diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for typst-hs
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2023, John MacFarlane
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of John MacFarlane nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Main where
+
+import Control.Monad (foldM, when)
+import qualified Data.ByteString as BS
+import Data.Maybe (fromMaybe)
+import qualified Data.Text.IO as TIO
+import System.Environment (getArgs)
+import System.Exit
+import System.IO (hPutStrLn, stderr)
+import System.Timeout (timeout)
+import Text.Read (readMaybe)
+import Text.Show.Pretty (pPrint)
+import Typst (evaluateTypst, parseTypst)
+import Typst.Types (Val (..), repr)
+
+data Opts = Opts
+  { optShowParse :: Bool,
+    optShowEval :: Bool,
+    optShowRepr :: Bool,
+    optShowLaTeX :: Bool,
+    optShowHtml :: Bool,
+    optStandalone :: Bool,
+    optTimeout :: Maybe (Maybe Int)
+  }
+  deriving (Show, Eq)
+
+err :: String -> IO a
+err msg = do
+  hPutStrLn stderr msg
+  exitWith (ExitFailure 1)
+
+parseArgs :: [String] -> IO (Maybe FilePath, Opts)
+parseArgs = foldM go (Nothing, Opts False False False False False False Nothing)
+  where
+    go (f, opts) "--parse" = pure (f, opts {optShowParse = True})
+    go (f, opts) "--eval" = pure (f, opts {optShowEval = True})
+    go (f, opts) "--repr" = pure (f, opts {optShowRepr = True})
+    go (f, opts) "--latex" = pure (f, opts {optShowLaTeX = True})
+    go (f, opts) "--html" = pure (f, opts {optShowHtml = True})
+    go (f, opts) "--standalone" = pure (f, opts {optStandalone = True})
+    go (f, opts) "--timeout" = pure (f, opts {optTimeout = Just Nothing })
+    go (f, opts) x
+      | optTimeout opts == Just Nothing =
+          pure (f, opts {optTimeout = Just (readMaybe x) })
+    go _ ('-' : xs) = err $ "Unknown option -" ++ xs
+    go (Nothing, opts) f = pure (Just f, opts)
+    go _ _ = err $ "Only one file can be specified as input."
+
+main :: IO ()
+main =
+  () <$ do
+    (mbfile, opts) <- getArgs >>= parseArgs
+    let showAll = case opts of
+          Opts False False False False False False _ -> True
+          _ -> False
+    ( case optTimeout opts of
+        Nothing -> fmap Just
+        Just Nothing -> timeout 1000
+        Just (Just ms) -> timeout (ms * 1000)
+      )
+      $ do
+        t <- maybe TIO.getContents TIO.readFile mbfile
+        case parseTypst (fromMaybe "stdin" mbfile) t of
+          Left e -> err $ show e
+          Right parseResult -> do
+            when (optShowParse opts || showAll) $ do
+              when showAll $ putStrLn "--- parse tree ---"
+              pPrint parseResult
+            result <- evaluateTypst BS.readFile "stdin" parseResult
+            case result of
+              Left e -> err $ show e
+              Right cs -> do
+                when (optShowEval opts || showAll) $ do
+                  when showAll $ putStrLn "--- evaluated ---"
+                  pPrint cs
+                when (optShowRepr opts || showAll) $ do
+                  when showAll $ putStrLn "--- repr ---"
+                  TIO.putStrLn $ repr $ VContent cs
+            exitSuccess
diff --git a/src/Typst.hs b/src/Typst.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst.hs
@@ -0,0 +1,12 @@
+module Typst
+  ( module Typst.Parse,
+    module Typst.Evaluate,
+    module Typst.Types,
+    module Typst.Syntax,
+  )
+where
+
+import Typst.Evaluate
+import Typst.Parse
+import Typst.Syntax
+import Typst.Types
diff --git a/src/Typst/Bind.hs b/src/Typst/Bind.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Bind.hs
@@ -0,0 +1,105 @@
+{-# LANGUAGE RankNTypes #-}
+
+module Typst.Bind (destructuringBind) where
+
+import Control.Monad.State
+import qualified Data.Map.Ordered as OM
+import Data.Maybe (fromMaybe)
+import qualified Data.Vector as V
+import Typst.Syntax
+import Typst.Types
+
+destructuringBind ::
+  Monad m =>
+  (forall m'. Monad m' => Identifier -> Val -> MP m' ()) ->
+  [BindPart] ->
+  Val ->
+  MP m ()
+destructuringBind setIdentifier parts val = do
+  let isSink Sink {} = True
+      isSink _ = False
+  let (fronts, rest) = break isSink parts
+  let (sinks, backs) = span isSink rest
+  mbsink <- case sinks of
+    [Sink s] -> pure s
+    [] -> pure Nothing
+    _ -> fail "Bind cannot contain multiple sinks"
+  case val of
+    VDict m ->
+      evalStateT (destructureDict setIdentifier fronts backs mbsink) m
+    VArray v ->
+      evalStateT (destructureArray setIdentifier fronts backs mbsink) v
+    _ -> fail "Only Array or Dictionary values can be destructured"
+
+destructureDict ::
+  Monad m =>
+  (forall m'. Monad m' => Identifier -> Val -> MP m' ()) ->
+  [BindPart] ->
+  [BindPart] ->
+  Maybe Identifier ->
+  StateT (OM.OMap Identifier Val) (MP m) ()
+destructureDict setIdentifier fronts backs mbsink = do
+  mapM_ handleDictBind (fronts ++ backs)
+  case mbsink of
+    Just i -> get >>= lift . setIdentifier i . VDict
+    Nothing -> pure ()
+  where
+    handleDictBind :: Monad m => BindPart -> StateT (OM.OMap Identifier Val) (MP m) ()
+    handleDictBind (Sink {}) = fail "Bind cannot contain multiple sinks"
+    handleDictBind (Simple Nothing) = pure ()
+    handleDictBind (Simple (Just i)) = do
+      m <- get
+      case OM.lookup i m of
+        Nothing ->
+          fail $ "Destructuring key not found in dictionary: " <> show i
+        Just v -> do
+          put $ OM.delete i m
+          lift $ setIdentifier i v
+    handleDictBind (WithKey key mbident) = do
+      m <- get
+      case OM.lookup key m of
+        Nothing ->
+          fail $ "Destructuring key not found in dictionary: " <> show key
+        Just v -> do
+          put $ OM.delete key m
+          lift $ setIdentifier (fromMaybe key mbident) v
+
+destructureArray ::
+  Monad m =>
+  (forall m'. Monad m' => Identifier -> Val -> MP m' ()) ->
+  [BindPart] ->
+  [BindPart] ->
+  Maybe Identifier ->
+  StateT (V.Vector Val) (MP m) ()
+destructureArray setIdentifier fronts backs mbsink = do
+  mapM_ handleFrontBind fronts
+  mapM_ handleBackBind (reverse backs)
+  case mbsink of
+    Just i -> get >>= lift . setIdentifier i . VArray
+    Nothing -> pure ()
+  where
+    handleFrontBind :: Monad m => BindPart -> StateT (V.Vector Val) (MP m) ()
+    handleFrontBind (Sink {}) = fail "Bind cannot contain multiple sinks"
+    handleFrontBind (WithKey {}) = fail "Cannot destructure array with key"
+    handleFrontBind (Simple mbi) = do
+      v <- get
+      case V.uncons v of
+        Nothing -> fail "Array does not contain enough elements to destructure"
+        Just (x, v') -> do
+          put v'
+          case mbi of
+            Nothing -> pure ()
+            Just i -> lift $ setIdentifier i x
+
+    handleBackBind :: Monad m => BindPart -> StateT (V.Vector Val) (MP m) ()
+    handleBackBind (Sink {}) = fail "Bind cannot contain multiple sinks"
+    handleBackBind (WithKey {}) = fail "Cannot destructure array with key"
+    handleBackBind (Simple mbi) = do
+      v <- get
+      case V.unsnoc v of
+        Nothing -> fail "Array does not contain enough elements to destructure"
+        Just (v', x) -> do
+          put v'
+          case mbi of
+            Nothing -> pure ()
+            Just i -> lift $ setIdentifier i x
diff --git a/src/Typst/Evaluate.hs b/src/Typst/Evaluate.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Evaluate.hs
@@ -0,0 +1,1054 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Typst.Evaluate
+  ( evaluateTypst,
+    valToContent,
+  )
+where
+
+import Control.Monad (MonadPlus (mplus), foldM, foldM_)
+import Control.Monad.State (MonadTrans (lift))
+import qualified Data.ByteString as BS
+import Data.List (intersperse, sortOn)
+import qualified Data.Map as M
+import qualified Data.Map.Ordered as OM
+import Data.Maybe (isJust)
+import Data.Sequence (Seq)
+import qualified Data.Sequence as Seq
+import qualified Data.Set as Set
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Vector as V
+import System.FilePath (replaceFileName, takeBaseName)
+import Text.Parsec
+import Typst.Bind (destructuringBind)
+import Typst.Methods (getMethod)
+import Typst.Module.Standard (loadFileText, standardModule)
+import Typst.Parse (parseTypst)
+import Typst.Regex (match)
+import Typst.Show (applyShowRules)
+import Typst.Syntax
+import Typst.Types
+import Typst.Util (makeFunction, nthArg)
+
+-- import Debug.Trace
+
+-- | Evaluate a parsed typst expression, evaluating the code and
+-- replacing it with content.
+evaluateTypst ::
+  Monad m =>
+  -- | Function to read a file
+  (FilePath -> m BS.ByteString) ->
+  -- | Path of parsed content
+  FilePath ->
+  -- | Markup produced by 'parseTypst'
+  [Markup] ->
+  m (Either ParseError (Seq Content))
+evaluateTypst loadBytes =
+  runParserT
+    (mconcat <$> many pContent <* eof)
+    initialEvalState {evalLoadBytes = loadBytes}
+
+initialEvalState :: EvalState m
+initialEvalState =
+  emptyEvalState { evalIdentifiers = [(BlockScope, standardModule')] }
+  where
+    standardModule' = M.insert "eval" evalFunction standardModule
+    evalFunction = makeFunction $ do
+      code :: Text <- nthArg 1
+      case parseTypst "eval" ("#{\n" <> code <> "\n}") of
+        Left e -> fail $ "eval: " <> show e
+        Right [Code _ expr] ->
+          -- run in Either monad so we can't access file system
+          case runParserT (evalExpr expr) initialEvalState "eval" [] of
+            Failure e -> fail $ "eval: " <> e
+            Success (Left e) -> fail $ "eval: " <> show e
+            Success (Right val) -> pure val
+        Right _ -> fail "eval: got something other than Code (should not happen)"
+
+satisfyTok :: Monad m => (Markup -> Bool) -> MP m Markup
+satisfyTok f = tokenPrim show showPos match'
+  where
+    showPos _oldpos (Code pos _) _ = pos
+    showPos oldpos _ _ = oldpos
+    match' x | f x = Just x
+    match' _ = Nothing
+
+pContent :: Monad m => MP m (Seq Content)
+pContent = (pTxt <|> pElt) >>= applyShowRules >>= addTextElement
+
+addTextElement :: Monad m => Seq Content -> MP m (Seq Content)
+addTextElement = foldM go mempty
+  where
+    go acc (Txt "") = pure acc
+    go acc (Txt t) = (acc <>) <$> element "text" (Arguments [VContent [Txt t]] OM.empty)
+    go acc x = pure (acc Seq.|> x)
+
+isText :: Markup -> Bool
+isText Text {} = True
+isText Space = True
+isText SoftBreak = True
+isText Nbsp = True
+isText Shy = True
+isText EmDash = True
+isText EnDash = True
+isText Ellipsis = True
+isText (Quote _) = True
+isText _ = False
+
+getText :: Markup -> Text
+getText (Text t) = t
+getText Space = " "
+getText SoftBreak = "\n"
+getText Nbsp = "\xa0"
+getText Shy = "\xad"
+getText EmDash = "\x2014"
+getText EnDash = "\x2013"
+getText Ellipsis = "\x2026"
+getText (Quote c) = T.singleton c -- TODO localize
+getText _ = ""
+
+pTxt :: Monad m => MP m (Seq Content)
+pTxt = do
+  mathMode <- evalMath <$> getState
+  txt <-
+    if mathMode
+      then getText <$> satisfyTok isText
+      else mconcat . map getText . setQuotes <$> many1 (satisfyTok isText)
+  pure $ Seq.singleton $ Txt txt
+
+setQuotes :: [Markup] -> [Markup]
+setQuotes [] = []
+setQuotes (Quote '"' : x : rest)
+  | x == Space || x == SoftBreak = Quote '\x201D' : setQuotes (x : rest)
+setQuotes (Quote '\'' : x : rest)
+  | x == Space || x == SoftBreak = Quote '\x201D' : setQuotes (x : rest)
+setQuotes (x : Quote '"' : rest)
+  | x == Space || x == SoftBreak = x : Quote '\x201C' : setQuotes rest
+setQuotes (x : Quote '\'' : rest)
+  | x == Space || x == SoftBreak = x : Quote '\x2018' : setQuotes rest
+setQuotes (Text t1 : Quote '\'' : Text t2 : rest) =
+  Text t1 : Quote '\x2019' : setQuotes (Text t2 : rest)
+setQuotes (Quote '"' : Text t : rest)
+  | t `notElem` ([")", ".", ",", ";", ":", "?", "!", "]"] :: [Text]) =
+      Quote '\x201C' : setQuotes (Text t : rest)
+setQuotes (Quote '\'' : Text t : rest)
+  | t `notElem` ([")", ".", ",", ";", ":", "?", "!", "]"] :: [Text]) =
+      Quote '\x2018' : setQuotes (Text t : rest)
+setQuotes (Quote '"' : rest) = Quote '\x201D' : setQuotes rest
+setQuotes (Quote '\'' : rest) = Quote '\x2019' : setQuotes rest
+setQuotes (x : xs) = x : setQuotes xs
+
+pInnerContents :: Monad m => [Markup] -> MP m (Seq Content)
+pInnerContents ms = do
+  oldInput <- getInput
+  oldPos <- getPosition
+  oldShowRules <- evalShowRules <$> getState
+  setInput ms
+  result <- mconcat <$> (many pContent <* eof)
+  setInput oldInput
+  setPosition oldPos
+  updateState $ \st -> st {evalShowRules = oldShowRules}
+  pure result
+
+single :: Content -> Seq Content
+single = Seq.singleton
+
+applyElementFunction :: Monad m => Identifier -> Function -> Arguments -> MP m Val
+applyElementFunction name (Function f) args = do
+  -- lookup styles set by "set" and apply them as defaults:
+  mbSty <- M.lookup name . evalStyles <$> getState
+  f $ maybe args (<> args) mbSty
+
+element :: Monad m => Identifier -> Arguments -> MP m (Seq Content)
+element name@(Identifier n) args = do
+  eltfn <- lookupIdentifier name
+  case eltfn of
+    VFunction Nothing _ (Function f) -> valToContent <$> f args
+    VFunction (Just i) _ (Function f) ->
+      valToContent <$> applyElementFunction i (Function f) args
+    _ -> fail $ T.unpack n <> " is not an element function"
+
+pElt :: Monad m => MP m (Seq Content)
+pElt = do
+  tok <- satisfyTok (not . isText)
+  case tok of
+    ParBreak -> element "parbreak" mempty
+    HardBreak -> element "linebreak" mempty
+    Comment -> pure mempty
+    Code pos expr -> setPosition pos *> pExpr expr
+    Emph ms -> do
+      body <- pInnerContents ms
+      element "emph" Arguments {positional = [VContent body], named = OM.empty}
+    Strong ms -> do
+      body <- pInnerContents ms
+      element "strong" Arguments {positional = [VContent body], named = OM.empty}
+    Bracketed ms -> do
+      body <- pInnerContents ms
+      pure $ (Txt "[" Seq.<| body) Seq.|> Txt "]"
+    RawBlock lang txt ->
+      element
+        "raw"
+        Arguments
+          { positional = [VString txt],
+            named =
+              OM.fromList
+                [ ("block", VBoolean True),
+                  ( "lang",
+                    if T.null lang
+                      then VNone
+                      else VString lang
+                  )
+                ]
+          }
+    RawInline txt -> do
+      element
+        "raw"
+        Arguments
+          { positional = [VString txt],
+            named =
+              OM.fromList
+                [ ("lang", VNone),
+                  ("block", VBoolean False)
+                ]
+          }
+    Heading level ms -> do
+      content <- pInnerContents ms
+      element
+        "heading"
+        Arguments
+          { positional = [VContent content],
+            named =
+              OM.fromList
+                [("level", VInteger (fromIntegral level))]
+          }
+    Equation display ms -> inBlock BlockScope $ do
+      VModule _ mathmod <- lookupIdentifier "math"
+      importModule mathmod
+      VModule _ symmod <- lookupIdentifier "sym"
+      importModule symmod
+      oldMath <- evalMath <$> getState
+      updateState $ \st -> st {evalMath = True}
+      content <- pInnerContents ms
+      updateState $ \st -> st {evalMath = oldMath}
+      element
+        "equation"
+        Arguments
+          { positional = [VContent content],
+            named =
+              OM.fromList
+                [ ("block", VBoolean display),
+                  ("numbering", VNone)
+                ]
+          }
+    MFrac numexp denexp -> do
+      let handleParens (MGroup (Just "(") (Just ")") xs) = MGroup Nothing Nothing xs
+          handleParens x = x
+      num <- pInnerContents [handleParens numexp]
+      den <- pInnerContents [handleParens denexp]
+      element
+        "frac"
+        Arguments
+          { positional = [VContent num, VContent den],
+            named = OM.empty
+          }
+    MAttach mbBottomExp mbTopExp baseExp -> do
+      base <- pInnerContents [baseExp]
+      mbBottom <-
+        maybe
+          (pure Nothing)
+          (fmap Just . pInnerContents . (: []))
+          mbBottomExp
+      mbTop <-
+        maybe
+          (pure Nothing)
+          (fmap Just . pInnerContents . (: []))
+          mbTopExp
+      element
+        "attach"
+        Arguments
+          { positional = [VContent base],
+            named =
+              OM.fromList
+                [ ("b", maybe VNone VContent mbBottom),
+                  ("t", maybe VNone VContent mbTop)
+                ]
+          }
+    MGroup mbOp mbCl ms -> wrapIn mbOp mbCl <$> pInnerContents ms
+    MAlignPoint -> element "alignpoint" mempty
+    Ref ident supp -> do
+      supp' <- evalExpr supp
+      element
+        "ref"
+        Arguments
+          { positional = [VLabel ident],
+            named =
+              OM.fromList
+                [ ( "supplement", supp' ) ]
+          }
+    BulletListItem ms -> do
+      skipMany $ satisfyTok isBreak
+      firstItem <- pInnerContents ms
+      -- parse a sequence of list items and put them in a list element
+      items <- (firstItem :) <$> many pListItem
+      element
+        "list"
+        Arguments
+          { positional = map VContent items,
+            named = OM.empty
+          }
+    EnumListItem mbStart ms -> do
+      skipMany $ satisfyTok isBreak
+      firstItem <- pInnerContents ms
+      -- parse a sequence of list items and put them in a list element
+      items <- (firstItem :) <$> many pEnumItem
+      element
+        "enum"
+        Arguments
+          { positional = map VContent items,
+            named =
+              maybe
+                OM.empty
+                ( \x ->
+                    OM.fromList
+                      [("start", VInteger (fromIntegral x))]
+                )
+                mbStart
+          }
+    DescListItem ts ds -> do
+      ts' <- pInnerContents ts
+      ds' <- pInnerContents ds
+      skipMany (satisfyTok isBreak)
+      let firstItem = VArray [VContent ts', VContent ds']
+      items <- (firstItem :) <$> many pDescItem
+      element
+        "terms"
+        Arguments
+          { positional = items,
+            named = OM.empty
+          }
+    Url t ->
+      element
+        "link"
+        Arguments
+          { positional =
+              [ VString t,
+                VContent (Seq.singleton (Txt t))
+              ],
+            named = OM.empty
+          }
+    _ -> fail $ "Encountered " <> show tok <> " in pElt"
+
+pDescItem :: Monad m => MP m Val
+pDescItem = do
+  tok <- satisfyTok isDescListItem
+  case tok of
+    DescListItem ts ds -> do
+      ts' <- pInnerContents ts
+      ds' <- pInnerContents ds
+      skipMany (satisfyTok isBreak)
+      pure $ VArray [VContent ts', VContent ds']
+    _ -> fail "pDescItem encountered non DescListItem"
+  where
+    isDescListItem DescListItem {} = True
+    isDescListItem _ = False
+
+pEnumItem :: Monad m => MP m (Seq Content)
+pEnumItem = do
+  tok <- satisfyTok isEnumListItem
+  case tok of
+    EnumListItem _ ms -> pInnerContents ms <* skipMany (satisfyTok isBreak)
+    _ -> fail "pEnumItem encountered non EnumListItem"
+  where
+    isEnumListItem EnumListItem {} = True
+    isEnumListItem _ = False
+
+pListItem :: Monad m => MP m (Seq Content)
+pListItem = do
+  tok <- satisfyTok isBulletListItem
+  case tok of
+    BulletListItem ms -> pInnerContents ms <* skipMany (satisfyTok isBreak)
+    _ -> fail "pListItem encountered non BulletListItem"
+  where
+    isBulletListItem BulletListItem {} = True
+    isBulletListItem _ = False
+
+isBreak :: Markup -> Bool
+isBreak SoftBreak = True
+isBreak ParBreak = True
+isBreak _ = False
+
+wrapIn :: Maybe Text -> Maybe Text -> Seq Content -> Seq Content
+wrapIn Nothing Nothing cs = cs
+wrapIn (Just op) (Just cl) cs =
+  Seq.singleton $
+    Elt
+      "math.lr"
+      Nothing
+      [ ( "body",
+          VArray $
+            V.fromList
+              [VContent $ Txt op Seq.<| (cs Seq.|> Txt cl)]
+        )
+      ]
+wrapIn Nothing (Just cl) cs = cs Seq.|> Txt cl
+wrapIn (Just op) Nothing cs = Txt op Seq.<| cs
+
+pExpr :: Monad m => Expr -> MP m (Seq Content)
+pExpr expr = valToContent <$> evalExpr expr
+
+evalExpr :: Monad m => Expr -> MP m Val
+evalExpr expr =
+  case expr of
+    Literal lit -> pure $ evalLiteral lit
+    Group e -> evalExpr e
+    Block (Content ms) -> VContent <$> pInnerContents ms
+    Block (CodeBlock exprs) ->
+      inBlock BlockScope $
+        -- let, etc. inside block are isolated
+        -- we concat the results inside the block
+        fst
+          <$> foldM
+            ( \(result, finished) e ->
+                if finished
+                  then pure (result, finished)
+                  else do
+                    updateState $ \st -> st {evalFlowDirective = FlowNormal}
+                    val <- evalExpr e
+                    flow <- evalFlowDirective <$> getState
+                    case flow of
+                      FlowNormal -> do
+                        combined <- joinVals result val
+                        pure (combined, False)
+                      FlowContinue -> do
+                        combined <- joinVals result val
+                        pure (combined, True)
+                      FlowBreak -> do
+                        combined <- joinVals result val
+                        pure (combined, True)
+                      FlowReturn True -> pure (val, True)
+                      FlowReturn False -> do
+                        combined <- joinVals result val
+                        pure (combined, True)
+            )
+            (VNone, False)
+            exprs
+    Array e -> VArray . V.fromList <$> mapM evalExpr e
+    Dict items ->
+      VDict
+        <$> foldM
+          ( \m (k, e) -> do
+              val <- evalExpr e
+              pure $ m OM.|> (k, val)
+          )
+          OM.empty
+          items
+    Not e -> do
+      val <- evalExpr e
+      case val of
+        VBoolean b -> pure $ VBoolean (not b)
+        _ -> fail $ "Cannot apply 'not' to " <> show val
+    And e1 e2 -> do
+      val1 <- evalExpr e1
+      case val1 of
+        VBoolean False -> pure $ VBoolean False
+        VBoolean True -> do
+          val2 <- evalExpr e2
+          case val2 of
+            VBoolean True -> pure $ VBoolean True
+            VBoolean False -> pure $ VBoolean False
+            _ -> fail $ "Cannot apply 'and' to " <> show val1
+        _ -> fail $ "Cannot apply 'and' to " <> show val1
+    Or e1 e2 -> do
+      val1 <- evalExpr e1
+      case val1 of
+        VBoolean True -> pure $ VBoolean True
+        VBoolean False -> do
+          val2 <- evalExpr e2
+          case val2 of
+            VBoolean True -> pure $ VBoolean True
+            VBoolean False -> pure $ VBoolean False
+            _ -> fail $ "Cannot apply 'or' to " <> show val1
+        _ -> fail $ "Cannot apply 'or' to " <> show val1
+    Ident ident -> lookupIdentifier ident
+    Let bind e -> do
+      val <- evalExpr e
+      case bind of
+        BasicBind (Just ident) -> addIdentifier ident val
+        BasicBind Nothing -> pure ()
+        DestructuringBind parts -> destructuringBind addIdentifier parts val
+      pure VNone
+    LetFunc name params e -> do
+      val <- toFunction (Just name) params e
+      addIdentifier name val
+      pure VNone
+    FieldAccess (Ident (Identifier fld)) e -> do
+      val <- evalExpr e
+      getMethod (updateExpression e) val fld
+        <|> case val of
+          VSymbol (Symbol _ accent variants) -> do
+            let variants' =
+                  sortOn (Set.size . fst) $
+                    filter (\(var, _) -> fld `Set.member` var) variants
+            case variants' of
+              [] -> fail $ "Symbol does not have variant " <> show fld
+              ((_, s) : _) -> pure $ VSymbol $ Symbol s accent variants'
+          VModule _ m ->
+            case M.lookup (Identifier fld) m of
+              Just x -> pure x
+              Nothing -> fail $ "Module does not contain " <> show fld
+          VFunction _ m _ ->
+            case M.lookup (Identifier fld) m of
+              Just x -> pure x
+              Nothing -> fail $ "Function scope does not contain " <> show fld
+          VDict m ->
+            case OM.lookup (Identifier fld) m of
+              Just x -> pure x
+              Nothing -> fail $ show (Identifier fld) <> " not found"
+          _ -> fail "FieldAccess requires a dictionary"
+    FieldAccess _ _ -> fail "FieldAccess requires an identifier"
+    FuncCall e args -> do
+      updateState $ \st -> st {evalFlowDirective = FlowNormal}
+      val <- evalExpr e
+      mathMode <- evalMath <$> getState
+      case val of
+        VFunction (Just i) _ (Function f) -> do
+          arguments <- toArguments args
+          applyElementFunction i (Function f) arguments
+        VFunction Nothing _ (Function f) -> toArguments args >>= f
+        VSymbol (Symbol _ True _) | mathMode ->
+          do
+            val' <- lookupIdentifier "accent"
+            case val' of
+              VFunction _ _ (Function f) ->
+                toArguments args
+                  >>= f . (\a -> a {positional = positional a ++ [val]})
+              _ -> fail "accent not defined"
+        _
+          | mathMode -> do
+              args' <- toArguments args
+              pure $
+                VContent $
+                  valToContent val
+                    <> single "("
+                    <> mconcat
+                      ( intersperse
+                          (single ",")
+                          (map valToContent (positional args'))
+                      )
+                    <> single ")"
+          | otherwise -> fail "Attempt to call a non-function"
+    FuncExpr params e -> toFunction Nothing params e
+    Equals e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case comp v1 v2 of
+        Just EQ -> pure $ VBoolean True
+        _ -> pure $ VBoolean False
+    LessThan e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case comp v1 v2 of
+        Nothing -> fail $ "Can't compare " <> show v1 <> " and " <> show v2
+        Just LT -> pure $ VBoolean True
+        _ -> pure $ VBoolean False
+    GreaterThan e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case comp v1 v2 of
+        Nothing -> fail $ "Can't compare " <> show v1 <> " and " <> show v2
+        Just GT -> pure $ VBoolean True
+        _ -> pure $ VBoolean False
+    LessThanOrEqual e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case comp v1 v2 of
+        Nothing -> fail $ "Can't compare " <> show e1 <> " and " <> show e2
+        Just LT -> pure $ VBoolean True
+        Just EQ -> pure $ VBoolean True
+        _ -> pure $ VBoolean False
+    GreaterThanOrEqual e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case comp v1 v2 of
+        Nothing -> fail $ "Can't compare " <> show v1 <> " and " <> show v2
+        Just GT -> pure $ VBoolean True
+        Just EQ -> pure $ VBoolean True
+        _ -> pure $ VBoolean False
+    InCollection e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case v2 of
+        VString t ->
+          case v1 of
+            VString t' -> pure $ VBoolean $ t' `T.isInfixOf` t
+            VRegex re -> pure $ VBoolean $ match re t
+            _ -> fail $ "Can't apply 'in' to " <> show v1 <> " and string"
+        VArray vec -> pure $ VBoolean $ V.elem v1 vec
+        VDict m ->
+          case v1 of
+            VString t -> pure $ VBoolean $ isJust $ OM.lookup (Identifier t) m
+            _ -> pure $ VBoolean False
+        _ -> fail $ "Can't apply 'in' to " <> show v2
+    Negated e -> do
+      v <- evalExpr e
+      case maybeNegate v of
+        Nothing -> fail $ "Can't negate " <> show v
+        Just v' -> pure v'
+    ToPower e1 e2 -> do
+      e <- evalExpr e1
+      b <- evalExpr e2
+      case (b, e) of
+        (VInteger i, VInteger j) ->
+          pure $
+            VInteger $
+              floor ((fromIntegral i :: Double) ** (fromIntegral j :: Double))
+        (VInteger i, VRatio j) ->
+          pure $
+            VFloat ((fromIntegral i :: Double) ** (fromRational j :: Double))
+        (VRatio i, VInteger j) ->
+          pure $
+            VFloat (fromRational i ** (fromIntegral j :: Double))
+        (VRatio i, VRatio j) -> pure $ VFloat (fromRational i ** fromRational j)
+        (VFloat i, VInteger j) -> pure $ VFloat (i ** (fromIntegral j :: Double))
+        (VFloat i, VFloat j) -> pure $ VFloat (i ** j)
+        (VInteger i, VFloat j) -> pure $ VFloat ((fromIntegral i :: Double) ** j)
+        (VFloat i, VRatio j) -> pure $ VFloat (i ** fromRational j)
+        _ -> fail $ "Can't exponentiate " <> show b <> " to " <> show e
+    Plus e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case (v1, v2) of
+        (VAlignment x1 y1, VAlignment x2 y2) ->
+          pure $ VAlignment (x1 `mplus` x2) (y1 `mplus` y2)
+        _ -> case maybePlus v1 v2 of
+          Nothing -> fail $ "Can't + " <> show v1 <> " and " <> show v2
+          Just v -> pure v
+    Minus e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case maybeMinus v1 v2 of
+        Nothing -> fail $ "Can't - " <> show v1 <> " and " <> show v2
+        Just v -> pure v
+    Times e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case maybeTimes v1 v2 of
+        Nothing -> fail $ "Can't * " <> show v1 <> " and " <> show v2
+        Just v -> pure v
+    Divided e1 e2 -> do
+      v1 <- evalExpr e1
+      v2 <- evalExpr e2
+      case maybeDividedBy v1 v2 of
+        Nothing -> fail $ "Can't / " <> show v1 <> " and " <> show v2
+        Just v -> pure v
+    Set e args -> do
+      v <- evalExpr e
+      as' <- toArguments args
+      case v of
+        VFunction (Just name) _ _ ->
+          updateState $ \st ->
+            st
+              { evalStyles =
+                  M.alter
+                    ( \case
+                        Nothing -> Just as'
+                        Just as'' -> Just (as'' <> as')
+                    )
+                    name
+                    $ evalStyles st
+              }
+        _ -> fail $ "Set expects an element name"
+      pure VNone
+    Show mbSelExpr e -> do
+      renderVal <- inBlock FunctionScope $ evalExpr e
+      case mbSelExpr of
+        Nothing -> do
+          rest <- mconcat <$> (many pContent <* eof)
+          case renderVal of
+            VFunction _ _ (Function f) ->
+              VContent . valToContent
+                <$> f Arguments {positional = [VContent rest], named = OM.empty}
+            _ -> pure $ VContent $ valToContent renderVal
+        Just selExpr -> do
+          selector <- evalExpr selExpr >>= toSelector
+          case renderVal of
+            VFunction _ _ (Function f) ->
+              updateState $ \st ->
+                st
+                  { evalShowRules =
+                      ShowRule
+                        selector
+                        ( \c ->
+                            valToContent
+                              <$> f
+                                Arguments
+                                  { positional = [VContent (Seq.singleton c)],
+                                    named = OM.empty
+                                  }
+                        )
+                        : evalShowRules st
+                  }
+            _ -> updateState $ \st ->
+              st
+                { evalShowRules =
+                    ShowRule
+                      selector
+                      ( \c ->
+                          case e of
+                            -- ignore show set for now TODO
+                            Set _ _ -> pure $ Seq.singleton c
+                            _ -> pure (valToContent renderVal)
+                      )
+                      : evalShowRules st
+                }
+          pure VNone
+    Binding _ -> fail $ "Encountered binding out of proper context"
+    Assign e1 e2 -> do
+      val <- evalExpr e2
+      case e1 of
+        Binding (BasicBind (Just ident)) -> updateIdentifier ident val
+        Binding (BasicBind Nothing) -> pure ()
+        Binding (DestructuringBind parts) ->
+          destructuringBind updateIdentifier parts val
+        x -> updateExpression x val
+      pure VNone
+    If clauses -> do
+      let go [] = pure VNone
+          go ((cond, e) : rest) = do
+            val <- evalExpr cond
+            case val of
+              VBoolean True -> evalExpr e
+              VBoolean False -> go rest
+              _ -> fail "If requires a boolean condition"
+      go clauses
+    While e1 e2 -> do
+      let go result = do
+            condval <- evalExpr e1
+            case condval of
+              VBoolean True -> do
+                val <- evalExpr e2
+                hadBreak <- (== FlowBreak) . evalFlowDirective <$> getState
+                joinVals result val >>= if hadBreak then pure else go
+              VBoolean False -> pure result
+              _ -> fail "While loop requires a boolean condition"
+      updateState $ \st -> st {evalFlowDirective = FlowNormal}
+      go VNone
+    For bind e1 e2 -> do
+      let go [] result = pure result
+          go (x : xs) result = do
+            case bind of
+              BasicBind (Just ident) -> addIdentifier ident x
+              BasicBind Nothing -> pure ()
+              DestructuringBind parts ->
+                destructuringBind addIdentifier parts x
+            val <- evalExpr e2
+            hadBreak <- (== FlowBreak) . evalFlowDirective <$> getState
+            joinVals result val >>= if hadBreak then pure else go xs
+      source <- evalExpr e1
+      items <- case source of
+        VString t -> pure $ map (VString . T.singleton) (T.unpack t)
+        VArray v -> pure $ V.toList v
+        VDict m ->
+          pure $
+            map
+              ( \(Identifier k, v) ->
+                  VArray (V.fromList [VString k, v])
+              )
+              (OM.assocs m)
+        _ -> fail $ "For expression requires an Array or Dictionary"
+      updateState $ \st -> st {evalFlowDirective = FlowNormal}
+      go items VNone
+    Return mbe -> do
+      -- these flow directives are examined in CodeBlock
+      updateState (\st -> st {evalFlowDirective = FlowReturn (isJust mbe)})
+      maybe (pure VNone) evalExpr mbe
+    Continue -> do
+      updateState (\st -> st {evalFlowDirective = FlowContinue})
+      pure VNone
+    Break -> do
+      updateState (\st -> st {evalFlowDirective = FlowBreak})
+      pure VNone
+    Label t -> pure $ VLabel t
+    Import e imports -> do
+      argval <- evalExpr e
+      (modid, modmap) <-
+        case argval of
+          VString t -> loadModule t
+          VModule i m -> pure (i, m)
+          VFunction (Just i) m _ -> pure (i, m)
+          VFunction Nothing m _ -> pure ("anonymous", m)
+          _ -> fail "Import requires a path or module or function"
+      case imports of
+        AllIdentifiers -> importModule modmap
+        SomeIdentifiers idents -> do
+          let addFromModule m ident =
+                case M.lookup ident modmap of
+                  Nothing -> fail $ show ident <> " not defined in module"
+                  Just v -> pure $ M.insert ident v m
+          foldM addFromModule mempty idents >>= importModule
+        NoIdentifiers -> addIdentifier modid (VModule modid modmap)
+      pure VNone
+    Include e -> do
+      argval <- evalExpr e
+      case argval of
+        VString t -> loadModule t >>= importModule . snd
+        _ -> fail "Include requires a path"
+      pure VNone
+
+toFunction ::
+  Monad m =>
+  Maybe Identifier ->
+  [Param] ->
+  Expr ->
+  MP m Val
+toFunction mbname params e = do
+  idents <- evalIdentifiers <$> getState
+  let fn = VFunction Nothing mempty $ Function $ \arguments -> do
+        -- set identifiers from params and arguments
+        let showIdentifier (Identifier i) = T.unpack i
+        let isSinkParam (SinkParam {}) = True
+            isSinkParam _ = False
+        let setParam as (DefaultParam ident e') = do
+              val <- case OM.lookup ident (named as) of
+                Nothing -> evalExpr e'
+                Just v -> pure v
+              addIdentifier ident val
+              pure $ as {named = OM.delete ident (named as)}
+            setParam as (NormalParam ident) = do
+              case positional as of
+                [] -> fail ("Expected parameter " <> showIdentifier ident)
+                (x : xs) -> do
+                  addIdentifier ident x
+                  pure $ as {positional = xs}
+            setParam _ (SinkParam {}) =
+              fail "setParam encountered SinkParam"
+            setParam as (DestructuringParam parts) =
+              case positional as of
+                [] -> fail ("Expected parameter " <> show parts)
+                (x : xs) -> do
+                  destructuringBind addIdentifier parts x
+                  pure $ as {positional = xs}
+            setParam as SkipParam = pure as
+        inBlock FunctionScope $ do
+          -- We create a closure around the identifiers defined
+          -- where the function is defined:
+          oldState <- getState
+          updateState $ \st -> st {evalIdentifiers = idents}
+          case mbname of
+            Nothing -> pure ()
+            Just name -> addIdentifier name fn
+          case break isSinkParam params of
+            (befores, SinkParam mbident : afters) -> do
+              as' <- foldM setParam arguments befores
+              as'' <-
+                foldM
+                  setParam
+                  as' {positional = reverse $ positional as'}
+                  (reverse afters)
+              let as = as'' {positional = reverse $ positional as''}
+              case mbident of
+                Just ident -> addIdentifier ident (VArguments as)
+                Nothing -> pure ()
+            _ -> foldM_ setParam arguments params
+          res <- evalExpr e
+          setState oldState
+          pure res
+  pure fn
+
+loadModule :: Monad m => Text -> MP m (Identifier, M.Map Identifier Val)
+loadModule modname = do
+  pos <- getPosition
+  let fp = replaceFileName (sourceName pos) (T.unpack modname)
+  let modid = Identifier (T.pack $ takeBaseName fp)
+  txt <- loadFileText fp
+  case parseTypst fp txt of
+    Left err -> fail $ show err
+    Right ms -> do
+      loadBytes <- evalLoadBytes <$> getState
+      res <-
+        lift $
+          runParserT
+            ( inBlock BlockScope $ -- add new identifiers list
+                many pContent *> eof *> getState
+            )
+            initialEvalState {evalLoadBytes = loadBytes}
+            fp
+            ms
+      case res of
+        Left err' -> fail $ show err'
+        Right st ->
+          case evalIdentifiers st of
+            [] -> fail "Empty evalIdentifiers in module!"
+            ((_, m) : _) -> pure (modid, m)
+
+importModule :: Monad m => M.Map Identifier Val -> MP m ()
+importModule m = updateState $ \st ->
+  st
+    { evalIdentifiers =
+        case evalIdentifiers st of
+          [] -> [(BlockScope, m)]
+          ((s, i) : is) -> (s, m <> i) : is
+    }
+
+evalLiteral :: Literal -> Val
+evalLiteral lit =
+  case lit of
+    String t -> VString t
+    Boolean b -> VBoolean b
+    Float x -> VFloat x
+    Int i -> VInteger i
+    Numeric x unit ->
+      case unit of
+        Fr -> VFraction x
+        Percent -> VRatio (toRational x / 100)
+        Deg -> VAngle x
+        Rad -> VAngle (x * (180 / pi))
+        Pt -> VLength (LExact x LPt)
+        Em -> VLength (LExact x LEm)
+        Mm -> VLength (LExact x LMm)
+        Cm -> VLength (LExact x LCm)
+        In -> VLength (LExact x LIn)
+    None -> VNone
+    Auto -> VAuto
+
+toArguments :: Monad m => [Arg] -> MP m Arguments
+toArguments = foldM addArg (Arguments mempty OM.empty)
+  where
+    addArg args (KeyValArg ident e) = do
+      val <- evalExpr e
+      pure $ args {named = named args OM.|> (ident, val)}
+    addArg args (NormalArg e) = do
+      val <- evalExpr e
+      pure $ args {positional = positional args ++ [val]}
+    addArg args (ArrayArg rows) = do
+      let pRow =
+            fmap (VArray . V.fromList)
+              . mapM (fmap VContent . pInnerContents . (: []))
+      vals <- mapM pRow rows
+      pure $ args {positional = positional args ++ vals}
+    addArg args (SpreadArg e) = do
+      val <- evalExpr e
+      case val of
+        VNone -> pure mempty
+        VArguments args' -> pure $ args <> args'
+        VDict m ->
+          pure $
+            args
+              <> Arguments {positional = mempty, named = m}
+        VArray v ->
+          pure $
+            args
+              <> Arguments {positional = V.toList v, named = OM.empty}
+        _ -> fail $ "spread requires an argument value, got " <> show val
+    addArg args (BlockArg ms) = do
+      val <- pInnerContents ms
+      pure $ args {positional = positional args ++ [VContent val]}
+
+addIdentifier :: Monad m => Identifier -> Val -> MP m ()
+addIdentifier ident val = do
+  identifiers <- evalIdentifiers <$> getState
+  case identifiers of
+    [] -> fail "Empty evalIdentifiers"
+    ((s, i) : is) -> updateState $ \st ->
+      st
+        { evalIdentifiers = (s, M.insert ident val i) : is
+        }
+
+updateIdentifier :: Monad m => Identifier -> Val -> MP m ()
+updateIdentifier ident val = do
+  let go (True, is) (s, m) = pure (True, (s, m) : is)
+      go (False, is) (s, m) =
+        case M.lookup ident m of
+          Nothing
+            | s == FunctionScope -> fail $ show ident <> " not defined in scope"
+            | otherwise -> pure (False, (s, m) : is)
+          Just _ -> pure (True, (s, M.adjust (const val) ident m) : is)
+  (finished, newmaps) <- getState >>= foldM go (False, []) . evalIdentifiers
+  if finished
+    then updateState $ \st -> st {evalIdentifiers = reverse newmaps}
+    else fail $ show ident <> " not defined"
+
+inBlock :: Monad m => Scope -> MP m a -> MP m a
+inBlock scope pa = do
+  oldStyles <- evalStyles <$> getState
+  -- add a new identifiers map
+  updateState $ \st ->
+    st
+      { evalIdentifiers = (scope, mempty) : evalIdentifiers st
+      }
+  result <- pa
+  updateState $ \st ->
+    st
+      { evalIdentifiers = drop 1 (evalIdentifiers st),
+        evalStyles = oldStyles
+      }
+  pure result
+
+updateExpression :: Monad m => Expr -> Val -> MP m ()
+updateExpression e val =
+  case e of
+    Ident i -> updateIdentifier i val
+    FuncCall
+      (FieldAccess (Ident (Identifier "at")) e')
+      [NormalArg (Literal (Int idx))] ->
+        do
+          ival <- evalExpr e'
+          case ival of
+            VArray v ->
+              updateExpression e' $ VArray $ v V.// [(fromIntegral idx, val)]
+            _ -> fail $ "Cannot update expression " <> show e
+    FuncCall (FieldAccess (Ident (Identifier "first")) e') [] ->
+      updateExpression
+        ( FuncCall
+            (FieldAccess (Ident (Identifier "at")) e')
+            [NormalArg (Literal (Int 0))]
+        )
+        val
+    FuncCall (FieldAccess (Ident (Identifier "last")) e') [] ->
+      updateExpression
+        ( FuncCall
+            (FieldAccess (Ident (Identifier "at")) e')
+            [NormalArg (Literal (Int (-1)))]
+        )
+        val
+    FuncCall
+      (FieldAccess (Ident (Identifier "at")) e')
+      [NormalArg (Literal (String fld))] ->
+        do
+          ival <- evalExpr e'
+          case ival of
+            VDict d ->
+              updateExpression e' $
+                VDict $
+                  OM.alter
+                    ( \case
+                        Just _ -> Just val
+                        Nothing -> Just val
+                    )
+                    (Identifier fld)
+                    d
+            _ -> fail $ "Cannot update expression " <> show e
+    FieldAccess (Ident (Identifier fld)) e' ->
+      updateExpression
+        ( FuncCall
+            (FieldAccess (Ident (Identifier "at")) e')
+            [NormalArg (Literal (String fld))]
+        )
+        val
+    _ -> fail $ "Cannot update expression " <> show e
+
+toSelector :: Monad m => Val -> MP m Selector
+toSelector (VSelector s) = pure s
+toSelector (VFunction (Just name) _ _) = pure $ SelectElement name []
+toSelector (VString t) = pure $ SelectString t
+toSelector (VRegex re) = pure $ SelectRegex re
+toSelector (VLabel t) = pure $ SelectLabel t
+toSelector (VSymbol (Symbol t _ _)) = pure $ SelectString t
+toSelector v = fail $ "could not convert " <> show v <> " to selector"
diff --git a/src/Typst/Methods.hs b/src/Typst/Methods.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Methods.hs
@@ -0,0 +1,666 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+
+module Typst.Methods
+  ( getMethod,
+    applyPureFunction,
+    formatNumber,
+  )
+where
+
+import Control.Monad (MonadPlus (mplus), foldM)
+import Control.Monad.Reader (MonadReader (ask), MonadTrans (lift))
+import qualified Data.Array as Array
+import qualified Data.Foldable as F
+import Data.List (intersperse, sort, sortOn)
+import qualified Data.Map as M
+import qualified Data.Map.Ordered as OM
+import Data.Maybe (fromMaybe)
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Vector as V
+import Text.Parsec (getState, runParserT, updateState)
+import Typst.Module.Standard (standardModule)
+import Typst.Regex
+  ( RE (..),
+    RegexMatch (..),
+    extract,
+    makeRE,
+    match,
+    matchAll,
+    replaceRegex,
+    splitRegex,
+  )
+import Typst.Types
+import Typst.Util (allArgs, makeFunction, namedArg, nthArg)
+
+-- import Debug.Trace
+
+getMethod ::
+  MonadFail m =>
+  (forall n. Monad n => Val -> MP n ()) ->
+  Val ->
+  Text ->
+  m Val
+getMethod updateVal val fld = do
+  let methodUnimplemented name =
+        fail $
+          "Method "
+            <> show name
+            <> " is not yet implemented"
+  let noMethod typename name =
+        fail $
+          typename
+            <> " does not have a method "
+            <> show name
+  case val of
+    VDict m ->
+      case fld of
+        "len" ->
+          pure $ makeFunction $ pure $ VInteger (fromIntegral $ OM.size m)
+        "at" ->
+          pure $ makeFunction $ do
+            key <- nthArg 1
+            defval <- namedArg "default" `mplus` pure VNone
+            case OM.lookup (Identifier key) m of
+              Nothing -> pure defval
+              Just v -> pure v
+        "insert" ->
+          pure $ makeFunction $ do
+            key <- nthArg 1
+            v <- nthArg 2
+            lift $ updateVal $ VDict $ m OM.|> (Identifier key, v)
+            pure v
+        "keys" ->
+          pure $
+            makeFunction $
+              pure $
+                VArray $
+                  V.fromList $
+                    map (\(Identifier t, _) -> VString t) $
+                      OM.assocs m
+        "values" ->
+          pure $ makeFunction $ pure $ VArray $ V.fromList $ map snd $ OM.assocs m
+        "pairs" ->
+          pure $ makeFunction $ do
+            pure $
+              VArray $
+                V.fromList $
+                  map
+                    ( \(Identifier k, v) ->
+                        VArray (V.fromList [VString k, v])
+                    )
+                    (OM.assocs m)
+        "remove" ->
+          pure $ makeFunction $ do
+            key <- nthArg 1
+            case OM.lookup (Identifier key) m of
+              Nothing -> pure VNone
+              Just oldval -> do
+                lift $ updateVal $ VDict $ OM.delete (Identifier key) m
+                pure oldval
+        _ -> case OM.lookup (Identifier fld) m of
+          Just x -> pure x
+          Nothing -> fail $ show (Identifier fld) <> " not found"
+    VColor col ->
+      case fld of
+        "darken" -> pure $ makeFunction $ do
+          (n :: Rational) <- nthArg 1
+          pure $ VColor $ case col of
+            RGB r g b o -> RGB (r * (1 - n)) (g * (1 - n)) (b * (1 - n)) o
+            CMYK c m y k -> CMYK (c * (1 - n)) (m * (1 - n)) (y * (1 - n)) (k * (1 - n))
+            Luma x -> Luma (x * (1 - n))
+        "lighten" -> pure $ makeFunction $ do
+          (n :: Rational) <- nthArg 1
+          pure $ VColor $ case col of
+            RGB r g b o ->
+              RGB
+                (r + ((1 - r) * n))
+                (g + ((1 - g) * n))
+                (b + ((1 - b) * n))
+                o
+            CMYK c m y k ->
+              CMYK
+                (c + ((1 - c) * n))
+                (m + ((1 - m) * n))
+                (y + ((1 - y) * n))
+                (k + ((1 - k) * n))
+            Luma x -> Luma (x + ((1 - x) * n))
+        "negate" -> pure $ makeFunction $ do
+          pure $ VColor $ case col of
+            RGB r g b o -> RGB (1 - r) (1 - g) (1 - b) o
+            CMYK c m y k -> CMYK (1 - c) (1 - m) (1 - y) k
+            Luma x -> Luma (1 - x)
+        _ -> noMethod "Color" fld
+    VString t -> do
+      let toPos n =
+            if n < 0
+              then T.length t + n
+              else n
+      case fld of
+        "len" ->
+          pure $ makeFunction $ pure $ VInteger (fromIntegral $ T.length t)
+        "first" ->
+          if T.null t
+            then fail "string is empty"
+            else pure $ makeFunction $ pure $ VString $ T.take 1 t
+        "last" ->
+          if T.null t
+            then fail "string is empty"
+            else pure $ makeFunction $ pure $ VString $ T.takeEnd 1 t
+        "at" ->
+          pure $ makeFunction $ do
+            n <- toPos <$> nthArg 1
+            pure $ VString $ T.take 1 $ T.drop n t
+        "slice" ->
+          pure $ makeFunction $ do
+            start <- toPos <$> nthArg 1
+            end <-
+              (toPos <$> nthArg 2)
+                `mplus` ((+ start) <$> namedArg "count")
+                `mplus` pure (T.length t)
+            if end < start
+              then pure $ VString ""
+              else pure $ VString $ T.take (end - start) $ T.drop start t
+        "clusters" -> pure $ makeFunction $ do
+          -- TODO this isn't right, but we'd need fancier libraries
+          -- to get at grapheme clusters
+          pure $ VArray $ V.fromList $ map VString $ T.chunksOf 1 t
+        "codepoints" -> pure $ makeFunction $ do
+          pure $ VArray $ V.fromList $ map VString $ T.chunksOf 1 t
+        "contains" -> pure $ makeFunction $ do
+          (patt :: RE) <- nthArg 1
+          pure $ VBoolean $ match patt t
+        "starts-with" -> pure $ makeFunction $ do
+          (RE reStr _) <- nthArg 1
+          patt <- makeRE ("^" <> reStr)
+          pure $ VBoolean $ match patt t
+        "ends-with" -> pure $ makeFunction $ do
+          (RE reStr _) <- nthArg 1
+          patt <- makeRE (reStr <> "$")
+          pure $ VBoolean $ match patt t
+        "find" -> pure $ makeFunction $ do
+          (patt :: RE) <- nthArg 1
+          pure $
+            let ((_, m, _) :: (Text, Text, Text)) = match patt t
+             in VString m
+        "position" -> pure $ makeFunction $ do
+          (patt :: RE) <- nthArg 1
+          pure $
+            let ((off, _) :: (Int, Int)) = match patt t
+             in VInteger (fromIntegral off)
+        "match" -> pure $ makeFunction $ do
+          (patt :: RE) <- nthArg 1
+          let (pre, whole, (_post :: Text), subs) = match patt t
+          if T.null whole
+            then pure VNone
+            else
+              pure $
+                VDict $
+                  OM.fromList
+                    [ ("start", VInteger (fromIntegral $ T.length pre)),
+                      ("end", VInteger (fromIntegral $ T.length pre + T.length whole)),
+                      ("text", VString whole),
+                      ("captures", VArray $ V.fromList $ map VString subs)
+                    ]
+        "matches" -> pure $ makeFunction $ do
+          (patt :: RE) <- nthArg 1
+          let matchToDict matchArray =
+                case Array.elems matchArray of
+                  [] -> VNone
+                  (off, len) : subs ->
+                    let submatches = map (\(o, l) -> VString $ extract (o, l) t) subs
+                     in VDict $
+                          OM.fromList
+                            [ ("start", VInteger (fromIntegral off)),
+                              ("end", VInteger (fromIntegral off + fromIntegral len)),
+                              ("text", VString $ extract (off, len) t),
+                              ("captures", VArray $ V.fromList submatches)
+                            ]
+          let matches = map matchToDict $ matchAll patt t
+          pure $ VArray $ V.fromList matches
+        "replace" -> pure $ makeFunction $ do
+          patt :: RE <- nthArg 1
+          (replacement :: Val) <- nthArg 2
+          mbCount :: Maybe Int <- namedArg "count" `mplus` pure Nothing
+          case mbCount of
+            Just 0 -> pure $ VString t
+            _ ->
+              case replacement of
+                VString r ->
+                  pure $ VString $ replaceRegex patt mbCount (const r) t
+                VFunction _ _ f ->
+                  pure $
+                    VString $
+                      replaceRegex
+                        patt
+                        mbCount
+                        ( \(RegexMatch start end txt captures) ->
+                            case applyPureFunction
+                              f
+                              [ VDict $
+                                  OM.fromList
+                                    [ ("start", VInteger (fromIntegral start)),
+                                      ("end", VInteger (fromIntegral end)),
+                                      ("text", VString txt),
+                                      ("captures", VArray (V.fromList (map VString captures)))
+                                    ]
+                              ] of
+                              Success (VString s) -> s
+                              _ -> ""
+                        )
+                        t
+                _ -> fail "replacement must be string or function"
+        "trim" -> pure $ makeFunction $ do
+          (RE patt _) <- nthArg 1 `mplus` makeRE "[[:space:]]*"
+          (repeated :: Bool) <- namedArg "repeat" `mplus` pure True
+          (mbAt :: Maybe Val) <- namedArg "at" `mplus` pure Nothing
+          let patt' =
+                if repeated
+                  then "(" <> patt <> ")*"
+                  else patt
+          patt'' <- case mbAt of
+            Just (VAlignment (Just HorizStart) _) -> makeRE $ "^" <> patt'
+            Just (VAlignment (Just HorizEnd) _) -> makeRE $ patt' <> "$"
+            Nothing -> makeRE $ "(^" <> patt' <> ")|(" <> patt' <> "$)"
+            _ -> fail "'at' expected either 'start' or 'end'"
+          pure $ VString $ replaceRegex patt'' Nothing (const mempty) t
+        "split" -> pure $ makeFunction $ do
+          arg <- nthArg 1
+          case arg of
+            VString "" ->
+              pure $ VArray $ V.fromList $ map VString $ "" : T.chunksOf 1 t ++ [""]
+            VString patt -> pure $ VArray $ V.fromList $ map VString $ T.splitOn patt t
+            VRegex patt ->
+              pure $
+                VArray $
+                  V.fromList $
+                    map VString $
+                      splitRegex patt t
+            _ ->
+              -- defaults to split on whitespace
+              pure $ VArray $ V.fromList $ map VString $ T.words t
+        _ -> noMethod "String" fld
+    VCounter key ->
+      case fld of
+        "display" -> pure $ makeFunction $ do
+          mbnum <- M.lookup key . evalCounters <$> lift getState
+          maybe (fail "counter not defined") (pure . VInteger) mbnum
+        "step" -> pure $ makeFunction $ do
+          lift $ updateState $ \st ->
+            st {evalCounters = M.adjust (+ 1) key $ evalCounters st}
+          pure VNone
+        "update" -> pure $ makeFunction $ do
+          mbnum <- M.lookup key . evalCounters <$> lift getState
+          case mbnum of
+            Nothing -> fail "counter not defined"
+            Just num -> do
+              newval <- nthArg 1
+              (newnum :: Integer) <-
+                case newval of
+                  VFunction _ _ fn ->
+                    case applyPureFunction fn [VInteger num] of
+                      Failure e -> fail e
+                      Success v -> fromVal v
+                  _ -> fromVal newval
+              lift $ updateState $ \st ->
+                st {evalCounters = M.adjust (const newnum) key $ evalCounters st}
+              pure VNone
+        "at" -> methodUnimplemented fld
+        "final" -> methodUnimplemented fld
+        _ -> noMethod "Counter" fld
+    VContent cs ->
+      case fld of
+        "func" -> pure $ makeFunction $ do
+          case F.toList cs of
+            [Elt name _ _] -> lift $ lookupIdentifier name
+            [Txt _] -> lift $ lookupIdentifier "text"
+            _ -> pure $ makeFunction $ do
+              xs <- allArgs
+              pure $ VContent $ foldMap valToContent xs
+        "has" -> pure $ makeFunction $ do
+          f <- nthArg 1
+          case F.toList cs of
+            [Elt _ _ fields] -> do
+              case M.lookup (Identifier f) fields of
+                Just _ -> pure $ VBoolean True
+                Nothing -> pure $ VBoolean False
+            _ | f == "children" -> pure $ VBoolean True
+            _ ->
+              fail $
+                "Content is not a single element: "
+                  <> T.unpack (repr (VContent cs))
+        "at" -> pure $ makeFunction $ do
+          (field :: Text) <- ask >>= getPositionalArg 1 >>= fromVal
+          defval <- namedArg "default" `mplus` pure VNone
+          case F.toList cs of
+            [Elt _ _ fields] ->
+              case M.lookup (Identifier field) fields of
+                Just v -> pure v
+                Nothing -> pure defval
+            _ -> pure defval
+        "location" -> methodUnimplemented fld
+        "text" ->
+          case F.toList cs of
+            [Txt t] -> pure $ VString t
+            [Elt "text" _ [("body", VContent [Txt t])]] -> pure $ VString t
+            [Elt _ _ fields]
+              | Just x <- M.lookup "text" fields -> pure x
+            _ -> fail "Content is not a single text element"
+        _ ->
+          let childrenOrFallback =
+                if fld == "children"
+                  then
+                    pure $
+                      VArray $
+                        V.fromList $
+                          map (\x -> VContent [x]) $
+                            F.toList cs
+                  else noMethod "Content" fld
+           in case cs of
+                [Elt _name _ fields] ->
+                  maybe childrenOrFallback pure $ M.lookup (Identifier fld) fields
+                _ -> childrenOrFallback
+    VTermItem t d ->
+      case fld of
+        "term" -> pure $ VContent t
+        "description" -> pure $ VContent d
+        _ -> noMethod "TermItem" fld
+    VArray v -> do
+      let toPos n =
+            if n < 0
+              then V.length v + n
+              else n
+      case fld of
+        "len" ->
+          pure $ makeFunction $ pure $ VInteger (fromIntegral $ V.length v)
+        "first" ->
+          pure $
+            makeFunction $
+              if V.null v
+                then fail "empty array"
+                else pure $ V.head v
+        "last" ->
+          pure $
+            makeFunction $
+              if V.null v
+                then fail "empty array"
+                else pure $ V.last v
+        "at" -> pure $ makeFunction $ do
+          pos <- toPos <$> nthArg 1
+          defval <- namedArg "default" `mplus` pure VNone
+          pure $ fromMaybe defval $ v V.!? pos
+        "push" -> pure $ makeFunction $ do
+          x <- nthArg 1
+          lift $ updateVal $ VArray $ V.snoc v x
+          pure VNone
+        "pop" ->
+          pure $
+            makeFunction $
+              if V.null v
+                then fail "empty array"
+                else do
+                  lift $ updateVal $ VArray $ V.init v
+                  pure $ V.last v
+        "slice" -> pure $ makeFunction $ do
+          start <- toPos <$> nthArg 1
+          end <-
+            (toPos <$> nthArg 2)
+              `mplus` ((+ start) <$> namedArg "count")
+              `mplus` pure (V.length v)
+          if V.length v < end
+            then fail "array contains insufficient elements for slice"
+            else
+              if end < start
+                then pure $ VArray mempty
+                else pure $ VArray $ V.slice start (end - start) v
+        "split" -> pure $ makeFunction $ do
+          spliton <- nthArg 1
+          let go v' = case V.break (== spliton) v' of
+                (a, b) | V.null b -> if V.null a then [] else [VArray a]
+                (a, b) -> VArray a : go (V.drop 1 b)
+          pure $ VArray $ V.fromList $ go v
+        "insert" -> pure $ makeFunction $ do
+          pos <- toPos <$> nthArg 1
+          newval <- nthArg 2
+          if pos >= V.length v || pos < 0
+            then fail "insert position out of bounds in array"
+            else do
+              lift $ updateVal $ VArray $ V.snoc (V.take pos v) newval <> V.drop pos v
+              pure VNone
+        "remove" -> pure $ makeFunction $ do
+          pos <- toPos <$> nthArg 1
+          if pos >= V.length v || pos < 0
+            then fail "remove position out of bounds in array"
+            else do
+              lift $ updateVal $ VArray $ V.take pos v <> V.drop (pos + 1) v
+              pure $ fromMaybe VNone $ v V.!? pos
+        "contains" -> pure $ makeFunction $ do
+          item <- nthArg 1
+          pure $ VBoolean $ V.elem item v
+        "find" -> pure $ makeFunction $ do
+          Function fn <- nthArg 1
+          let go Nothing y = do
+                res <- lift $ fn Arguments {positional = [y], named = OM.empty}
+                case res of
+                  VBoolean True -> pure $ Just y
+                  VBoolean False -> pure Nothing
+                  _ -> fail "function does not return a boolean"
+              go (Just z) _ = pure $ Just z
+          res <- foldM go Nothing v
+          case res of
+            Just z -> pure z
+            Nothing -> pure VNone
+        "position" -> pure $ makeFunction $ do
+          Function fn <- nthArg 1
+          let go (Left i) y = do
+                res <- lift $ fn Arguments {positional = [y], named = OM.empty}
+                case res of
+                  VBoolean True -> pure $ Right i
+                  VBoolean False -> pure $ Left (i + 1)
+                  _ -> fail "function does not return a boolean"
+              go (Right i) _ = pure $ Right i
+          res <- foldM go (Left 0) v
+          case res of
+            Right i -> pure $ VInteger i
+            Left _ -> pure VNone
+        "filter" -> pure $ makeFunction $ do
+          Function fn <- nthArg 1
+          let predicate y = do
+                res <- lift $ fn Arguments {positional = [y], named = OM.empty}
+                case res of
+                  VBoolean True -> pure True
+                  VBoolean False -> pure False
+                  _ -> fail "function does not return a boolean"
+          VArray <$> V.filterM predicate v
+        "map" -> pure $ makeFunction $ do
+          Function fn <- nthArg 1
+          let f y = lift $ fn Arguments {positional = [y], named = OM.empty}
+          VArray <$> V.mapM f v
+        "flatten" ->
+          pure $
+            makeFunction $
+              pure $
+                VArray $
+                  V.concat [v' | VArray v' <- V.toList v]
+        "enumerate" ->
+          pure $
+            makeFunction $
+              pure $
+                VArray $
+                  V.zipWith
+                    (\x y -> VArray [x, y])
+                    (V.map VInteger [0 .. (fromIntegral $ V.length v)])
+                    v
+        "fold" -> pure $ makeFunction $ do
+          (start :: Val) <- nthArg 1
+          Function fn <- nthArg 2
+          let f acc y = fn Arguments {positional = [acc, y], named = OM.empty}
+          lift $ foldM f start $ V.toList v
+        "any" -> pure $ makeFunction $ do
+          Function fn <- nthArg 1
+          let predicate y = do
+                res <- lift $ fn Arguments {positional = [y], named = OM.empty}
+                case res of
+                  VBoolean True -> pure True
+                  VBoolean False -> pure False
+                  _ -> fail "function not return a boolean"
+          (VBoolean . V.any id) <$> mapM predicate v
+        "all" -> pure $ makeFunction $ do
+          Function fn <- nthArg 1
+          let predicate y = do
+                res <- lift $ fn Arguments {positional = [y], named = OM.empty}
+                case res of
+                  VBoolean True -> pure True
+                  VBoolean False -> pure False
+                  _ -> fail "function not return a boolean"
+          (VBoolean . V.all id) <$> mapM predicate v
+        "rev" -> pure $ makeFunction $ pure $ VArray $ V.reverse v
+        "join" -> pure $ makeFunction $ do
+          separator <- nthArg 1
+          lastsep <- namedArg "last" `mplus` pure separator
+          let xs' = F.toList v
+          let xs = case xs' of
+                [] -> []
+                _ -> intersperse separator (init xs') ++ [lastsep, last xs']
+          foldM joinVals VNone xs
+        "sorted" -> pure $ makeFunction $ do
+          (mbKeyFn :: Maybe Function) <- namedArg "key" `mplus` pure Nothing
+          case mbKeyFn of
+            Nothing -> pure $ VArray $ V.fromList $ sort $ V.toList v
+            Just (Function kf) -> do
+              let kf' x = lift $ kf Arguments {positional = [x], named = OM.empty}
+              VArray . V.fromList . map fst . sortOn snd
+                <$> (mapM (\x -> (x,) <$> kf' x) (V.toList v))
+        "zip" -> pure $ makeFunction $ do
+          (v' :: V.Vector Val) <- ask >>= getPositionalArg 1
+          pure $ VArray $ V.map pairToArray $ V.zip v v'
+        "sum" -> pure $ makeFunction $ do
+          mbv <- namedArg "default" `mplus` pure Nothing
+          case V.uncons v of
+            Nothing ->
+              maybe
+                (fail "sum of empty array with no default value")
+                pure
+                mbv
+            Just (h, rest) ->
+              pure $
+                fromMaybe VNone $
+                  V.foldl
+                    ( \mbsum x -> case mbsum of
+                        Nothing -> Nothing
+                        Just y -> maybePlus y x
+                    )
+                    (Just h)
+                    rest
+        "product" -> pure $ makeFunction $ do
+          mbv <- namedArg "default" `mplus` pure Nothing
+          case V.uncons v of
+            Nothing ->
+              maybe
+                (fail "product of empty array with no default value")
+                pure
+                mbv
+            Just (h, rest) ->
+              pure $
+                fromMaybe VNone $
+                  V.foldl
+                    ( \mbsum x -> case mbsum of
+                        Nothing -> Nothing
+                        Just y -> maybeTimes y x
+                    )
+                    (Just h)
+                    rest
+        _ -> noMethod "Array" fld
+    VFunction mbName scope (Function f) ->
+      case fld of
+        "with" -> pure $ makeFunction $ do
+          args <- ask
+          pure $
+            VFunction mbName scope $
+              Function $
+                \args' -> f (args <> args')
+        "where" -> pure $ makeFunction $ do
+          args <- ask
+          case mbName of
+            Nothing -> fail "function is not an element function"
+            Just name ->
+              pure $
+                VSelector $
+                  SelectElement name (OM.assocs (named args))
+        _ -> noMethod "Function" fld
+    VSelector sel ->
+      case fld of
+        "or" -> pure $ makeFunction $ do
+          (other :: Selector) <- nthArg 1
+          pure $ VSelector $ SelectOr other sel
+        "and" -> pure $ makeFunction $ do
+          (other :: Selector) <- nthArg 1
+          pure $ VSelector $ SelectAnd other sel
+        "before" -> pure $ makeFunction $ do
+          (other :: Selector) <- nthArg 1
+          pure $ VSelector $ SelectBefore other sel
+        "after" -> pure $ makeFunction $ do
+          (other :: Selector) <- nthArg 1
+          pure $ VSelector $ SelectAfter other sel
+        _ -> noMethod "Selector" fld
+    VArguments args ->
+      case fld of
+        "pos" -> pure $ makeFunction $ pure $ VArray $ V.fromList (positional args)
+        "named" -> pure $ makeFunction $ pure $ VDict $ named args
+        _ -> noMethod "Arguments" fld
+    _ -> noMethod (drop 1 $ takeWhile (/= ' ') $ show val) fld
+
+pairToArray :: (Val, Val) -> Val
+pairToArray (x, y) = VArray $ V.fromList [x, y]
+
+applyPureFunction :: Function -> [Val] -> Attempt Val
+applyPureFunction (Function f) vals =
+  let args = Arguments vals OM.empty
+   in case runParserT (f args) initialEvalState "" [] of
+        Failure s -> Failure s
+        Success (Left s) -> Failure $ show s
+        Success (Right v) -> Success v
+
+initialEvalState :: MonadFail m => EvalState m
+initialEvalState =
+  emptyEvalState { evalIdentifiers = [(BlockScope, standardModule)] }
+
+formatNumber :: Text -> Int -> Text
+formatNumber t n = F.foldMap go $ T.unpack t
+  where
+    go '1' | n >= 0 = T.pack (show n)
+    go 'a' | n >= 1 = T.singleton $ cycle ['a' .. 'z'] !! (n - 1 `mod` 26)
+    go 'A' | n >= 1 = T.singleton $ cycle ['A' .. 'Z'] !! (n - 1 `mod` 26)
+    go 'i' | n >= 1 = T.toLower $ toRomanNumeral n
+    go 'I' | n >= 1 = toRomanNumeral n
+    go 'い' | n >= 1 = T.pack (show n) -- TODO
+    go 'イ' | n >= 1 = T.pack (show n) -- TODO
+    go 'א' | n >= 1 = T.pack (show n) -- TODO
+    go '*'
+      | n >= 1 =
+          T.singleton $ cycle ['*', '†', '‡', '§', '¶', '‖'] !! (n - 1 `mod` 6)
+      | otherwise = "-"
+    go c = T.singleton c
+
+toRomanNumeral :: Int -> T.Text
+toRomanNumeral x
+  | x >= 4000 || x < 0 = "?"
+  | x >= 1000 = "M" <> toRomanNumeral (x - 1000)
+  | x >= 900 = "CM" <> toRomanNumeral (x - 900)
+  | x >= 500 = "D" <> toRomanNumeral (x - 500)
+  | x >= 400 = "CD" <> toRomanNumeral (x - 400)
+  | x >= 100 = "C" <> toRomanNumeral (x - 100)
+  | x >= 90 = "XC" <> toRomanNumeral (x - 90)
+  | x >= 50 = "L" <> toRomanNumeral (x - 50)
+  | x >= 40 = "XL" <> toRomanNumeral (x - 40)
+  | x >= 10 = "X" <> toRomanNumeral (x - 10)
+  | x == 9 = "IX"
+  | x >= 5 = "V" <> toRomanNumeral (x - 5)
+  | x == 4 = "IV"
+  | x >= 1 = "I" <> toRomanNumeral (x - 1)
+  | otherwise = ""
diff --git a/src/Typst/Module/Calc.hs b/src/Typst/Module/Calc.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Module/Calc.hs
@@ -0,0 +1,201 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Typst.Module.Calc
+  ( calcModule,
+  )
+where
+
+import Control.Applicative ((<|>))
+import qualified Data.Map as M
+import Data.Maybe (fromMaybe)
+import Typst.Types
+import Typst.Util
+
+calcModule :: M.Map Identifier Val
+calcModule =
+  M.fromList
+    [ ( "abs",
+        makeFunction $ do
+          (v :: Val) <- nthArg 1
+          (n :: Double) <- fromVal v
+          pure $
+            if n < 0
+              then fromMaybe v $ maybeNegate v
+              else v
+      ),
+      ( "binom",
+        makeFunction $ do
+          (n :: Integer) <- nthArg 1
+          (k :: Integer) <- nthArg 2
+          pure $ VInteger $ product [(1 + n - k) .. n] `div` product [1 .. k]
+      ),
+      ( "ceil",
+        makeFunction $ do
+          (x :: Double) <- nthArg 1
+          pure $ VInteger (ceiling x)
+      ),
+      ( "clamp",
+        makeFunction $ do
+          value <- nthArg 1
+          minval <- nthArg 2
+          maxval <- nthArg 3
+          pure $
+            if value < minval
+              then minval
+              else
+                if value > maxval
+                  then maxval
+                  else value
+      ),
+      ( "even",
+        makeFunction $ do
+          v <- nthArg 1
+          case v of
+            VInteger i -> pure $ VBoolean $ even i
+            _ -> fail "even requires an integer argument"
+      ),
+      ( "fact",
+        makeFunction $ do
+          v <- nthArg 1
+          case v of
+            VInteger i
+              | i == 0 -> pure $ VInteger 1
+              | i > 0 -> pure $ VInteger $ product [1 .. i]
+            _ -> fail "odd requires a non-negative integer argument"
+      ),
+      ( "floor",
+        makeFunction $ do
+          (x :: Double) <- nthArg 1
+          pure $ VInteger (floor x)
+      ),
+      ( "fract",
+        makeFunction $ do
+          (v :: Val) <- nthArg 1
+          case v of
+            VInteger _ -> pure $ VInteger 0
+            VFloat x -> pure $ VFloat (x - fromIntegral (truncate x :: Integer))
+            _ -> fail "fract requires integer or float argument"
+      ),
+      ( "gcd",
+        makeFunction $ do
+          x <- nthArg 1
+          y <- nthArg 2
+          pure $ VInteger $ gcd x y
+      ),
+      ( "lcm",
+        makeFunction $ do
+          x <- nthArg 1
+          y <- nthArg 2
+          pure $ VInteger $ lcm x y
+      ),
+      ( "log",
+        makeFunction $ do
+          b <- namedArg "base" <|> pure 10
+          n <- nthArg 1
+          if n <= 0
+            then fail "value must be strictly positive"
+            else
+              if b == 0
+                then fail "base may not be 0"
+                else pure $ VFloat $ logBase b n
+      ),
+      ( "max",
+        makeFunction $ do
+          vs <- allArgs
+          case vs of
+            [] -> fail "max requires one or more argument"
+            _ : _ -> pure $ maximum vs
+      ),
+      ( "min",
+        makeFunction $ do
+          vs <- allArgs
+          case vs of
+            [] -> fail "min requires one or more argument"
+            _ : _ -> pure $ minimum vs
+      ),
+      ( "mod",
+        makeFunction $ do
+          (a :: Integer) <- nthArg 1
+          (b :: Integer) <- nthArg 2
+          pure $ VInteger $ a `mod` b
+      ),
+      ( "odd",
+        makeFunction $ do
+          v <- nthArg 1
+          case v of
+            VInteger i -> pure $ VBoolean $ odd i
+            _ -> fail "odd requires an integer argument"
+      ),
+      ( "perm",
+        makeFunction $ do
+          b <- nthArg 1
+          n <- nthArg 2
+          pure $
+            if n > b
+              then VInteger 0
+              else VInteger $ div (product [1 .. b]) (product [1 .. (b - n)])
+      ),
+      ( "pow",
+        makeFunction $ do
+          base <- nthArg 1
+          ex <- nthArg 2
+          case (base, ex) of
+            (VInteger x, VInteger y) -> pure $ VInteger $ x ^ y
+            _ -> do
+              (base' :: Double) <- fromVal base
+              (ex' :: Integer) <- fromVal ex
+              pure $ VFloat $ (base') ^ (ex')
+      ),
+      ( "quo",
+        makeFunction $ do
+          (a :: Integer) <- nthArg 1
+          (b :: Integer) <- nthArg 2
+          pure $ VInteger $ a `quot` b
+      ),
+      ( "rem",
+        makeFunction $ do
+          (a :: Integer, f :: Double) <- properFraction <$> nthArg 1
+          (b :: Integer) <- nthArg 2
+          pure $
+            if f == 0
+              then VInteger $ rem a b
+              else VFloat $ fromIntegral (rem a b) + f
+      ),
+      ( "round",
+        makeFunction $ do
+          (x :: Double) <- nthArg 1
+          (digits :: Integer) <- namedArg "digits" <|> pure 0
+          pure $
+            if digits > 0
+              then
+                VFloat $
+                  fromIntegral (round (x * 10 ^ digits) :: Integer)
+                    / 10 ^ digits
+              else VInteger (round x)
+      ),
+      ( "trunc",
+        makeFunction $ do
+          (x :: Double) <- nthArg 1
+          pure $ VInteger $ truncate x
+      ),
+      ( "sqrt",
+        makeFunction $ do
+          n <- nthArg 1
+          if n < 0
+            then fail "can't take square root of negative number"
+            else pure $ VFloat $ sqrt n
+      ),
+      ("cos", makeFunction $ VFloat . cos <$> nthArg 1),
+      ("cosh", makeFunction $ VFloat . cosh <$> nthArg 1),
+      ("sin", makeFunction $ VFloat . sin <$> nthArg 1),
+      ("sinh", makeFunction $ VFloat . sinh <$> nthArg 1),
+      ("tan", makeFunction $ VFloat . tan <$> nthArg 1),
+      ("tanh", makeFunction $ VFloat . tanh <$> nthArg 1),
+      ("acos", makeFunction $ VAngle . acos <$> nthArg 1),
+      ("asin", makeFunction $ VAngle . asin <$> nthArg 1),
+      ("atan", makeFunction $ VAngle . atan <$> nthArg 1),
+      ("atan2", makeFunction $ VAngle <$> (atan2 <$> nthArg 1 <*> nthArg 2)),
+      ("e", VFloat (exp 1)),
+      ("pi", VFloat pi)
+    ]
diff --git a/src/Typst/Module/Math.hs b/src/Typst/Module/Math.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Module/Math.hs
@@ -0,0 +1,184 @@
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Typst.Module.Math
+  ( mathModule,
+  )
+where
+
+import qualified Data.Map as M
+import qualified Data.Sequence as Seq
+import qualified Data.Vector as V
+import Text.Parsec (getPosition)
+import Typst.Types
+import Typst.Util
+
+mathModule :: M.Map Identifier Val
+mathModule =
+  M.fromList
+    [ makeElement
+        (Just "math")
+        "frac"
+        [ ("num", One TContent),
+          ("denom", One TContent)
+        ],
+      makeElement
+        (Just "math")
+        "accent"
+        [ ("base", One TContent),
+          ("accent", One (TContent :|: TString :|: TSymbol))
+        ],
+      makeElement (Just "math") "attach" [("base", One TContent)],
+      makeElement (Just "math") "scripts" [("body", One TContent)],
+      makeElement (Just "math") "limits" [("body", One TContent)],
+      makeElement
+        (Just "math")
+        "binom"
+        [ ("upper", One TContent),
+          ("lower", One TContent)
+        ],
+      makeElement (Just "math") "cancel" [("body", One TContent)],
+      makeElement (Just "math") "equation" [("body", One TContent)],
+      makeElement
+        (Just "math")
+        "root"
+        [ ("index", One (TNone :|: TContent :|: TInteger :|: TRatio)),
+          ("radicand", One TContent)
+        ],
+      makeElement (Just "math") "sqrt" [("radicand", One TContent)],
+      makeElement (Just "math") "cases" [("children", Many TContent)],
+      makeElement (Just "math") "lr" [("body", Many TContent)],
+      makeElement (Just "math") "abs" [("body", One TContent)],
+      makeElement (Just "math") "norm" [("body", One TContent)],
+      makeElement (Just "math") "floor" [("body", One TContent)],
+      makeElement (Just "math") "ceil" [("body", One TContent)],
+      ("mat", matrixElement),
+      makeElement (Just "math") "round" [("body", One TContent)],
+      makeElement (Just "math") "serif" [("body", One TContent)],
+      makeElement (Just "math") "sans" [("body", One TContent)],
+      makeElement (Just "math") "frak" [("body", One TContent)],
+      makeElement (Just "math") "mono" [("body", One TContent)],
+      makeElement (Just "math") "bb" [("body", One TContent)],
+      makeElement (Just "math") "cal" [("body", One TContent)],
+      makeElement (Just "math") "cal" [("body", One TContent)],
+      makeElement (Just "math") "upright" [("body", One TContent)],
+      makeElement (Just "math") "italic" [("body", One TContent)],
+      makeElement (Just "math") "bold" [("body", One TContent)],
+      makeElement (Just "math") "op" [("text", One TString)],
+      makeElement (Just "math") "underline" [("body", One TContent)],
+      makeElement (Just "math") "overline" [("body", One TContent)],
+      makeElement
+        (Just "math")
+        "underbrace"
+        [ ("body", One TContent),
+          ("annotation", One (TNone :|: TContent))
+        ],
+      makeElement
+        (Just "math")
+        "overbrace"
+        [ ("body", One TContent),
+          ("annotation", One (TNone :|: TContent))
+        ],
+      makeElement
+        (Just "math")
+        "underbracket"
+        [ ("body", One TContent),
+          ("annotation", One (TNone :|: TContent))
+        ],
+      makeElement
+        (Just "math")
+        "overbracket"
+        [ ("body", One TContent),
+          ("annotation", One (TNone :|: TContent))
+        ],
+      makeElement (Just "math") "vec" [("children", Many TContent)],
+      makeElement (Just "math") "alignpoint" [] -- not a real element, but needed internally
+    ]
+    <> M.map (VContent . Seq.singleton) predefinedOperators
+    <> M.map (VContent . Seq.singleton) spaceConstants
+    <> [ ("dif", VSymbol (Symbol "d" False mempty)),
+         ("Dif", VSymbol (Symbol "D" False mempty))
+       ]
+
+matrixElement :: Val
+matrixElement = VFunction (Just "mat") mempty $ Function $ \args -> do
+  pos <- getPosition
+  -- get array args first
+  let isArray (VArray {}) = True
+      isArray _ = False
+  let (as, bs) = span isArray (positional args)
+  let rows =
+        if null bs
+          then as
+          else as ++ [VArray (V.fromList bs)]
+  -- then any leftovers
+  let fields = M.fromList [("rows", VArray (V.fromList rows))]
+  pure $ VContent . Seq.singleton $ Elt "math.mat" (Just pos) fields
+
+spaceConstants :: M.Map Identifier Content
+spaceConstants =
+  [ ("thin", Txt "\8201"),
+    ("thick", Txt "\8197"),
+    ("med", Txt "\8287"),
+    ("quad", Txt "\8195")
+  ]
+
+predefinedOperators :: M.Map Identifier Content
+predefinedOperators =
+  M.fromList $
+    map
+      ( \t ->
+          ( Identifier t,
+            Elt
+              "math.op"
+              Nothing
+              [("text", VString t), ("limits", VBoolean True)]
+          )
+      )
+      [ "limsup",
+        "liminf",
+        "det",
+        "gcd",
+        "inf",
+        "lim",
+        "max",
+        "min",
+        "Pr",
+        "sup"
+      ]
+      ++ map
+        ( \t ->
+            ( Identifier t,
+              Elt
+                "math.op"
+                Nothing
+                [("text", VString t), ("limits", VBoolean False)]
+            )
+        )
+        [ "arccos",
+          "arcsin",
+          "arctan",
+          "arg",
+          "cos",
+          "cosh",
+          "cot",
+          "ctg",
+          "coth",
+          "csc",
+          "deg",
+          "dim",
+          "exp",
+          "hom",
+          "mod",
+          "ker",
+          "lg",
+          "ln",
+          "log",
+          "sec",
+          "sin",
+          "sinc",
+          "sinh",
+          "tan",
+          "tg",
+          "tanh"
+        ]
diff --git a/src/Typst/Module/Standard.hs b/src/Typst/Module/Standard.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Module/Standard.hs
@@ -0,0 +1,517 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Typst.Module.Standard
+  ( standardModule,
+    loadFileText,
+  )
+where
+
+import Control.Applicative ((<|>))
+import Control.Monad (mplus, unless)
+import Control.Monad.Reader (lift)
+import qualified Data.Aeson as Aeson
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Csv as Csv
+import qualified Data.Map as M
+import qualified Data.Map.Ordered as OM
+import Data.Maybe (mapMaybe)
+import Data.Ratio ((%))
+import qualified Data.Sequence as Seq
+import qualified Data.Set as Set
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+import qualified Data.Vector as V
+import qualified Data.Yaml as Yaml
+import Text.Parsec (getPosition, getState, updateState)
+import Text.Read (readMaybe)
+import qualified Text.XML as XML
+import Typst.Emoji (typstEmojis)
+import Typst.Module.Calc (calcModule)
+import Typst.Module.Math (mathModule)
+import Typst.Regex (makeRE)
+import Typst.Symbols (typstSymbols)
+import Typst.Types
+import Typst.Util
+
+standardModule :: M.Map Identifier Val
+standardModule =
+  M.fromList $
+    [ ("math", VModule "math" mathModule),
+      ("sym", VModule "sym" symModule),
+      ("emoji", VModule "emoji" emojiModule),
+      ("calc", VModule "calc" calcModule)
+    ]
+      ++ colors
+      ++ directions
+      ++ alignments
+      ++ textual
+      ++ layout
+      ++ visualize
+      ++ meta
+      ++ foundations
+      ++ construct
+      ++ dataLoading
+
+symModule :: M.Map Identifier Val
+symModule = M.map VSymbol $ makeSymbolMap typstSymbols
+
+emojiModule :: M.Map Identifier Val
+emojiModule = M.map VSymbol $ makeSymbolMap typstEmojis
+
+textual :: [(Identifier, Val)]
+textual =
+  [ makeElement
+      Nothing
+      "text"
+      [ ("color", One TColor),
+        ("size", One TLength),
+        ("body", One (TContent :|: TString :|: TSymbol))
+      ],
+    makeElement Nothing "emph" [("body", One TContent)],
+    makeElement Nothing "linebreak" [],
+    makeElement Nothing "strong" [("body", One TContent)],
+    makeElement Nothing "sub" [("body", One TContent)],
+    makeElement Nothing "super" [("body", One TContent)],
+    makeElement Nothing "strike" [("body", One TContent)],
+    makeElement Nothing "smallcaps" [("body", One TContent)],
+    makeElement Nothing "underline" [("body", One TContent)],
+    makeElement Nothing "overline" [("body", One TContent)],
+    makeElement Nothing "raw" [("text", One TString)],
+    makeElement Nothing "smartquote" [],
+    makeElement Nothing "lower" [("text", One (TString :|: TContent))],
+    ( "lower",
+      makeFunction $ do
+        val <- nthArg 1
+        case val of
+          VString t -> pure $ VString $ T.toLower t
+          VContent cs -> do
+            pos <- lift getPosition
+            pure $ VContent . Seq.singleton $ Elt "lower" (Just pos) [("text", VContent cs)]
+          _ -> fail "argument must be string or content"
+    ),
+    ( "upper",
+      makeFunction $ do
+        val <- nthArg 1
+        case val of
+          VString t -> pure $ VString $ T.toUpper t
+          VContent cs -> do
+            pos <- lift getPosition
+            pure $ VContent . Seq.singleton $ Elt "upper" (Just pos) [("text", VContent cs)]
+          _ -> fail "argument must be string or content"
+    )
+  ]
+
+layout :: [(Identifier, Val)]
+layout =
+  [ makeElement
+      Nothing
+      "align"
+      [ ("alignment", One TAlignment),
+        ("body", One TContent)
+      ],
+    makeElement Nothing "block" [("body", One TContent)],
+    makeElement Nothing "box" [("body", One TContent)],
+    makeElement Nothing "colbreak" [],
+    makeElement Nothing "columns" [("count", One TInteger), ("body", One TContent)],
+    makeElement Nothing "grid" [("children", Many TContent)],
+    makeElement Nothing "h" [("amount", One (TLength :|: TRatio :|: TFraction))],
+    makeElement Nothing "v" [("amount", One (TLength :|: TRatio :|: TFraction))],
+    makeElement Nothing "hide" [("body", One TContent)],
+    makeElementWithScope
+      Nothing
+      "enum"
+      [("children", Many TContent)]
+      [ makeElement
+          (Just "enum")
+          "item"
+          [ ("number", One (TInteger :|: TNone)),
+            ("body", One TContent)
+          ]
+      ],
+    makeElementWithScope
+      Nothing
+      "list"
+      [("children", Many TContent)]
+      [makeElement (Just "list") "item" [("body", One TContent)]],
+    -- for "measure" see below
+    makeElement Nothing "move" [("body", One TContent)],
+    -- the fact that pad can take a positional param for a length (= rest) is undocumented!
+    makeElement Nothing "pad" [("rest", One (TLength :|: TRatio :|: TNone)), ("body", One TContent)],
+    makeElement Nothing "page" [("body", One TContent)],
+    makeElement Nothing "pagebreak" [],
+    makeElement Nothing "par" [("body", One TContent)],
+    makeElement Nothing "parbreak" [],
+    makeElement Nothing "place" [("alignment", One (TAlignment :|: TNone)), ("body", One TContent)],
+    makeElement Nothing "repeat" [("body", One TContent)],
+    makeElement Nothing "rotate" [("angle", One TAngle), ("body", One TContent)],
+    -- the fact that scale can take a positional factor is undocumented!
+    makeElement Nothing "scale" [("factor", One (TRatio :|: TNone)), ("body", One TContent)],
+    makeElement
+      Nothing
+      "stack"
+      [("children", Many (TLength :|: TRatio :|: TFraction :|: TContent))],
+    makeElement Nothing "table" [("children", Many TContent)],
+    makeElementWithScope
+      Nothing
+      "terms"
+      [("children", Many TTermItem)]
+      [ makeElement
+          (Just "terms")
+          "item"
+          [ ("term", One TContent),
+            ("description", One TContent)
+          ]
+      ],
+    ( "measure",
+      makeFunction $ do
+        -- content <- nthArg 1
+        -- styles <- nthArg 2
+        pure $
+          VDict $
+            OM.fromList
+              [ ("width", VLength (LExact 1.0 LEm)),
+                ("height", VLength (LExact 1.0 LEm))
+              ]
+    )
+    -- these are fake widths so we don't crash...
+  ]
+
+visualize :: [(Identifier, Val)]
+visualize =
+  [ makeElement Nothing "circle" [("body", One (TContent :|: TNone))],
+    makeElement Nothing "ellipse" [("body", One (TContent :|: TNone))],
+    makeElement Nothing "image" [("path", One TString)],
+    makeElement Nothing "line" [],
+    makeElement Nothing "path" [("vertices", Many TArray)],
+    makeElement Nothing "polygon" [("vertices", Many TArray)],
+    makeElement Nothing "rect" [("body", One (TContent :|: TNone))],
+    makeElement Nothing "square" [("body", One (TContent :|: TNone))]
+  ]
+
+meta :: [(Identifier, Val)]
+meta =
+  [ makeElement Nothing "bibliography" [("path", One (TString :|: TArray))],
+    makeElement
+      Nothing
+      "cite"
+      [ ("keys", Many TString),
+        ("supplement", One (TContent :|: TNone))
+      ],
+    makeElement Nothing "document" [],
+    makeElement Nothing "figure" [("body", One TContent)],
+    makeElement Nothing "heading" [("body", One TContent)],
+    makeElement Nothing "layout" [("func", One TFunction)],
+    makeElement
+      Nothing
+      "link"
+      [ ("dest", One (TString :|: TLabel :|: TDict :|: TLocation)),
+        ("body", One TContent)
+      ],
+    makeElement Nothing "locate" [("func", One TFunction)],
+    makeElement
+      Nothing
+      "numbering"
+      [ ("numbering", One (TString :|: TFunction)),
+        ("numbers", Many TInteger)
+      ],
+    makeElement Nothing "outline" [],
+    makeElement
+      Nothing
+      "query"
+      [ ("target", One (TLabel :|: TFunction)),
+        ("location", One TLocation)
+      ],
+    makeElement Nothing "ref" [("target", One TLabel)],
+    makeElement Nothing "state" [("key", One TString), ("init", One TAny)],
+    makeElement Nothing "style" [("func", One TFunction)],
+    makeElementWithScope
+      Nothing
+      "footnote"
+      [("body", One TContent)]
+      [makeElement (Just "footnote") "entry" [("note", One TContent)]]
+  ]
+
+colors :: [(Identifier, Val)]
+colors =
+  [ ("red", VColor $ RGB (0xff % 0xff) (0x41 % 0xff) (0x36 % 0xff) 1),
+    ("blue", VColor $ RGB (0x00 % 0xff) (0x74 % 0xff) (0xd9 % 0xff) 1),
+    ("black", VColor $ RGB (0x00 % 0xff) (0x00 % 0xff) (0x00 % 0xff) 1),
+    ("gray", VColor $ RGB (0xaa % 0xff) (0xaa % 0xff) (0xaa % 0xff) 1),
+    ("silver", VColor $ RGB (0xdd % 0xff) (0xdd % 0xff) (0xdd % 0xff) 1),
+    ("white", VColor $ RGB (0xff % 0xff) (0xff % 0xff) (0xff % 0xff) 1),
+    ("navy", VColor $ RGB (0x00 % 0xff) (0x1f % 0xff) (0x3f % 0xff) 1),
+    ("aqua", VColor $ RGB (0x7f % 0xff) (0xdb % 0xff) (0xff % 0xff) 1),
+    ("teal", VColor $ RGB (0x39 % 0xff) (0xcc % 0xff) (0xcc % 0xff) 1),
+    ("eastern", VColor $ RGB (0x23 % 0xff) (0x9d % 0xff) (0xad % 0xff) 1),
+    ("purple", VColor $ RGB (0xb1 % 0xff) (0x0d % 0xff) (0xc9 % 0xff) 1),
+    ("fuchsia", VColor $ RGB (0xf0 % 0xff) (0x12 % 0xff) (0xbe % 0xff) 1),
+    ("maroon", VColor $ RGB (0x85 % 0xff) (0x14 % 0xff) (0x4b % 0xff) 1),
+    ("yellow", VColor $ RGB (0xff % 0xff) (0xdc % 0xff) (0x00 % 0xff) 1),
+    ("orange", VColor $ RGB (0xff % 0xff) (0x85 % 0xff) (0x1b % 0xff) 1),
+    ("olive", VColor $ RGB (0x3d % 0xff) (0x99 % 0xff) (0x70 % 0xff) 1),
+    ("green", VColor $ RGB (0x2e % 0xff) (0xcc % 0xff) (0x40 % 0xff) 1),
+    ("lime", VColor $ RGB (0x01 % 0xff) (0xff % 0xff) (0x70 % 0xff) 1)
+  ]
+
+directions :: [(Identifier, Val)]
+directions =
+  [ ("ltr", VDirection Ltr),
+    ("rtl", VDirection Rtl),
+    ("ttb", VDirection Ttb),
+    ("btt", VDirection Btt)
+  ]
+
+alignments :: [(Identifier, Val)]
+alignments =
+  [ ("start", VAlignment (Just HorizStart) Nothing),
+    ("end", VAlignment (Just HorizEnd) Nothing),
+    ("left", VAlignment (Just HorizLeft) Nothing),
+    ("center", VAlignment (Just HorizCenter) Nothing),
+    ("right", VAlignment (Just HorizRight) Nothing),
+    ("top", VAlignment Nothing (Just VertTop)),
+    ("horizon", VAlignment Nothing (Just VertHorizon)),
+    ("bottom", VAlignment Nothing (Just VertBottom))
+  ]
+
+foundations :: [(Identifier, Val)]
+foundations =
+  [ ( "assert",
+      makeFunctionWithScope
+        ( do
+            (cond :: Bool) <- nthArg 1
+            unless cond $ do
+              (msg :: String) <- namedArg "message" <|> pure "Assertion failed"
+              fail msg
+            pure VNone
+        )
+        [ ( "eq",
+            makeFunction $ do
+              (v1 :: Val) <- nthArg 1
+              (v2 :: Val) <- nthArg 2
+              unless (comp v1 v2 == Just EQ) $ fail "Assertion failed"
+              pure VNone
+          ),
+          ( "ne",
+            makeFunction $ do
+              (v1 :: Val) <- nthArg 1
+              (v2 :: Val) <- nthArg 2
+              unless (comp v1 v2 /= Just EQ) $ fail "Assertion failed"
+              pure VNone
+          )
+        ]
+    ),
+    ("panic", makeFunction $ allArgs >>= fail . unlines . map show),
+    ("repr", makeFunction $ nthArg 1 >>= pure . VString . repr),
+    ( "type",
+      makeFunction $ do
+        (x :: Val) <- nthArg 1
+        pure $
+          VString $
+            case valType x of
+              TAlignment ->
+                case x of
+                  VAlignment (Just _) (Just _) -> "2d alignment"
+                  _ -> "alignment"
+              TDict -> "dictionary"
+              ty -> T.toLower . T.drop 1 . T.pack . show $ ty
+    )
+  ]
+
+construct :: [(Identifier, Val)]
+construct =
+  [ ( "cmyk",
+      makeFunction $
+        VColor <$> (CMYK <$> nthArg 1 <*> nthArg 2 <*> nthArg 3 <*> nthArg 4)
+    ),
+    ("float", makeFunction $ VFloat <$> nthArg 1),
+    ("int", makeFunction $ VInteger <$> nthArg 1),
+    ("label", makeFunction $ VLabel <$> nthArg 1),
+    ( "counter",
+      makeFunction $ do
+        (counter :: Counter) <- nthArg 1
+        let initializeIfMissing Nothing = Just 0
+            initializeIfMissing (Just x) = Just x
+        lift $ updateState $ \st ->
+          st {evalCounters = M.alter initializeIfMissing counter $ evalCounters st}
+        pure $ VCounter counter
+    ),
+    ("luma", makeFunction $ VColor <$> (Luma <$> nthArg 1)),
+    ( "range",
+      makeFunction $ do
+        first <- nthArg 1
+        mbsecond <- nthArg 2 `mplus` (fmap (+ first) <$> namedArg "count")
+        step <- namedArg "step" `mplus` pure 1
+        pure $
+          VArray $
+            V.fromList $
+              map VInteger $
+                case (first, mbsecond) of
+                  (end, Nothing) -> enumFromThenTo 0 step (end - 1)
+                  (start, Just end) ->
+                    enumFromThenTo
+                      start
+                      (start + step)
+                      ( if start < end
+                          then end - 1
+                          else end + 1
+                      )
+    ),
+    ("regex", makeFunction $ VRegex <$> (nthArg 1 >>= makeRE)),
+    ( "rgb",
+      makeFunction $
+        VColor
+          <$> ( ( RGB
+                    <$> (nthArg 1 >>= toRatio)
+                    <*> (nthArg 2 >>= toRatio)
+                    <*> (nthArg 3 >>= toRatio)
+                    <*> ((nthArg 4 >>= toRatio) `mplus` pure 1.0)
+                )
+                  <|> (nthArg 1 >>= hexToRGB)
+              )
+    ),
+    ( "str",
+      makeFunction $ do
+        val <- nthArg 1
+        VString <$> (fromVal val `mplus` pure (repr val))
+    ),
+    ( "symbol",
+      makeFunction $ do
+        (t :: Text) <- nthArg 1
+        vs <- drop 1 <$> allArgs
+        variants <-
+          mapM
+            ( \case
+                VArray [VString k, VString v] ->
+                  pure (Set.fromList (T.split (== '.') k), v)
+                _ -> fail "wrong type in symbol arguments"
+            )
+            vs
+        pure $ VSymbol $ Symbol t False variants
+    ),
+    ( "lorem",
+      makeFunction $ do
+        (num :: Int) <- nthArg 1
+        pure $ VString $ T.unwords $ take num loremWords
+    )
+  ]
+
+loremWords :: [Text]
+loremWords =
+  cycle $
+    T.words $
+      "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\
+      \ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut\
+      \ enim ad minim veniam, quis nostrud exercitation ullamco laboris\
+      \ nisi ut aliquip ex ea commodo consequat.  Duis aute irure dolor in\
+      \ reprehenderit in voluptate velit esse cillum dolore eu fugiat\
+      \ nulla pariatur. Excepteur sint occaecat cupidatat non proident,\
+      \ sunt in culpa qui officia deserunt mollit anim id est laborum."
+
+toRatio :: MonadFail m => Val -> m Rational
+toRatio (VRatio r) = pure r
+toRatio (VInteger i) = pure $ i % 255
+toRatio _ = fail "cannot convert to rational"
+
+hexToRGB :: MonadFail m => Val -> m Color
+hexToRGB (VString s) = do
+  let s' = T.dropWhile (== '#') s
+  parts <-
+    map (fmap (% 255) . readMaybe . T.unpack . ("0x" <>))
+      <$> case T.length s' of
+        3 -> pure $ T.chunksOf 1 s'
+        4 -> pure $ T.chunksOf 1 s'
+        6 -> pure $ T.chunksOf 2 s'
+        8 -> pure $ T.chunksOf 2 s'
+        _ -> fail "hex string must be 3, 4, 6, or 8 digits"
+  case parts of
+    [Just r, Just g, Just b] -> pure $ RGB r g b 1.0
+    [Just r, Just g, Just b, Just o] -> pure $ RGB r g b o
+    _ -> fail "could not read string as hex color"
+hexToRGB _ = fail "expected string"
+
+loadFileLazyBytes :: Monad m => FilePath -> MP m BL.ByteString
+loadFileLazyBytes fp = do
+  loadBytes <- evalLoadBytes <$> getState
+  lift $ BL.fromStrict <$> loadBytes fp
+
+loadFileText :: Monad m => FilePath -> MP m T.Text
+loadFileText fp = do
+  loadBytes <- evalLoadBytes <$> getState
+  lift $ TE.decodeUtf8 <$> loadBytes fp
+
+dataLoading :: [(Identifier, Val)]
+dataLoading =
+  [ ( "csv",
+      makeFunction $ do
+        fp <- nthArg 1
+        bs <- lift $ loadFileLazyBytes fp
+        case Csv.decode Csv.NoHeader bs of
+          Left e -> fail e
+          Right (v :: V.Vector (V.Vector String)) ->
+            pure $ VArray $ V.map (VArray . V.map (VString . T.pack)) v
+    ),
+    ( "json",
+      makeFunction $ do
+        fp <- nthArg 1
+        bs <- lift $ loadFileLazyBytes fp
+        case Aeson.eitherDecode bs of
+          Left e -> fail e
+          Right (v :: Val) -> pure v
+    ),
+    ( "yaml",
+      makeFunction $ do
+        fp <- nthArg 1
+        bs <- lift $ loadFileLazyBytes fp
+        case Yaml.decodeEither' (BL.toStrict bs) of
+          Left e -> fail $ show e
+          Right (v :: Val) -> pure v
+    ),
+    ( "read",
+      makeFunction $ do
+        fp <- nthArg 1
+        t <- lift $ loadFileText fp
+        pure $ VString t
+    ),
+    ("toml", makeFunction $ fail "unimplemented toml"),
+    ( "xml",
+      makeFunction $ do
+        fp <- nthArg 1
+        bs <- lift $ loadFileLazyBytes fp
+        case XML.parseLBS XML.def bs of
+          Left e -> fail $ show e
+          Right doc ->
+            pure $
+              VArray $
+                V.fromList $
+                  mapMaybe
+                    nodeToVal
+                    [XML.NodeElement (XML.documentRoot doc)]
+            where
+              showname n = XML.nameLocalName n
+              nodeToVal (XML.NodeElement elt) = Just $ eltToDict elt
+              nodeToVal (XML.NodeContent t) = Just $ VString t
+              nodeToVal _ = Nothing
+              eltToDict elt =
+                VDict $
+                  OM.fromList
+                    [ ("tag", VString $ showname (XML.elementName elt)),
+                      ( "attrs",
+                        VDict $
+                          OM.fromList $
+                            map
+                              (\(k, v) -> (Identifier (showname k), VString v))
+                              (M.toList $ XML.elementAttributes elt)
+                      ),
+                      ( "children",
+                        VArray $
+                          V.fromList $
+                            mapMaybe nodeToVal (XML.elementNodes elt)
+                      )
+                    ]
+    )
+  ]
diff --git a/src/Typst/Parse.hs b/src/Typst/Parse.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Parse.hs
@@ -0,0 +1,1160 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+
+module Typst.Parse
+  ( parseTypst,
+  )
+where
+
+import Control.Applicative (some)
+import Control.Monad (MonadPlus (mzero), guard, void, when)
+import Control.Monad.Identity (Identity)
+import Data.Char hiding (Space)
+import Data.Maybe (isJust)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Text.Parsec hiding (string)
+import qualified Text.Parsec as P
+import Text.Parsec.Expr
+import Text.Read (readMaybe)
+import Typst.Syntax
+
+-- import Debug.Trace
+
+parseTypst :: FilePath -> Text -> Either ParseError [Markup]
+parseTypst fp inp =
+  case runParser (spaces *> many pMarkup <* pEndOfContent) initialState fp inp of
+    Left e -> Left e
+    Right r -> Right r
+
+data PState = PState
+  { stIndent :: [Int],
+    stLineStartCol :: !Int,
+    stAllowNewlines :: !Int, -- allow newlines if > 0
+    stBeforeSpace :: Maybe (SourcePos, Text),
+    stContentBlockNesting :: Int
+  }
+  deriving (Show)
+
+initialState :: PState
+initialState =
+  PState
+    { stIndent = [],
+      stLineStartCol = 1,
+      stAllowNewlines = 0,
+      stBeforeSpace = Nothing,
+      stContentBlockNesting = 0
+    }
+
+type P = Parsec Text PState
+
+string :: String -> P String
+string = try . P.string
+
+ws :: P ()
+ws = do
+  p1 <- getPosition
+  inp <- getInput
+  allowNewlines <- stAllowNewlines <$> getState
+  let isSp c
+        | allowNewlines > 0 = c == ' ' || c == '\t' || c == '\n' || c == '\r'
+        | otherwise = c == ' ' || c == '\t'
+  ( skipMany1 (void (satisfy isSp) <|> void pComment)
+      *> updateState (\st -> st {stBeforeSpace = Just (p1, inp)})
+    )
+    <|> updateState (\st -> st {stBeforeSpace = Nothing})
+
+lexeme :: P a -> P a
+lexeme pa = pa <* ws
+
+sym :: String -> P String
+sym = lexeme . string
+
+op :: String -> P ()
+op s = try $ lexeme $ do
+  void $ string s
+  when
+    ( s == "+"
+        || s == "-"
+        || s == "*"
+        || s == "/"
+        || s == "="
+        || s == "<"
+        || s == ">"
+        || s == "!"
+    )
+    $ notFollowedBy (char '=')
+  when (s == "-") $
+    notFollowedBy (char '>') -- arrows
+  when (s == "<") $
+    notFollowedBy (char '-' <|> char '=') -- arrows
+  when (s == "=") $
+    notFollowedBy (char '>' <|> char '=')
+
+withNewlines :: P a -> P a
+withNewlines pa = do
+  updateState $ \st -> st {stAllowNewlines = stAllowNewlines st + 1}
+  res <- pa
+  updateState $ \st -> st {stAllowNewlines = stAllowNewlines st - 1}
+  pure res
+
+inParens :: P a -> P a
+inParens pa = withNewlines (between (sym "(") (char ')') pa) <* ws
+
+inBraces :: P a -> P a
+inBraces pa = withNewlines (between (sym "{") (char '}') pa) <* ws
+
+pMarkup :: P Markup
+pMarkup =
+  pSpace
+    <|> pHeading
+    <|> pComment
+    <|> pEol
+    <|> pHardbreak
+    <|> pStrong
+    <|> pEmph
+    <|> pEquation
+    <|> pListItem
+    <|> pUrl
+    <|> pText
+    <|> pRawBlock
+    <|> pRawInline
+    <|> pEscaped
+    <|> pNbsp
+    <|> pDash
+    <|> pEllipsis
+    <|> pQuote
+    <|> pLabelInContent
+    <|> pRef
+    <|> pHash
+    <|> pBracketed
+    <|> pSymbol
+
+-- We need to group paired brackets or the closing bracketed may be
+-- taken to close a pContent block:
+pBracketed :: P Markup
+pBracketed =
+  Bracketed <$> try (between (char '[') (char ']') (many pMarkup))
+
+pSymbol :: P Markup
+pSymbol = do
+  blockNesting <- stContentBlockNesting <$> getState
+  let isSpecial' c = isSpecial c && (c /= ']' || blockNesting == 0)
+  Text . T.singleton <$> satisfy isSpecial'
+
+-- equation ::= ('$' math* '$') | ('$ ' math* ' $')
+pEquation :: P Markup
+pEquation = do
+  void $ char '$'
+  withNewlines $ do
+    display <- option False $ True <$ lookAhead space
+    ws
+    maths <- many pMath
+    void $ char '$'
+    pure $ Equation display maths
+
+mathOperatorTable :: [[Operator Text PState Identity Markup]]
+mathOperatorTable =
+  [ -- precedence 6
+    [ Infix (attachBottom <$ op "_") AssocLeft,
+      Infix (attachTop <$ op "^") AssocLeft
+    ],
+    -- precedence 5
+    [ Postfix
+        ( try $ do
+            mbBeforeSpace <- stBeforeSpace <$> getState
+            -- NOTE: can't have space before () or [] arg in a
+            -- function call! to prevent bugs with e.g. 'if 2<3 [...]'.
+            guard $ mbBeforeSpace == Nothing
+            args <- mGrouped '(' ')' True
+            pure $ \expr -> MGroup Nothing Nothing [expr, args]
+        )
+    ],
+    -- precedence 3
+    [ Infix (makeFrac <$ op "/") AssocLeft
+    ]
+  ]
+
+attachBottom :: Markup -> Markup -> Markup
+attachBottom base x = MAttach (Just (hideOuterParens x)) Nothing base
+
+attachTop :: Markup -> Markup -> Markup
+attachTop (MAttach x Nothing y) z = MAttach x (Just (hideOuterParens z)) y
+attachTop base x = MAttach Nothing (Just (hideOuterParens x)) base
+
+makeFrac :: Markup -> Markup -> Markup
+makeFrac x y = MFrac x (hideOuterParens y)
+
+hideOuterParens :: Markup -> Markup
+hideOuterParens (MGroup (Just "(") (Just ")") x) = MGroup Nothing Nothing x
+hideOuterParens x = x
+
+mathExpressionTable :: [[Operator Text PState Identity Expr]]
+mathExpressionTable = take 16 (cycle [[fieldAccess], [mathFunctionCall]])
+
+mathFunctionCall :: Operator Text PState Identity Expr
+mathFunctionCall =
+  Postfix
+    ( do
+        mbBeforeSpace <- stBeforeSpace <$> getState
+        -- NOTE: can't have space before () or [] arg in a
+        -- function call! to prevent bugs with e.g. 'if 2<3 [...]'.
+        guard $ mbBeforeSpace == Nothing
+        args <- mArgs
+        pure $ \expr -> FuncCall expr args
+    )
+
+mExpr :: P Markup
+mExpr = Code <$> getPosition <*> pMathExpr
+
+pMathExpr :: P Expr
+pMathExpr = buildExpressionParser mathExpressionTable (pMathIdent <|> pLiteral)
+
+pMathIdent :: P Expr
+pMathIdent =
+  (Ident <$> pMathIdentifier)
+    <|> ( do
+            void $ char '√'
+            (Ident (Identifier "root") <$ lookAhead (char '('))
+              <|> ( do
+                      x <- pMath
+                      pure $
+                        FuncCall
+                          (Ident (Identifier "root"))
+                          [NormalArg (Block (Content [x]))]
+                  )
+        )
+
+pMathIdentifier :: P Identifier
+pMathIdentifier = lexeme $ try $ do
+  c <- satisfy isIdentStart
+  cs <- many1 $ satisfy isMathIdentContinue
+  pure $ Identifier $ T.pack (c : cs)
+
+isMathIdentContinue :: Char -> Bool
+isMathIdentContinue c = isIdentContinue c && c /= '_' && c /= '-'
+
+pMath :: P Markup
+pMath = buildExpressionParser mathOperatorTable pBaseMath
+  where
+    pBaseMath =
+      mNumber
+        <|> mLiteral
+        <|> mEscaped
+        <|> mBreak
+        <|> mAlignPoint
+        <|> mExpr
+        <|> mGroup
+        <|> mCode
+        <|> mMid
+        <|> mSymbol
+
+mGroup :: P Markup
+mGroup =
+  mGrouped '(' ')' False
+    <|> mGrouped '{' '}' False
+    <|> mGrouped '[' ']' False
+    <|> mGrouped '|' '|' True
+
+mGrouped :: Char -> Char -> Bool -> P Markup
+mGrouped op' cl requireMatch = withNewlines $ try $ do
+  void $ sym [op']
+  res <- many (notFollowedBy (char cl) *> pMath)
+  (MGroup (Just (T.singleton op')) (Just (T.singleton cl)) res <$ void (sym [cl]))
+    <|> (MGroup (Just (T.singleton op')) Nothing res <$ guard (not requireMatch))
+
+mNumber :: P Markup
+mNumber = lexeme $ do
+  ds <- T.pack <$> many1 digit
+  opt <-
+    option
+      mempty
+      ( do
+          e <- char '.'
+          es <- many1 digit
+          pure $ T.pack (e : es)
+      )
+  pure $ Text (ds <> opt)
+
+mLiteral :: P Markup
+mLiteral = do
+  mbBeforeSpace <- stBeforeSpace <$> getState
+  String t <- pStr
+  -- ensure space in e.g. x "is natural":
+  mbAfterSpace <- stBeforeSpace <$> getState
+  pure $
+    Text $
+      (maybe "" (const " ") mbBeforeSpace)
+        <> t
+        <> (maybe "" (const " ") mbAfterSpace)
+
+mEscaped :: P Markup
+mEscaped = Text . T.singleton <$> lexeme (try pEsc)
+
+mBreak :: P Markup
+mBreak = HardBreak <$ lexeme (char '\\' *> skipMany (satisfy (isSpace)))
+
+-- we don't need to check for following whitespace, because
+-- anything else would have been parsed by mEsc.
+-- but we do skip following whitespace, since \160 wouldn't be gobbled by lexeme...
+
+mAlignPoint :: P Markup
+mAlignPoint = MAlignPoint <$ sym "&"
+
+-- Math args can't have a content block; they can use semicolons
+-- to separate array args.
+mArgs :: P [Arg]
+mArgs =
+  inParens $
+    many (mKeyValArg <|> mArrayArg <|> mNormArg <|> mMathArg)
+  where
+    sep = void (sym ",") <|> void (lookAhead (char ')'))
+    mNormArg =
+      NormalArg <$> (char '#' *> pExpr <* sep)
+    mKeyValArg = do
+      ident <- try $ pIdentifier <* sym ":"
+      KeyValArg ident
+        <$> ( (char '#' *> pExpr <* sep)
+                <|> Block . Content <$> mathContent
+            )
+    mathContent = do
+      xs <- maths
+      if null xs
+        then void $ sym ","
+        else sep
+      pure xs
+    mMathArg = BlockArg <$> mathContent
+    mArrayArg = try $ do
+      let pRow = sepBy' (toGroup <$> maths) (sym ",")
+      rows <- many1 $ try (pRow <* sym ";")
+      -- parse any regular items and form a last row
+      lastrow <- many (toGroup <$> mathContent)
+      let rows' =
+            if null lastrow
+              then rows
+              else rows ++ [lastrow]
+      pure $ ArrayArg rows'
+    maths = many (notFollowedBy (oneOf ",;)") *> notFollowedBy mKeyValArg *> pMath)
+    toGroup [m] = m
+    toGroup ms = MGroup Nothing Nothing ms
+    -- special sepBy' with an added try:
+    sepBy' p s = sepBy1' p s <|> pure []
+    sepBy1' p s = do
+      x <- p
+      xs <- many (try (s *> p))
+      pure (x : xs)
+
+mCode :: P Markup
+mCode = char '#' *> (Code <$> getPosition <*> pBasicExpr)
+
+mMid :: P Markup
+mMid = try $ do
+  stBeforeSpace <$> getState >>= guard . isJust
+  void $ char '|' *> space *> ws
+  pure $ MGroup Nothing Nothing [Nbsp, Text "|", Nbsp]
+
+mSymbol :: P Markup
+mSymbol =
+  Text
+    <$> lexeme
+      ( ("≠" <$ string "!=")
+          <|> ("≥" <$ string ">=")
+          <|> ("≤" <$ string "<=")
+          <|> ("←" <$ string "<-")
+          <|> ("→" <$ string "->")
+          <|> ("⇐" <$ string "<=")
+          <|> ("⇒" <$ string "=>")
+          <|> ("⟵" <$ string "<--")
+          <|> ("⟶" <$ string "-->")
+          <|> ("⟸" <$ string "<==")
+          <|> ("⟹" <$ string "==>")
+          <|> ("…" <$ string "...")
+          <|> ("′" <$ char '\'')
+          <|> ( T.singleton
+                  <$> satisfy (\c -> not (isSpace c) && c /= '$' && c /= '\\')
+              )
+      )
+
+withIndent :: Int -> P a -> P a
+withIndent indent pa = do
+  oldIndent <- stIndent <$> getState
+  updateState $ \st -> st {stIndent = indent : oldIndent}
+  ms <- pa
+  updateState $ \st -> st {stIndent = oldIndent}
+  pure ms
+
+-- list ::= '-' space markup
+-- enum ::= (digit+ '.' | '+') space markup
+-- desc ::= '/' space markup ':' space markup
+pListItem :: P Markup
+pListItem = do
+  col <- sourceColumn <$> getPosition
+  startLine <- stLineStartCol <$> getState
+  guard (col == startLine)
+  try
+    ( do
+        void $ char '-'
+        void (char ' ') <|> pBlankline
+        BulletListItem <$> withIndent col (many pMarkup)
+    )
+    <|> try
+      ( do
+          start <- (Nothing <$ char '+') <|> (Just <$> enumListStart)
+          void (char ' ') <|> pBlankline
+          EnumListItem start <$> withIndent col (many pMarkup)
+      )
+    <|> try
+      ( do
+          -- desc list
+          void (char '/')
+          void (many1 (char ' '))
+          term <- manyTill pMarkup (char ':')
+          skipMany spaceChar
+          optional pBlankline
+          DescListItem term <$> withIndent col (many pMarkup)
+      )
+
+enumListStart :: P Int
+enumListStart = do
+  ds <- many1 digit
+  void $ char '.'
+  case readMaybe ds of
+    Nothing -> fail $ "could not read " <> ds <> " as digits"
+    Just x -> pure x
+
+-- line-comment = '//' (!unicode(Newline))*
+-- block-comment = '/*' (. | block-comment)* '*/'
+pComment :: P Markup
+pComment = Comment <$ (pLineComment <|> pBlockComment)
+
+pLineComment :: P ()
+pLineComment = do
+  void $ string "//"
+  skipMany (satisfy (\c -> c /= '\n' && c /= '\r'))
+  void endOfLine
+
+pBlockComment :: P ()
+pBlockComment = do
+  void $ string "/*"
+  void $
+    manyTill
+      ( pBlockComment
+          <|> pLineComment
+          <|> void anyChar
+      )
+      (string "*/")
+
+pSpace :: P Markup
+pSpace = Space <$ some (satisfy (\c -> isSpace c && c /= '\r' && c /= '\n'))
+
+pEol :: P Markup
+pEol = do
+  pBaseEol
+  (ParBreak <$ many1 pBaseEol)
+    <|> (ParBreak <$ pEndOfContent)
+    <|> pure SoftBreak
+
+pBaseEol :: P ()
+pBaseEol = try $ do
+  void endOfLine
+  -- fail if we can't indent enough
+  indents <- stIndent <$> getState
+  case indents of
+    (i : _) -> void (try (count i (char ' '))) <|> pBlankline
+    [] -> pure ()
+  eatPrefixSpaces
+
+eatPrefixSpaces :: P ()
+eatPrefixSpaces = do
+  skipMany spaceChar
+  col <- sourceColumn <$> getPosition
+  updateState $ \st -> st {stLineStartCol = col}
+
+spaceChar :: P Char
+spaceChar = satisfy (\c -> c == ' ' || c == '\t')
+
+pHardbreak :: P Markup
+pHardbreak =
+  HardBreak <$ try (char '\\' *> (void spaceChar <|> pBaseEol) *> skipMany spaceChar)
+
+pBlankline :: P ()
+pBlankline = try $ do
+  skipMany spaceChar
+  void (lookAhead (endOfLine)) <|> pEndOfContent
+
+pRawInline :: P Markup
+pRawInline =
+  RawInline . T.pack
+    <$> (char '`' *> manyTill anyChar (void (char '`') <|> eof))
+
+pRawBlock :: P Markup
+pRawBlock = do
+  void $ string "```"
+  numticks <- (+ 3) . length <$> many (char '`')
+  lang <- T.pack <$> (many alphaNum <* optional (char ' '))
+  optional $ try $ skipMany (char ' ') *> pEol
+  let nl = newline <* optionalGobbleIndent
+  code <-
+    T.pack
+      <$> manyTill
+        (nl <|> anyChar)
+        (string (replicate numticks '`'))
+  skipMany (char '`')
+  pure $ RawBlock lang code
+
+optionalGobbleIndent :: P ()
+optionalGobbleIndent = do
+  indents <- stIndent <$> getState
+  case indents of
+    (i : _) -> gobble i
+    [] -> pure ()
+  where
+    gobble :: Int -> P ()
+    gobble 0 = pure ()
+    gobble n = (char ' ' *> gobble (n - 1)) <|> pure ()
+
+pStrong :: P Markup
+pStrong = Strong <$> (char '*' *> manyTill pMarkup (char '*'))
+
+pEmph :: P Markup
+pEmph = Emph <$> (char '_' *> manyTill pMarkup (char '_'))
+
+pHeading :: P Markup
+pHeading = try $ do
+  col <- sourceColumn <$> getPosition
+  lineStartCol <- stLineStartCol <$> getState
+  guard (col == lineStartCol)
+  lev <- length <$> many1 (char '=')
+  void (many1 (char ' ')) <|> void (lookAhead endOfLine)
+  -- Note: == hi _foo
+  -- bar_ is parsed as a heading with "hi emph(foobar)"
+  ms <- manyTill pMarkup (    void pEol
+                          <|> pEndOfContent
+                          <|> void (lookAhead (try (spaces *> pLabel)))
+                          <|> void (lookAhead (char ']')))
+  skipMany spaceChar
+  pure $ Heading lev ms
+
+pUrl :: P Markup
+pUrl = try $ do
+  prot <- T.pack <$> (string "http://" <|> string "https://")
+  rest <- T.pack <$> pNonspaceWithBalancedBrackets 0 0 0
+  pure $ Url $ prot <> rest
+
+pNonspaceWithBalancedBrackets :: Int -> Int -> Int -> P [Char]
+pNonspaceWithBalancedBrackets parens brackets braces =
+  ((:) <$> char '(' <*> pNonspaceWithBalancedBrackets (parens + 1) brackets braces)
+    <|> ((:) <$> (guard (parens > 0) *> char ')') <*> pNonspaceWithBalancedBrackets (parens - 1) brackets braces)
+    <|> ((:) <$> char '[' <*> pNonspaceWithBalancedBrackets parens (brackets + 1) braces)
+    <|> ((:) <$> (guard (brackets > 0) *> char ']') <*> pNonspaceWithBalancedBrackets parens (brackets - 1) braces)
+    <|> ((:) <$> char '{' <*> pNonspaceWithBalancedBrackets parens brackets (braces + 1))
+    <|> ((:) <$> (guard (braces > 0) *> char '}') *> pNonspaceWithBalancedBrackets parens brackets (braces - 1))
+    <|> (:) <$> noneOf " \t\r\n()[]{}" <*> pNonspaceWithBalancedBrackets parens brackets braces
+    <|> pure []
+
+pText :: P Markup
+pText =
+  Text . T.pack
+    <$> some
+      ( satisfy (\c -> not (isSpace c || isSpecial c))
+          <|> try ((char '*' <|> char '_') <* lookAhead alphaNum)
+      )
+
+pEscaped :: P Markup
+pEscaped = Text . T.singleton <$> pEsc
+
+pEsc :: P Char
+pEsc =
+  char '\\' *> (uniEsc <|> satisfy (not . isSpace))
+
+pStrEsc :: P Char
+pStrEsc =
+  try $
+    char '\\'
+      *> ( uniEsc
+             <|> satisfy isSpecial
+             <|> ('\n' <$ char 'n')
+             <|> ('\t' <$ char 't')
+             <|> ('\r' <$ char 'r')
+         )
+
+uniEsc :: P Char
+uniEsc = chr <$> (char 'u' *> char '{' *> hexnum <* char '}')
+  where
+    hexnum :: P Int
+    hexnum = do
+      ds <- many1 hexDigit
+      case readMaybe ("0x" ++ ds) of
+        Just i
+          | i <= 1114112 -> pure i
+          | otherwise -> pure 0xFFFD
+        Nothing -> fail $ "Could not read hex number " ++ ds
+
+pNbsp :: P Markup
+pNbsp = Nbsp <$ char '~'
+
+pDash :: P Markup
+pDash = do
+  void $ char '-'
+  (Shy <$ char '?')
+    <|> (char '-' *> ((EmDash <$ char '-') <|> pure EnDash))
+    <|> pure (Text "-")
+
+pEllipsis :: P Markup
+pEllipsis = do
+  void $ char '.'
+  (Ellipsis <$ string "..") <|> pure (Text ".")
+
+pQuote :: P Markup
+pQuote = Quote <$> (char '\'' <|> char '"')
+
+pLabelInContent :: P Markup
+pLabelInContent = Code <$> getPosition <*> pLabel
+
+pLabel :: P Expr
+pLabel =
+  Label . T.pack
+    <$> try
+      ( char '<'
+          *> many1 (satisfy isIdentContinue <|> char '_' <|> char '.')
+          <* char '>'
+      )
+
+pRef :: P Markup
+pRef =
+  Ref
+    <$> (char '@' *> (T.pack <$> many1 (satisfy isIdentContinue <|> char '_')))
+    <*> option (Literal Auto) (Block <$> pContent)
+
+-- "If a character would continue the expression but should be interpreted as
+-- text, the expression can forcibly be ended with a semicolon (;)."
+-- "A few kinds of expressions are not compatible with the hashtag syntax
+-- (e.g. binary operator expressions). To embed these into markup, you
+-- can use parentheses, as in #(1 + 2)." Hence pBasicExpr not pExpr.
+pHash :: P Markup
+pHash = do
+  void $ char '#'
+  res <- Code <$> getPosition <*> pBasicExpr <* optional (sym ";")
+  -- rewind if we gobbled space:
+  mbBeforeSpace <- stBeforeSpace <$> getState
+  case mbBeforeSpace of
+    Nothing -> pure ()
+    Just (pos, inp) -> do
+      setPosition pos
+      setInput inp
+  pure res
+
+isSpecial :: Char -> Bool
+isSpecial '\\' = True
+isSpecial '[' = True
+isSpecial ']' = True
+isSpecial '#' = True
+isSpecial '-' = True
+isSpecial '.' = True
+isSpecial '"' = True
+isSpecial '\'' = True
+isSpecial '*' = True
+isSpecial '_' = True
+isSpecial '`' = True
+isSpecial '$' = True
+isSpecial '<' = True
+isSpecial '>' = True
+isSpecial '@' = True
+isSpecial '/' = True
+isSpecial ':' = True
+isSpecial '~' = True
+isSpecial '=' = True
+isSpecial '(' = True -- so we don't gobble ( before URLs
+isSpecial _ = False
+
+pIdentifier :: P Identifier
+pIdentifier = lexeme $ try $ do
+  c <- satisfy isIdentStart
+  cs <- many $ satisfy isIdentContinue
+  pure $ Identifier $ T.pack (c : cs)
+
+-- ident_start ::= unicode(XID_Start)
+-- ID_Start characters are derived from the Unicode General_Category of
+-- uppercase letters, lowercase letters, titlecase letters, modifier letters,
+-- other letters, letter numbers, plus Other_ID_Start, minus Pattern_Syntax and
+-- Pattern_White_Space code points.
+isIdentStart :: Char -> Bool
+isIdentStart c =
+  case generalCategory c of
+    UppercaseLetter -> True
+    LowercaseLetter -> True
+    TitlecaseLetter -> True
+    ModifierLetter -> True
+    OtherLetter -> True
+    LetterNumber -> True
+    _ -> False
+
+-- ident_continue ::= unicode(XID_Continue) | '-'
+-- ID_Continue characters include ID_Start characters, plus characters having
+-- the Unicode General_Category of nonspacing marks, spacing combining marks,
+-- decimal number, connector punctuation, plus Other_ID_Continue, minus
+-- Pattern_Syntax and Pattern_White_Space code points.
+isIdentContinue :: Char -> Bool
+isIdentContinue c =
+  isIdentStart c
+    || c == '-'
+    || c == '_'
+    || case generalCategory c of
+      NonSpacingMark -> True
+      SpacingCombiningMark -> True
+      DecimalNumber -> True
+      ConnectorPunctuation -> True
+      _ -> False
+
+pKeyword :: String -> P ()
+pKeyword t = lexeme $ try $ string t *> notFollowedBy (satisfy isIdentContinue)
+
+-- NOTE: there can be field access lookups that require identifiers like
+-- 'not'.
+-- keywords :: [Text]
+-- keywords = ["none", "auto", "true", "false", "not", "and", "or", "let",
+--             "set", "show", "wrap", "if", "else", "for", "in", "as", "while",
+--             "break", "continue", "return", "import", "include", "from"]
+
+pExpr :: P Expr
+pExpr = buildExpressionParser operatorTable pBasicExpr
+
+-- A basic expression excludes the unary and binary operators outside of parens,
+-- but includes field access and function application. Needed for pHash.
+pBasicExpr :: P Expr
+pBasicExpr = buildExpressionParser basicOperatorTable pBaseExpr
+
+pQualifiedIdentifier :: P Expr
+pQualifiedIdentifier =
+  buildExpressionParser (replicate 4 [fieldAccess]) pIdent
+
+pBaseExpr :: P Expr
+pBaseExpr =
+  pLiteral
+    <|> pKeywordExpr
+    <|> pFuncExpr
+    <|> pBindExpr
+    <|> pIdent
+    <|> pArrayExpr
+    <|> pDictExpr
+    <|> inParens pExpr
+    <|> (Block . Content . (: []) <$> pEquation)
+    <|> pLabel
+    <|> pBlock
+
+pLiteral :: P Expr
+pLiteral =
+  Literal
+    <$> ( pNone
+            <|> pAuto
+            <|> pBoolean
+            <|> pNumeric
+            <|> pStr
+        )
+
+fieldAccess :: Operator Text PState Identity Expr
+fieldAccess = Postfix (FieldAccess <$> try (sym "." *> pIdent))
+
+-- don't allow space after .
+restrictedFieldAccess :: Operator Text PState Identity Expr
+restrictedFieldAccess = Postfix (FieldAccess <$> try (char '.' *> pIdent))
+
+functionCall :: Operator Text PState Identity Expr
+functionCall =
+  Postfix
+    ( do
+        mbBeforeSpace <- stBeforeSpace <$> getState
+        -- NOTE: can't have space before () or [] arg in a
+        -- function call! to prevent bugs with e.g. 'if 2<3 [...]'.
+        guard $ mbBeforeSpace == Nothing
+        args <- pArgs
+        pure $ \expr -> FuncCall expr args
+    )
+
+-- The reason we cycle field access and function call
+-- is that a postfix operator will not
+-- be repeatable at the same precedence level...see docs for
+-- buildExpressionParser.
+basicOperatorTable :: [[Operator Text PState Identity Expr]]
+basicOperatorTable =
+  take 16 (cycle [[restrictedFieldAccess], [functionCall]])
+
+operatorTable :: [[Operator Text PState Identity Expr]]
+operatorTable =
+  -- precedence 8 (real field access, perhaps  with space after .)
+  take 12 (cycle [[fieldAccess], [functionCall]])
+    ++
+    -- precedence 7 (repeated because of parsec's quirks with postfix, prefix)
+    replicate 6 [Postfix (ToPower <$> try (char 'e' *> notFollowedBy letter *> pExpr))]
+    ++ replicate 6 [Prefix (Negated <$ op "-"), Prefix (id <$ op "+")]
+    ++ [
+         -- precedence 6
+         [ Infix (Times <$ op "*") AssocLeft,
+           Infix (Divided <$ op "/") AssocLeft
+         ],
+         -- precedence 5
+         [ Infix (Plus <$ op "+") AssocLeft,
+           Infix (Minus <$ op "-") AssocLeft
+         ],
+         -- precedence 4
+         [ Infix (Equals <$ op "==") AssocLeft,
+           Infix ((\x y -> Not (Equals x y)) <$ op "!=") AssocLeft,
+           Infix (LessThan <$ op "<") AssocLeft,
+           Infix (LessThanOrEqual <$ op "<=") AssocLeft,
+           Infix (GreaterThan <$ op ">") AssocLeft,
+           Infix (GreaterThanOrEqual <$ op ">=") AssocLeft,
+           Infix (InCollection <$ pKeyword "in") AssocLeft,
+           Infix
+             ( (\x y -> Not (InCollection x y))
+                 <$ try (pKeyword "not" *> pKeyword "in")
+             )
+             AssocLeft
+         ],
+         -- precedence 3
+         [ Prefix (Not <$ pKeyword "not"),
+           Infix (And <$ pKeyword "and") AssocLeft
+         ],
+         -- precedence 2
+         [ Infix (Or <$ pKeyword "or") AssocLeft
+         ],
+         -- precedence 1
+         [ Infix (Assign <$ op "=") AssocRight,
+           Infix ((\x y -> Assign x (Plus x y)) <$ op "+=") AssocRight,
+           Infix ((\x y -> Assign x (Minus x y)) <$ op "-=") AssocRight,
+           Infix ((\x y -> Assign x (Times x y)) <$ op "*=") AssocRight,
+           Infix ((\x y -> Assign x (Divided x y)) <$ op "/=") AssocRight
+         ]
+       ]
+
+pNone :: P Literal
+pNone = None <$ pKeyword "none"
+
+pAuto :: P Literal
+pAuto = Auto <$ pKeyword "auto"
+
+pBoolean :: P Literal
+pBoolean =
+  (Boolean True <$ pKeyword "true") <|> (Boolean False <$ pKeyword "false")
+
+pNumber :: P (Either Integer Double)
+pNumber = try $ do
+  pref <- string "0b" <|> string "0x" <|> string "0o" <|> pure ""
+  case pref of
+    "0b" -> do
+      nums <- many1 ((1 <$ char '1') <|> (0 <$ char '0'))
+      pure $ Left $ sum $ zipWith (*) (reverse nums) (map (2 ^) [(0 :: Integer) ..])
+    "0x" -> do
+      num <- many1 hexDigit
+      case readMaybe ("0x" ++ num) of
+        Just (i :: Integer) -> pure $ Left i
+        _ -> fail $ "could not read " <> num <> " as hex digits"
+    "0o" -> do
+      num <- many1 octDigit
+      case readMaybe ("0o" ++ num) of
+        Just (i :: Integer) -> pure $ Left i
+        _ -> fail $ "could not read " <> num <> " as octal digits"
+    _ -> do
+      as <- many1 digit <|> ("0" <$ lookAhead (try (char '.' *> digit)))
+      pe <- option [] $ string "."
+      bs <- many digit
+      es <-
+        option
+          ""
+          ( do
+              void $ try $ char 'e' *> lookAhead (digit <|> char '-')
+              minus <- option [] $ count 1 (char '-')
+              ds <- many1 digit
+              pure ("e" ++ minus ++ ds)
+          )
+      let num = pref ++ as ++ pe ++ bs ++ es
+      case readMaybe num of
+        Just (i :: Integer) -> pure $ Left i
+        Nothing ->
+          case readMaybe num of
+            Just (d :: Double) -> pure $ Right d
+            Nothing -> fail $ "could not read " <> num <> " as integer"
+
+pNumeric :: P Literal
+pNumeric = lexeme $ do
+  result <- pNumber
+  ( do
+      unit <- pUnit
+      case result of
+        Left i -> pure $ Numeric (fromIntegral i) unit
+        Right d -> pure $ Numeric d unit
+    )
+    <|> case result of
+      Left i -> pure $ Int i
+      Right d -> pure $ Float d
+
+pStr :: P Literal
+pStr = lexeme $ do
+  void $ char '"'
+  String . T.pack <$> manyTill (pStrEsc <|> noneOf "\"\r\n") (char '"')
+
+pUnit :: P Unit
+pUnit =
+  (Percent <$ sym "%")
+    <|> (Pt <$ pKeyword "pt")
+    <|> (Mm <$ pKeyword "mm")
+    <|> (Cm <$ pKeyword "cm")
+    <|> (In <$ pKeyword "in")
+    <|> (Deg <$ pKeyword "deg")
+    <|> (Rad <$ pKeyword "rad")
+    <|> (Em <$ pKeyword "em")
+    <|> (Fr <$ pKeyword "fr")
+
+pIdent :: P Expr
+pIdent = Ident <$> pIdentifier
+
+pBlock :: P Expr
+pBlock = Block <$> (pCodeBlock <|> pContent)
+
+pCodeBlock :: P Block
+pCodeBlock = CodeBlock <$> inBraces pCode
+
+pCode :: P [Expr]
+pCode = sepEndBy pExpr (void (sym ";") <|> ws)
+
+-- content-block ::= '[' markup ']'
+pContent :: P Block
+pContent = do
+  void $ char '['
+  col <- sourceColumn <$> getPosition
+  oldLineStartCol <- stLineStartCol <$> getState
+  updateState $ \st ->
+    st
+      { stLineStartCol = col,
+        stContentBlockNesting =
+          stContentBlockNesting st + 1
+      }
+  ms <- manyTill pMarkup (char ']')
+  ws
+  updateState $ \st ->
+    st
+      { stLineStartCol = oldLineStartCol,
+        stContentBlockNesting =
+          stContentBlockNesting st - 1
+      }
+  pure $ Content ms
+
+pEndOfContent :: P ()
+pEndOfContent =
+  eof <|> do
+    blockNesting <- stContentBlockNesting <$> getState
+    if blockNesting > 0
+      then void (lookAhead (char ']'))
+      else mzero
+
+-- array-expr ::= '(' ((expr ',') | (expr (',' expr)+ ','?))? ')'
+pArrayExpr :: P Expr
+pArrayExpr =
+  try $
+    inParens $
+      ( do
+          v <- pExpr
+          vs <- many $ try $ sym "," *> pExpr
+          if null vs
+            then void $ sym ","
+            else optional $ void $ sym ","
+          pure $ Array (v : vs)
+      )
+        <|> (Array [] <$ optional (void $ sym ","))
+
+-- dict-expr ::= '(' (':' | (pair (',' pair)* ','?)) ')'
+-- pair ::= (ident | str) ':' expr
+pDictExpr :: P Expr
+pDictExpr = try $ inParens (pEmptyDict <|> pNonemptyDict)
+  where
+    pEmptyDict = Dict mempty <$ sym ":"
+    pNonemptyDict = Dict <$> sepEndBy1 pPair (sym ",")
+    pPair = (,) <$> pKey <*> try (sym ":" *> pExpr)
+    pKey = pIdentifier <|> pStrKey
+    pStrKey = do
+      String t <- pStr
+      pure $ Identifier t
+
+-- func-expr ::= (params | ident) '=>' expr
+pFuncExpr :: P Expr
+pFuncExpr = try $ FuncExpr <$> pParamsOrIdent <*> (sym "=>" *> pExpr)
+  where
+    pParamsOrIdent =
+      pParams
+        <|> ((\i -> [NormalParam i]) <$> pIdentifier)
+        <|> ([SkipParam] <$ sym "_")
+
+pKeywordExpr :: P Expr
+pKeywordExpr =
+  pLetExpr
+    <|> pSetExpr
+    <|> pShowExpr
+    <|> pIfExpr
+    <|> pWhileExpr
+    <|> pForExpr
+    <|> pImportExpr
+    <|> pIncludeExpr
+    <|> pBreakExpr
+    <|> pContinueExpr
+    <|> pReturnExpr
+
+-- args ::= ('(' (arg (',' arg)* ','?)? ')' content-block*) | content-block+
+pArgs :: P [Arg]
+pArgs = do
+  void $ lookAhead (char '(' <|> char '[')
+  args <- option [] $ inParens $ sepEndBy pArg (sym ",")
+  blocks <- many $ do
+    -- make sure we haven't had a space
+    skippedSpaces <- isJust . stBeforeSpace <$> getState
+    if skippedSpaces
+      then mzero
+      else do
+        Content ms <- pContent
+        pure ms
+  pure $ args ++ map BlockArg blocks
+
+-- arg ::= (ident ':')? expr
+pArg :: P Arg
+pArg = pKeyValArg <|> pSpreadArg <|> pNormalArg
+  where
+    pKeyValArg = KeyValArg <$> try (pIdentifier <* sym ":") <*> pExpr
+    pNormalArg =
+      NormalArg
+        <$> ((Block . Content . (: []) <$> lexeme (pRawBlock <|> pRawInline)) <|> pExpr)
+    pSpreadArg = SpreadArg <$> try (string ".." *> pExpr)
+
+-- params ::= '(' (param (',' param)* ','?)? ')'
+pParams :: P [Param]
+pParams = inParens $ sepEndBy pParam (sym ",")
+
+-- param ::= ident (':' expr)?
+pParam :: P Param
+pParam =
+  pSinkParam <|> pDestructuringParam <|> pNormalOrDefaultParam <|> pSkipParam
+  where
+    pSinkParam =
+      SinkParam
+        <$> try
+          ( sym ".."
+              *> option Nothing (Just <$> pIdentifier)
+          )
+    pSkipParam = SkipParam <$ sym "_"
+    pNormalOrDefaultParam = do
+      i <- pIdentifier
+      (DefaultParam i <$> (sym ":" *> pExpr)) <|> pure (NormalParam i)
+    pDestructuringParam = do
+      DestructuringBind parts <- pDestructuringBind
+      pure $ DestructuringParam parts
+
+pBind :: P Bind
+pBind = pBasicBind <|> pDestructuringBind
+
+pBasicBind :: P Bind
+pBasicBind = BasicBind <$> try (pBindIdentifier <|> inParens pBindIdentifier)
+
+pBindIdentifier :: P (Maybe Identifier)
+pBindIdentifier = (Just <$> pIdentifier) <|> (Nothing <$ sym "_")
+
+pDestructuringBind :: P Bind
+pDestructuringBind =
+  inParens $
+    DestructuringBind <$> (pBindPart `sepEndBy` (sym ","))
+  where
+    pBindPart = do
+      sink <- option False $ True <$ string ".."
+      if sink
+        then do
+          ident <- option Nothing pBindIdentifier -- ..
+          pure $ Sink ident
+        else do
+          ident <- pBindIdentifier
+          case ident of
+            Nothing -> pure (Simple ident)
+            Just key ->
+              (WithKey key <$> (sym ":" *> pBindIdentifier))
+                <|> pure (Simple ident)
+
+-- let-expr ::= 'let' ident params? '=' expr
+pLetExpr :: P Expr
+pLetExpr = do
+  pKeyword "let"
+  bind <- pBind
+  case bind of
+    BasicBind mbname -> do
+      mbparams <- option Nothing $ Just <$> pParams
+      mbexpr <- option Nothing $ Just <$> (sym "=" *> pExpr)
+      case (mbparams, mbexpr, mbname) of
+        (Nothing, Nothing, _) -> pure $ Let bind (Literal None)
+        (Nothing, Just expr, _) -> pure $ Let bind expr
+        (Just params, Just expr, Just name) -> pure $ LetFunc name params expr
+        (Just _, Just _, Nothing) -> fail "expected name for function"
+        (Just _, Nothing, _) -> fail "expected expression for let binding"
+    _ -> Let bind <$> (sym "=" *> pExpr)
+
+-- set-expr ::= 'set' expr args
+pSetExpr :: P Expr
+pSetExpr = do
+  set <- pKeyword "set" *> (Set <$> pQualifiedIdentifier <*> pArgs)
+  addCondition <- option id $ pKeyword "if" *> ((\c x -> If [(c, x)]) <$> pExpr)
+  pure $ addCondition set
+
+pShowExpr :: P Expr
+pShowExpr = do
+  pKeyword "show"
+  from <- (Nothing <$ sym ":") <|> Just <$> (pBasicExpr <* sym ":")
+  to <- pBasicExpr
+  pure $ Show from to
+
+-- if-expr ::= 'if' expr block ('else' 'if' expr block)* ('else' block)?
+pIfExpr :: P Expr
+pIfExpr = do
+  a <- pIf
+  as <- many $ try (pKeyword "else" *> pIf)
+  finalElse <-
+    option [] $
+      -- we represent the final "else" as a conditional with expr True:
+      (: []) . (Literal (Boolean True),) <$> (pKeyword "else" *> pBlock)
+  return $ If (a : as ++ finalElse)
+  where
+    pIf = pKeyword "if" *> ((,) <$> pExpr <*> pBlock)
+
+-- while-expr ::= 'while' expr block
+pWhileExpr :: P Expr
+pWhileExpr = pKeyword "while" *> (While <$> pExpr <*> pBlock)
+
+-- for-expr ::= 'for' bind 'in' expr block
+pForExpr :: P Expr
+pForExpr =
+  pKeyword "for" *> (For <$> pBind <*> (pKeyword "in" *> pExpr) <*> pBlock)
+
+pImportExpr :: P Expr
+pImportExpr = pKeyword "import" *> (Import <$> pExpr <*> pImportItems)
+  where
+    pImportItems =
+      option NoIdentifiers $
+        sym ":"
+          *> ( (AllIdentifiers <$ sym "*")
+                 <|> (SomeIdentifiers <$> sepEndBy pIdentifier (sym ","))
+             )
+
+pBreakExpr :: P Expr
+pBreakExpr = Break <$ pKeyword "break"
+
+pContinueExpr :: P Expr
+pContinueExpr = Continue <$ pKeyword "continue"
+
+pReturnExpr :: P Expr
+pReturnExpr = do
+  pos <- getPosition
+  pKeyword "return"
+  pos' <- getPosition
+  if sourceLine pos' > sourceLine pos
+    then pure $ Return Nothing
+    else Return <$> (option Nothing (Just <$> pExpr))
+
+pIncludeExpr :: P Expr
+pIncludeExpr = Include <$> (pKeyword "include" *> pExpr)
+
+pBindExpr :: P Expr
+pBindExpr =
+  Binding <$> try (pBind <* lookAhead (op "="))
diff --git a/src/Typst/Regex.hs b/src/Typst/Regex.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Regex.hs
@@ -0,0 +1,131 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Typst.Regex
+  ( RE (..),
+    RegexMatch (..),
+    replaceRegex,
+    splitRegex,
+    makeLiteralRE,
+    makeRE,
+    match,
+    matchAll,
+    -- re-export
+    extract,
+  )
+where
+
+import qualified Data.Array as Array
+import Data.Text (Text)
+import qualified Data.Text as T
+import Data.Typeable (Typeable)
+import Text.Regex.TDFA (Regex, extract)
+import qualified Text.Regex.TDFA as TDFA
+import qualified Text.Regex.TDFA.Text as TDFA
+
+-- import Debug.Trace
+
+data RE = RE !Text !Regex
+  deriving (Typeable)
+
+instance Eq RE where
+  RE t1 _ == RE t2 _ = t1 == t2
+
+instance Ord RE where
+  compare (RE t1 _) (RE t2 _) = compare t1 t2
+
+instance Show RE where
+  show (RE t _) = "/" <> T.unpack t <> "/"
+
+data RegexMatch = RegexMatch
+  { matchStart :: Int,
+    matchEnd :: Int,
+    matchText :: Text,
+    matchCaptures :: [Text]
+  }
+  deriving (Eq, Ord, Typeable)
+
+replaceRegex :: RE -> Maybe Int -> (RegexMatch -> Text) -> Text -> Text
+replaceRegex (RE _ re) mbCount replaceFn strIn =
+  let matches = maybe id take mbCount $ TDFA.matchAll re strIn
+      getCaptures m =
+        map
+          (\(off, len) -> extract (off, len) strIn)
+          (drop 1 (Array.elems m))
+      go i [] = T.drop i strIn
+      go i (m : rest) =
+        seq i $
+          let (off, len) = m Array.! 0
+           in ( if off > i
+                  then slice i (off - i) strIn
+                  else mempty
+              )
+                <> replaceFn
+                  RegexMatch
+                    { matchStart = off,
+                      matchEnd = off + len,
+                      matchText = extract (off, len) strIn,
+                      matchCaptures = getCaptures m
+                    }
+                <> go (off + len) rest
+      slice pos len = T.take len . T.drop pos
+   in go 0 matches
+
+makeRE :: MonadFail m => Text -> m RE
+makeRE t =
+  RE t'
+    <$> either
+      fail
+      pure
+      (TDFA.compile compopts TDFA.defaultExecOpt t')
+  where
+    (caseSensitive, t') =
+      if "(?i)" `T.isPrefixOf` t
+        then (False, T.pack . go . T.unpack $ T.drop 4 t)
+        else (True, T.pack . go . T.unpack $ t)
+    compopts = TDFA.defaultCompOpt {TDFA.caseSensitive = caseSensitive}
+    -- handle things not supported in TFFA (posix) regexes, e.g. \d \w \s, +, ?
+    go [] = []
+    go ('?' : cs) = "{0,1}" ++ go cs
+    go ('+' : cs) = "{1,}" ++ go cs
+    go ('\\' : c : cs)
+      | c == 'd' = "[[:digit:]]" ++ go cs
+      | c == 'D' = "[^[:digit:]]" ++ go cs
+      | c == 's' = "[[:space:]]" ++ go cs
+      | c == 'S' = "[^[:space:]]" ++ go cs
+      | c == 'w' = "[[:word:]]" ++ go cs
+      | c == 'W' = "[^[:word:]]" ++ go cs
+      | otherwise = '\\' : c : go cs
+    go (c : cs) = c : go cs
+
+match :: TDFA.RegexContext Regex source target => RE -> source -> target
+match (RE _ re) t = TDFA.match re t
+
+matchAll :: TDFA.RegexLike Regex source => RE -> source -> [TDFA.MatchArray]
+matchAll (RE _ re) t = TDFA.matchAll re t
+
+makeLiteralRE :: MonadFail m => Text -> m RE
+makeLiteralRE t
+  | T.null t = makeRE ".{0,0}" -- experimentally behaves as typst does
+  | otherwise = makeRE $ T.foldl go mempty t
+  where
+    go acc c = if isSpecial c then acc <> T.pack ['\\', c] else T.snoc acc c
+    isSpecial c = c `elem` (".*?+{}[]\\" :: [Char])
+
+-- from regex-compat but for Text
+splitRegex :: RE -> Text -> [Text]
+splitRegex (RE _ delim) strIn =
+  let matches = map (Array.! 0) (TDFA.matchAll delim strIn)
+      go _i str [] = str : []
+      go i str ((off, len) : rest) =
+        let i' = off + len
+            firstline = T.take (off - i) str
+            remainder = T.drop (i' - i) str
+         in seq i' $
+              if T.null remainder
+                then [firstline, ""]
+                else firstline : go i' remainder rest
+   in go 0 strIn matches
diff --git a/src/Typst/Show.hs b/src/Typst/Show.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Show.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fsimpl-tick-factor=140 #-}
+
+module Typst.Show (applyShowRules) where
+
+import Control.Monad (foldM)
+import Data.Array ((!))
+import qualified Data.Map as M
+import Data.Sequence (Seq)
+import qualified Data.Sequence as Seq
+import Data.Text (Text)
+import qualified Data.Text as T
+import Text.Parsec (getState, updateState, (<|>))
+import qualified Text.Regex.TDFA as TDFA
+import Typst.Regex (RE (..), makeLiteralRE)
+import Typst.Syntax
+import Typst.Types
+
+-- import Debug.Trace
+
+applyShowRules :: Monad m => Seq Content -> MP m (Seq Content)
+applyShowRules cs = do
+  rules <- evalShowRules <$> getState
+  foldM (tryShowRules rules) mempty cs
+
+withoutShowRule :: Monad m => Selector -> MP m a -> MP m a
+withoutShowRule selector pa = do
+  oldShowRules <- evalShowRules <$> getState
+  updateState $ \st ->
+    st
+      { evalShowRules =
+          [ ShowRule sel f | ShowRule sel f <- evalShowRules st, sel /= selector
+          ]
+      }
+  res <- pa
+  updateState $ \st -> st {evalShowRules = oldShowRules}
+  pure res
+
+-- By experiment, it seems that show rules work this way:
+-- the first (i.e. most recently defined) one to match a given element
+-- are applied first.
+tryShowRules ::
+  Monad m =>
+  [ShowRule] ->
+  Seq Content ->
+  Content ->
+  MP m (Seq Content)
+tryShowRules [] cs c = pure $ cs Seq.|> c
+tryShowRules (ShowRule sel f : rs) cs c = do
+  c' <- case c of
+    Elt name pos fields -> do
+      let applyToVal (VContent cs') =
+            VContent
+              <$> foldMap (tryShowRules [ShowRule sel f] mempty) cs'
+          applyToVal (VArray as) = VArray <$> mapM applyToVal as
+          applyToVal x = pure x
+      fields' <- mapM applyToVal fields
+      pure $ Elt name pos fields'
+    _ -> pure c
+  case (sel, c') of
+    (SelectString s, Txt t) ->
+      ( do
+          re <- makeLiteralRE s
+          withoutShowRule
+            sel
+            ((cs <>) <$> (replaceRegexContent re t f >>= applyShowRules))
+      )
+        <|> tryShowRules rs cs c'
+    (SelectRegex re, Txt t) ->
+      ( withoutShowRule
+          sel
+          ((cs <>) <$> (replaceRegexContent re t f >>= applyShowRules))
+      )
+        <|> tryShowRules rs cs c'
+    (SelectLabel s, elt@(Elt _ _ fields))
+      | Just (VLabel s') <- M.lookup "label" fields,
+        s' == s ->
+          withoutShowRule sel ((cs <>) <$> (f elt >>= applyShowRules))
+    (SelectElement name fields, elt@(Elt name' _ fields'))
+      | name == name',
+        fieldsMatch fields fields' ->
+          withoutShowRule sel $ (cs <>) <$> (f elt >>= applyShowRules)
+    (SelectOr _sel1 _sel2, _elt) ->
+      fail "or is not yet implemented for select"
+    (SelectAnd _sel1 _sel2, _elt) ->
+      fail "and is not yet implemented for select"
+    (SelectBefore _sel1 _sel2, _elt) ->
+      fail "before is not yet implemented for select"
+    (SelectAfter _sel1 _sel2, _elt) ->
+      fail "after is not yet implemented for select"
+    _ -> tryShowRules rs cs c'
+
+fieldsMatch :: [(Identifier, Val)] -> (M.Map Identifier Val) -> Bool
+fieldsMatch [] _ = True
+fieldsMatch ((k, v) : rest) m =
+  ( case M.lookup k m of
+      Just v' -> v == v'
+      Nothing -> False
+  )
+    && fieldsMatch rest m
+
+replaceRegexContent ::
+  Monad m =>
+  RE ->
+  Text ->
+  (forall m'. Monad m' => Content -> MP m' (Seq Content)) ->
+  MP m (Seq Content)
+replaceRegexContent (RE _ re) strIn f =
+  let matches = map (! 0) (TDFA.matchAll re strIn)
+      go _i str [] = pure $ Seq.singleton (Txt str)
+      go i str ((off, len) : rest) =
+        let i' = off + len
+            before = T.take (off - i) str
+            matched = T.take len (T.drop (off - i) str)
+            after = T.drop (i' - i) str
+         in seq i' $
+              (\x y -> Seq.singleton (Txt before) <> x <> y)
+                <$> f (Txt matched)
+                <*> go i' after rest
+   in go 0 strIn matches
diff --git a/src/Typst/Syntax.hs b/src/Typst/Syntax.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Syntax.hs
@@ -0,0 +1,158 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+module Typst.Syntax
+  ( Markup (..),
+    Identifier (..),
+    Imports (..),
+    Arg (..),
+    Param (..),
+    Bind (..),
+    BindPart (..),
+    Literal (..),
+    Block (..),
+    Expr (..),
+    Unit (..),
+  )
+where
+
+import Data.Data (Data, Typeable)
+import Data.String
+import Data.Text (Text)
+import qualified Data.Text as T
+import Text.Parsec (SourcePos)
+
+data Markup
+  = Space
+  | SoftBreak
+  | HardBreak
+  | ParBreak
+  | Text Text
+  | Nbsp
+  | Shy
+  | EmDash
+  | EnDash
+  | Ellipsis
+  | Quote Char
+  | Ref Text Expr
+  | Equation Bool [Markup] -- Bool is True for displayed format
+  | Strong [Markup]
+  | Emph [Markup]
+  | Bracketed [Markup]
+  | RawInline Text
+  | RawBlock Text Text
+  | Heading Int [Markup]
+  | Url Text
+  | BulletListItem [Markup]
+  | EnumListItem (Maybe Int) [Markup]
+  | DescListItem [Markup] [Markup]
+  | Code SourcePos Expr
+  | Comment
+  | MAlignPoint
+  | MFrac Markup Markup
+  | MAttach (Maybe Markup) (Maybe Markup) Markup -- bottom then top
+  | MGroup (Maybe Text) (Maybe Text) [Markup] -- maybes are open/cloes delims
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+newtype Identifier = Identifier Text
+  deriving (Show, Eq, Ord, Data, Typeable, Semigroup, Monoid)
+
+instance IsString Identifier where
+  fromString = Identifier . T.pack
+
+data Arg
+  = KeyValArg Identifier Expr
+  | NormalArg Expr
+  | ArrayArg [[Markup]]
+  | SpreadArg Expr
+  | BlockArg [Markup]
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+data Param
+  = DefaultParam Identifier Expr
+  | NormalParam Identifier
+  | DestructuringParam [BindPart]
+  | SinkParam (Maybe Identifier)
+  | SkipParam -- _
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+data Bind
+  = BasicBind (Maybe Identifier)
+  | DestructuringBind [BindPart]
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+data BindPart
+  = Simple (Maybe Identifier)
+  | WithKey Identifier (Maybe Identifier)
+  | Sink (Maybe Identifier)
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+data Unit = Pt | Mm | Cm | In | Deg | Rad | Em | Fr | Percent
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+data Literal
+  = String Text
+  | Boolean Bool
+  | Float Double
+  | Int Integer
+  | Numeric Double Unit
+  | None
+  | Auto
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+data Block
+  = Content [Markup]
+  | CodeBlock [Expr]
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+-- binary-op ::=
+--   '+' | '-' | '*' | '/' | 'and' | 'or' | '==' | '!=' |
+--   '<' | '<=' | '>' | '>=' | '=' | 'in' | ('not' 'in') |
+--   '+=' | '-=' | '*=' | '/='
+data Expr
+  = Literal Literal
+  | Negated Expr
+  | ToPower Expr Expr
+  | Times Expr Expr
+  | Divided Expr Expr
+  | Plus Expr Expr
+  | Minus Expr Expr
+  | Equals Expr Expr
+  | LessThan Expr Expr
+  | LessThanOrEqual Expr Expr
+  | GreaterThan Expr Expr
+  | GreaterThanOrEqual Expr Expr
+  | InCollection Expr Expr
+  | Not Expr
+  | And Expr Expr
+  | Or Expr Expr
+  | Assign Expr Expr
+  | Ident Identifier
+  | FuncCall Expr [Arg]
+  | FuncExpr [Param] Expr
+  | FieldAccess Expr Expr
+  | Group Expr
+  | Array [Expr]
+  | Dict [(Identifier, Expr)]
+  | Binding Bind
+  | Let Bind Expr
+  | LetFunc Identifier [Param] Expr
+  | Set Expr [Arg]
+  | Show (Maybe Expr) Expr
+  | If [(Expr, Expr)]
+  | While Expr Expr
+  | For Bind Expr Expr
+  | Block Block
+  | Import Expr Imports
+  | Include Expr
+  | Return (Maybe Expr)
+  | Label Text
+  | Break
+  | Continue
+  deriving (Show, Ord, Eq, Data, Typeable)
+
+data Imports
+  = AllIdentifiers
+  | SomeIdentifiers [Identifier]
+  | NoIdentifiers
+  deriving (Show, Ord, Eq, Data, Typeable)
diff --git a/src/Typst/Types.hs b/src/Typst/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Types.hs
@@ -0,0 +1,877 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE InstanceSigs #-}
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Typst.Types
+  ( RE,
+    Val (..),
+    ValType (..),
+    valType,
+    hasType,
+    FromVal (..),
+    Negatable (..),
+    Summable (..),
+    Multipliable (..),
+    Selector (..),
+    Symbol (..),
+    Content (..),
+    Function (..),
+    Arguments (..),
+    getPositionalArg,
+    getNamedArg,
+    Compare (..),
+    MP,
+    Scope (..),
+    FlowDirective (..),
+    EvalState (..),
+    emptyEvalState,
+    ShowRule (..),
+    Counter (..),
+    LUnit (..),
+    Length (..),
+    renderLength,
+    Horiz (..),
+    Vert (..),
+    Color (..),
+    Direction (..),
+    Identifier (..), -- reexported
+    lookupIdentifier,
+    joinVals,
+    prettyVal,
+    valToContent,
+    repr,
+    Attempt (..),
+  )
+where
+
+import Control.Monad (MonadPlus (..))
+import Data.Aeson (FromJSON, parseJSON)
+import qualified Data.Aeson as Aeson
+import qualified Data.ByteString as BS
+import Data.Data (Typeable)
+import qualified Data.Foldable as F
+import Data.Functor.Classes (Ord1 (liftCompare))
+import qualified Data.Map as M
+import qualified Data.Map.Ordered as OM
+import Data.Maybe (fromMaybe, isJust)
+import Data.Scientific (floatingOrInteger)
+import Data.Sequence (Seq)
+import qualified Data.Sequence as Seq
+import qualified Data.Set as Set
+import Data.String
+import Data.Text (Text)
+import qualified Data.Text as T
+import Data.Vector (Vector)
+import qualified Data.Vector as V
+import Text.Parsec
+import qualified Text.PrettyPrint as P
+import Text.Read (readMaybe)
+import Typst.Regex (RE, makeLiteralRE)
+import Typst.Syntax (Identifier (..), Markup)
+
+data Val
+  = VNone
+  | VAuto
+  | VBoolean !Bool
+  | VInteger !Integer
+  | VFloat !Double
+  | VRatio !Rational
+  | VLength !Length
+  | VAlignment (Maybe Horiz) (Maybe Vert)
+  | VAngle !Double -- degrees
+  | VFraction !Double
+  | VColor !Color
+  | VSymbol !Symbol
+  | VString !Text
+  | VRegex !RE
+  | VContent (Seq Content)
+  | VArray (Vector Val)
+  | VDict (OM.OMap Identifier Val)
+  | VTermItem (Seq Content) (Seq Content)
+  | VDirection Direction
+  | VFunction (Maybe Identifier) (M.Map Identifier Val) Function
+  | -- first param is Just ident if element function
+    -- second param is a map of subfunctions in this function's scope
+    VArguments Arguments
+  | VLabel !Text
+  | VCounter !Counter
+  | VSelector !Selector
+  | VModule Identifier (M.Map Identifier Val)
+  | VStyles -- just a placeholder for now
+  deriving (Show, Eq, Typeable)
+
+instance FromJSON Val where
+  parseJSON v@(Aeson.Object {}) =
+    VDict . OM.fromList . M.toList . M.mapKeys Identifier <$> parseJSON v
+  parseJSON v@(Aeson.Array {}) = VArray <$> parseJSON v
+  parseJSON (Aeson.String t) = pure $ VString t
+  parseJSON (Aeson.Number n) =
+    pure $ either VFloat VInteger (floatingOrInteger n)
+  parseJSON (Aeson.Bool b) = pure $ VBoolean b
+  parseJSON Aeson.Null = pure VNone
+
+data ValType
+  = TNone
+  | TAuto
+  | TBoolean
+  | TInteger
+  | TFloat
+  | TRatio
+  | TLength
+  | TAlignment
+  | TAngle
+  | TFraction
+  | TColor
+  | TSymbol
+  | TString
+  | TRegex
+  | TContent
+  | TArray
+  | TDict
+  | TTermItem
+  | TDirection
+  | TFunction
+  | TArguments
+  | TModule
+  | TSelector
+  | TStyles
+  | TLabel
+  | TCounter
+  | TLocation
+  | TAny
+  | ValType :|: ValType
+  deriving (Show, Eq, Typeable)
+
+valType :: Val -> ValType
+valType v =
+  case v of
+    VNone {} -> TNone
+    VAuto {} -> TAuto
+    VBoolean {} -> TBoolean
+    VInteger {} -> TInteger
+    VFloat {} -> TFloat
+    VRatio {} -> TRatio
+    VLength {} -> TLength
+    VAlignment {} -> TAlignment
+    VAngle {} -> TAngle
+    VFraction {} -> TFraction
+    VColor {} -> TColor
+    VSymbol {} -> TSymbol
+    VString {} -> TString
+    VRegex {} -> TRegex
+    VContent {} -> TContent
+    VArray {} -> TArray
+    VDict {} -> TDict
+    VTermItem {} -> TTermItem
+    VDirection {} -> TDirection
+    VLabel {} -> TLabel
+    VCounter {} -> TCounter
+    VFunction {} -> TFunction
+    VArguments {} -> TArguments
+    VModule {} -> TModule
+    VSelector {} -> TSelector
+    VStyles {} -> TStyles
+
+hasType :: ValType -> Val -> Bool
+hasType TAny _ = True
+hasType TLocation (VDict m) =
+  isJust (OM.lookup "page" m >> OM.lookup "x" m >> OM.lookup "y" m)
+hasType (t1 :|: t2) v = hasType t1 v || hasType t2 v
+hasType t v = t == valType v
+
+class FromVal a where
+  fromVal :: (MonadPlus m, MonadFail m) => Val -> m a
+
+instance FromVal Val where
+  fromVal = pure
+
+instance FromVal (Seq Content) where
+  fromVal = pure . valToContent
+
+instance FromVal Text where
+  fromVal (VContent cs) = mconcat <$> mapM go (F.toList cs)
+    where
+      go (Txt t) = pure t
+      go (Elt "text" _ fs) =
+        maybe
+          (fail "text element has no body")
+          fromVal
+          (M.lookup "body" fs)
+      go _ = fail "not a text element"
+  fromVal (VString t) = pure t
+  fromVal _ = fail "not a string or content value"
+
+instance FromVal String where
+  fromVal = fmap T.unpack . fromVal
+
+instance FromVal RE where
+  fromVal (VString t) = makeLiteralRE t
+  fromVal (VRegex re) = pure re
+  fromVal _ = fail "not a string or regex"
+
+instance FromVal Integer where
+  fromVal val =
+    case val of
+      VInteger x -> pure $ fromIntegral x
+      VFloat x -> pure $ floor x
+      VRatio x -> pure $ floor x
+      VBoolean x -> pure $ if x then 1 else 0
+      VString x | Just (xint :: Integer) <- readMaybe (T.unpack x) -> pure xint
+      _ -> fail $ "Cannot convert " <> show val <> " to integer"
+
+instance FromVal Int where
+  fromVal val = (fromIntegral :: Integer -> Int) <$> fromVal val
+
+instance FromVal Rational where
+  fromVal val =
+    case val of
+      VRatio x -> pure x
+      VInteger x -> pure $ fromIntegral x
+      VString x | Just (xrat :: Rational) <- readMaybe (T.unpack x) -> pure xrat
+      _ -> fail $ "Cannot convert " <> show val <> " to rational"
+
+instance FromVal Double where
+  fromVal val =
+    case val of
+      VInteger x -> pure $ fromIntegral x
+      VFloat x -> pure x
+      VRatio x -> pure $ fromRational x
+      VString x | Just (xdb :: Double) <- readMaybe (T.unpack x) -> pure xdb
+      _ -> fail $ "Cannot convert " <> show val <> " to double"
+
+instance FromVal Bool where
+  fromVal (VBoolean b) = pure b
+  fromVal val = fail $ "Cannot convert " <> show val <> " to boolean"
+
+instance FromVal Length where
+  fromVal (VLength x) = pure x
+  fromVal (VRatio x) = pure $ LRatio x
+  fromVal val = fail $ "Cannot convert " <> show val <> " to length"
+
+instance FromVal Function where
+  fromVal (VFunction _ _ f) = pure f
+  fromVal val = fail $ show val <> " is not a function"
+
+instance FromVal Direction where
+  fromVal (VDirection d) = pure d
+  fromVal val = fail $ show val <> " is not a direction"
+
+instance FromVal Counter where
+  fromVal (VString t) = pure $ CounterCustom t
+  fromVal (VLabel t) = pure $ CounterLabel t
+  fromVal (VFunction (Just "page") _ _) = pure $ CounterPage
+  fromVal (VFunction (Just name) _ _) = pure $ CounterSelector $ SelectElement name []
+  fromVal (VSelector s) = pure $ CounterSelector s
+  fromVal val = fail $ show val <> " is not a counter"
+
+instance FromVal Selector where
+  fromVal (VSelector s) = pure s
+  fromVal val = fail $ show val <> " is not a selector"
+
+instance FromVal a => FromVal (Maybe a) where
+  fromVal VNone = pure Nothing
+  fromVal x = (Just <$> fromVal x) `mplus` pure Nothing
+
+instance FromVal a => FromVal (Vector a) where
+  fromVal (VArray v) = V.mapM fromVal v
+  fromVal val = fail $ "Could not convert " <> show val <> " to array"
+
+data Selector
+  = SelectElement Identifier [(Identifier, Val)]
+  | SelectString !Text
+  | SelectRegex !RE
+  | SelectLabel !Text
+  | SelectOr Selector Selector
+  | SelectAnd Selector Selector
+  | SelectBefore Selector Selector
+  | SelectAfter Selector Selector
+  deriving (Show, Eq, Ord, Typeable)
+
+data Symbol = Symbol
+  { symDefault :: !Text,
+    symAccent :: !Bool,
+    symVariants :: [(Set.Set Text, Text)]
+  }
+  deriving (Show, Eq, Typeable)
+
+joinVals :: MonadFail m => Val -> Val -> m Val
+joinVals = go
+  where
+    go VNone v = pure v
+    go v VNone = pure v
+    go v (VSymbol (Symbol s _ _)) = go v (VString s)
+    go (VString t) (VString t') = pure $ VString (t <> t')
+    go (VString t) (VContent cs) = pure $ VContent (Txt t Seq.<| cs)
+    go (VContent cs) (VString t) = pure $ VContent (cs Seq.|> Txt t)
+    go (VContent cs) (VContent cs') = pure $ VContent (cs <> cs')
+    go (VArray vec) (VArray vec') = pure $ VArray (vec <> vec')
+    go accum v = fail $ "Can't combine " <> show accum <> " and " <> show v
+
+class Compare a where
+  comp :: a -> a -> Maybe Ordering
+
+instance Compare Val where
+  comp VNone VNone = Just EQ
+  comp VAuto VAuto = Just EQ
+  comp (VBoolean b1) (VBoolean b2) = Just $ compare b1 b2
+  comp (VInteger i1) (VInteger i2) = Just $ compare i1 i2
+  comp (VFloat f1) (VFloat f2) = Just $ compare f1 f2
+  comp (VInteger i1) (VFloat f2) = Just $ compare (fromIntegral i1) f2
+  comp (VFloat f1) (VInteger i2) = Just $ compare f1 (fromIntegral i2)
+  comp (VRatio r1) (VRatio r2) = Just $ compare r1 r2
+  comp (VRatio r1) (VLength (LRatio r2)) = Just $ compare r1 r2
+  comp (VLength (LRatio r1)) (VRatio r2) = Just $ compare r1 r2
+  comp (VRatio r1) x = comp (VFloat (fromRational r1)) x
+  comp x (VRatio r1) = comp x (VFloat (fromRational r1))
+  comp (VLength x1) (VLength x2) = compareLength x1 x2
+  comp (VAlignment {}) (VAlignment {}) = Nothing
+  comp (VAngle x1) (VAngle x2) = Just $ compare x1 x2
+  comp (VFraction x1) (VFraction x2) = Just $ compare x1 x2
+  comp (VColor c1) (VColor c2) = Just $ compare c1 c2
+  comp (VSymbol (Symbol s1 _ _)) (VSymbol (Symbol s2 _ _)) = Just $ compare s1 s2
+  comp (VString s1) (VString s2) = Just $ compare s1 s2
+  comp (VContent c1) (VContent c2) = Just $ compare c1 c2
+  comp (VArray v1) (VArray v2) =
+    Just $ liftCompare (\x y -> fromMaybe LT (comp x y)) v1 v2
+  comp (VDict m1) (VDict m2) =
+    Just $ liftCompare (\x y -> fromMaybe LT (comp x y)) (OM.toMap m1) (OM.toMap m2)
+  comp (VFunction (Just i1) _ _) (VFunction (Just i2) _ _) = Just $ compare i1 i2
+  comp _ _ = Nothing
+
+instance Ord Val where
+  compare v1 v2 = fromMaybe EQ $ comp v1 v2
+
+class Negatable a where
+  maybeNegate :: a -> Maybe a
+
+instance Negatable Val where
+  maybeNegate (VInteger i) = pure $ VInteger (-i)
+  maybeNegate (VFloat f) = pure $ VFloat (-f)
+  maybeNegate (VLength x) = pure $ VLength $ negateLength x
+  maybeNegate (VAngle x) = pure $ VAngle (-x)
+  maybeNegate (VFraction x) = pure $ VFraction (-x)
+  maybeNegate (VRatio x) = pure $ VRatio (-x)
+  maybeNegate v = fail $ "could not negate " <> show v
+
+class Negatable a => Summable a where
+  maybePlus :: a -> a -> Maybe a
+  maybeMinus :: a -> a -> Maybe a
+  maybeMinus x y = maybeNegate y >>= maybePlus x
+
+instance Summable Val where
+  maybePlus VNone x = pure x
+  maybePlus x VNone = pure x
+  maybePlus (VInteger i1) (VInteger i2) = pure $ VInteger (i1 + i2)
+  maybePlus (VRatio r1) (VRatio r2) = pure $ VRatio (r1 + r2)
+  maybePlus (VFloat f1) (VFloat f2) = pure $ VFloat (f1 + f2)
+  maybePlus (VInteger i1) (VFloat f2) = pure $ VFloat (fromIntegral i1 + f2)
+  maybePlus (VFloat f1) (VInteger i2) = pure $ VFloat (f1 + fromIntegral i2)
+  maybePlus (VInteger i1) (VRatio r2) = pure $ VRatio (fromIntegral i1 + r2)
+  maybePlus (VRatio r1) (VInteger i2) = pure $ VRatio (r1 + fromIntegral i2)
+  maybePlus (VFloat f1) (VRatio r2) = pure $ VFloat (f1 + fromRational r2)
+  maybePlus (VRatio r1) (VFloat f2) = pure $ VFloat (fromRational r1 + f2)
+  maybePlus (VString s1) (VString s2) = pure $ VString (s1 <> s2)
+  maybePlus (VContent c1) (VContent c2) = pure $ VContent (c1 <> c2)
+  maybePlus (VString s1) (VContent c2) = pure $ VContent (Txt s1 Seq.<| c2)
+  maybePlus (VContent c1) (VString s2) = pure $ VContent (c1 Seq.|> Txt s2)
+  maybePlus (VLength l1) (VLength l2) = pure $ VLength (l1 <> l2)
+  maybePlus (VLength l1) (VRatio r1) = pure $ VLength (l1 <> LRatio r1)
+  maybePlus (VRatio r1) (VLength l1) = pure $ VLength (l1 <> LRatio r1)
+  maybePlus (VAngle a1) (VAngle a2) = pure $ VAngle (a1 + a2)
+  maybePlus (VFraction f1) (VFraction f2) = pure $ VFraction (f1 + f2)
+  maybePlus (VArray v1) (VArray v2) = pure $ VArray (v1 <> v2)
+  maybePlus (VDict m1) (VDict m2) = pure $ VDict (m1 OM.<>| m2)
+  maybePlus (VColor c) (VLength l) =
+    -- Stroke '1pt + red'
+    pure $ VDict $ OM.fromList [("thickness", VLength l), ("color", VColor c)]
+  maybePlus (VLength l) (VColor c) = maybePlus (VColor c) (VLength l)
+  maybePlus v1 v2 = fail $ "could not add " <> show v1 <> " and " <> show v2
+
+class Multipliable a where
+  maybeTimes :: a -> a -> Maybe a
+  maybeDividedBy :: a -> a -> Maybe a
+
+instance Multipliable Val where
+  maybeTimes (VInteger i1) (VInteger i2) = pure $ VInteger (i1 * i2)
+  maybeTimes (VFloat x1) (VFloat x2) = pure $ VFloat (x1 * x2)
+  maybeTimes (VInteger i1) (VFloat f2) = pure $ VFloat (fromIntegral i1 * f2)
+  maybeTimes (VFloat f1) (VInteger i2) = pure $ VFloat (f1 * fromIntegral i2)
+  maybeTimes (VInteger i) (VArray v) =
+    pure $ VArray (mconcat $ replicate (fromIntegral i) v)
+  maybeTimes (VArray v) (VInteger i) =
+    pure $ VArray (mconcat $ replicate (fromIntegral i) v)
+  maybeTimes (VInteger i) (VString s)
+    | i >= 0 = pure $ VString (T.replicate (fromIntegral i) s)
+  maybeTimes (VString s) (VInteger i)
+    | i >= 0 = pure $ VString (T.replicate (fromIntegral i) s)
+  maybeTimes (VInteger i) (VContent c)
+    | i >= 0 = pure $ VContent (mconcat $ replicate (fromIntegral i) c)
+  maybeTimes (VContent c) (VInteger i)
+    | i >= 0 = pure $ VContent (mconcat $ replicate (fromIntegral i) c)
+  maybeTimes (VInteger i) (VLength l) = pure $ VLength $ timesLength (fromIntegral i) l
+  maybeTimes (VLength l) (VInteger i) = pure $ VLength $ timesLength (fromIntegral i) l
+  maybeTimes (VFloat f) (VLength l) = pure $ VLength $ timesLength f l
+  maybeTimes (VLength l) (VFloat f) = pure $ VLength $ timesLength f l
+  maybeTimes (VInteger i) (VAngle a) = pure $ VAngle (fromIntegral i * a)
+  maybeTimes (VAngle a) (VInteger i) = pure $ VAngle (fromIntegral i * a)
+  maybeTimes (VFloat f) (VAngle a) = pure $ VAngle (f * a)
+  maybeTimes (VAngle a) (VFloat f) = pure $ VAngle (f * a)
+  maybeTimes (VInteger i) (VFraction f) = pure $ VFraction (fromIntegral i * f)
+  maybeTimes (VFraction f) (VInteger i) = pure $ VFraction (fromIntegral i * f)
+  maybeTimes (VFloat x) (VFraction f) = pure $ VFraction (x * f)
+  maybeTimes (VFraction f) (VFloat x) = pure $ VFraction (x * f)
+  maybeTimes (VFraction f1) (VFraction f2) = pure $ VFraction (f1 * f2)
+  maybeTimes (VRatio r1) (VRatio r2) = pure $ VRatio (r1 * r2)
+  maybeTimes (VInteger i) (VRatio r) = pure $ VRatio (fromIntegral i * r)
+  maybeTimes (VRatio r) (VInteger i) = pure $ VRatio (fromIntegral i * r)
+  maybeTimes (VFloat x) (VRatio r) = pure $ VRatio (realToFrac x * r)
+  maybeTimes (VRatio r) (VFloat x) = pure $ VRatio (realToFrac x * r)
+  maybeTimes v1 v2 = fail $ "could not multiply " <> show v1 <> " and " <> show v2
+
+  maybeDividedBy (VInteger i1) (VInteger i2) =
+    if i1 `mod` i2 == 0
+      then pure $ VInteger (i1 `div` i2)
+      else pure $ VFloat (fromIntegral i1 / fromIntegral i2)
+  maybeDividedBy (VFloat x1) (VFloat x2) = maybeTimes (VFloat x1) (VFloat (1 / x2))
+  maybeDividedBy (VInteger i1) (VFloat f2) = pure $ VFloat (fromIntegral i1 / f2)
+  maybeDividedBy (VFloat f1) (VInteger i2) = pure $ VFloat (f1 / fromIntegral i2)
+  maybeDividedBy (VLength l) (VInteger i)
+    | i >= 0 = pure $ VLength (mconcat $ replicate (fromIntegral i) l)
+  maybeDividedBy (VLength l) (VFloat f) = pure $ VLength $ timesLength (1 / f) l
+  maybeDividedBy (VAngle a) (VInteger i) = pure $ VAngle (fromIntegral i / a)
+  maybeDividedBy (VInteger i) (VFraction f) = pure $ VFraction (fromIntegral i / f)
+  maybeDividedBy (VFraction f) (VInteger i) = pure $ VFraction (fromIntegral i / f)
+  maybeDividedBy (VFraction f1) (VFraction f2) = pure $ VFraction (f1 / f2)
+  maybeDividedBy (VLength l1) (VLength l2)
+    | l1 == l2 = pure $ VInteger 1
+  maybeDividedBy (VLength (LExact l1 u1)) (VLength (LExact l2 u2))
+    | u1 == u2 = pure $ VFloat (l1 / l2)
+    | Just pts1 <- toPts u1 l1,
+      Just pts2 <- toPts u2 l2 =
+        pure $ VFloat (pts1 / pts2)
+  maybeDividedBy (VLength (LRatio r)) x
+    | Just (VRatio r') <- maybeDividedBy (VRatio r) x =
+        pure $ VLength (LRatio r')
+  maybeDividedBy (VRatio r1) (VLength (LRatio r2)) = pure $ VRatio (r1 / r2)
+  maybeDividedBy (VAngle a1) (VAngle a2) = pure $ VFloat (a1 / a2)
+  maybeDividedBy (VRatio a1) (VRatio a2) = pure $ VRatio (a1 / a2)
+  maybeDividedBy (VRatio r) (VInteger i) = pure $ VRatio (r / fromIntegral i)
+  maybeDividedBy (VRatio r) (VFloat x) =
+    pure $ VRatio (r / realToFrac x)
+  maybeDividedBy v1 v2 = fail $ "could not divide " <> show v1 <> " by " <> show v2
+
+data Content
+  = Txt !Text
+  | Lab !Text
+  | Elt
+      { eltName :: Identifier,
+        eltPos :: Maybe SourcePos,
+        eltFields :: M.Map Identifier Val
+      }
+  deriving (Show, Typeable)
+
+instance Eq Content where
+  Txt t1 == Txt t2 = t1 == t2
+  Lab t1 == Lab t2 = t1 == t2
+  Elt n1 _ f1 == Elt n2 _ f2 = n1 == n2 && f1 == f2
+  _ == _ = False
+
+instance Ord Content where
+  compare Txt {} Lab {} = LT
+  compare Lab {} Elt {} = LT
+  compare Txt {} Elt {} = LT
+  compare Lab {} Txt {} = GT
+  compare Elt {} Lab {} = GT
+  compare Elt {} Txt {} = GT
+  compare (Txt t1) (Txt t2) = compare t1 t2
+  compare (Lab t1) (Lab t2) = compare t1 t2
+  compare (Elt n1 _ f1) (Elt n2 _ f2) = compare (n1, f1) (n2, f2)
+
+instance IsString Content where
+  fromString x = Txt (T.pack x)
+
+newtype Function = Function (forall m. Monad m => Arguments -> MP m Val)
+  deriving (Typeable)
+
+instance Show Function where
+  show _ = "<function>"
+
+instance Eq Function where
+  _ == _ = False
+
+data Scope
+  = FunctionScope
+  | BlockScope
+  deriving (Show, Ord, Eq)
+
+data FlowDirective
+  = FlowNormal
+  | FlowBreak
+  | FlowContinue
+  | FlowReturn Bool
+  deriving (Show, Ord, Eq)
+
+data EvalState m = EvalState
+  { evalIdentifiers :: [(Scope, M.Map Identifier Val)],
+    -- first item is current block, then superordinate block, etc.
+    evalCounters :: M.Map Counter Integer,
+    evalMath :: Bool,
+    evalShowRules :: [ShowRule],
+    evalStyles :: M.Map Identifier Arguments,
+    evalFlowDirective :: FlowDirective,
+    evalLoadBytes :: FilePath -> m BS.ByteString
+  }
+
+emptyEvalState :: EvalState m
+emptyEvalState = EvalState
+    { evalIdentifiers = [],
+      evalCounters = mempty,
+      evalMath = False,
+      evalShowRules = [],
+      evalStyles = mempty,
+      evalFlowDirective = FlowNormal,
+      evalLoadBytes = undefined
+    }
+
+data Attempt a
+  = Success a
+  | Failure String
+  deriving (Show, Eq, Ord, Typeable)
+
+instance Functor Attempt where
+  fmap f (Success x) = Success (f x)
+  fmap _ (Failure s) = Failure s
+
+instance Applicative Attempt where
+  pure = Success
+  (Success f) <*> (Success a) = Success (f a)
+  Failure s <*> _ = Failure s
+  _ <*> Failure s = Failure s
+
+instance Monad Attempt where
+  return = pure
+  Failure s >>= _ = Failure s
+  Success x >>= f = f x
+
+instance MonadFail Attempt where
+  fail = Failure
+
+data ShowRule
+  = ShowRule Selector (forall m. Monad m => Content -> MP m (Seq Content))
+
+instance Show ShowRule where
+  show (ShowRule sel _) = "ShowRule " <> show sel <> " <function>"
+
+type MP m = ParsecT [Markup] (EvalState m) m
+
+data Arguments = Arguments
+  { positional :: [Val],
+    named :: OM.OMap Identifier Val
+  }
+  deriving (Show, Eq, Typeable)
+
+instance Semigroup Arguments where
+  Arguments ps1 ns1 <> Arguments ps2 ns2 =
+    Arguments (combinePositional ps1 ps2) (OM.unionWithR (\_ _ v -> v) ns1 ns2)
+
+-- we want to let a later alignment, color, or length supersede rather than
+-- adding to an earlier one. For #set.
+combinePositional :: [Val] -> [Val] -> [Val]
+combinePositional [] ys = ys
+combinePositional xs (y : ys) =
+  case (valType y, valType (last xs)) of
+    (TAlignment, TAlignment) -> init xs ++ y : ys
+    (TLength, TLength) -> init xs ++ y : ys
+    (TAngle, TAngle) -> init xs ++ y : ys
+    (TColor, TColor) -> init xs ++ y : ys
+    _ -> xs ++ y : ys
+combinePositional xs ys = xs ++ ys
+
+instance Monoid Arguments where
+  mappend = (<>)
+  mempty :: Arguments
+  mempty = Arguments mempty OM.empty
+
+getPositionalArg :: (MonadFail m, MonadPlus m, FromVal a) => Int -> Arguments -> m a
+getPositionalArg idx args =
+  if length (positional args) < idx
+    then fail "Not enough arguments"
+    else fromVal (positional args !! (idx - 1))
+
+getNamedArg :: (MonadFail m, MonadPlus m, FromVal a) => Identifier -> Arguments -> m a
+getNamedArg ident@(Identifier name) args =
+  case OM.lookup ident (named args) of
+    Nothing -> fail $ "No argument named " <> T.unpack name
+    Just v -> fromVal v
+
+data Counter
+  = CounterCustom !Text
+  | CounterLabel !Text
+  | CounterSelector !Selector
+  | CounterPage
+  deriving (Eq, Ord, Show, Typeable)
+
+data LUnit = LEm | LPt | LIn | LCm | LMm
+  deriving (Show, Eq, Typeable)
+
+data Length
+  = LExact Double LUnit
+  | LRatio !Rational
+  | LSum Length Length
+  deriving (Show, Eq, Typeable)
+
+instance Semigroup Length where
+  (LExact x xu) <> (LExact y yu)
+    | Just (z, zu) <- addLengths (x, xu) (y, yu) =
+        LExact z zu
+  LRatio x <> LRatio y = LRatio (x + y)
+  LRatio x <> LExact 0 _ = LRatio x
+  LExact 0 _ <> LRatio x = LRatio x
+  LRatio 0 <> LExact x u = LExact x u
+  LExact x u <> LRatio 0 = LExact x u
+  x <> y = LSum x y
+
+instance Monoid Length where
+  mappend = (<>)
+  mempty = LExact 0.0 LPt
+
+addLengths :: (Double, LUnit) -> (Double, LUnit) -> Maybe (Double, LUnit)
+addLengths (0, _xu) (y, yu) = pure (y, yu)
+addLengths (x, xu) (0, _yu) = pure (x, xu)
+addLengths (x, xu) (y, yu) =
+  if xu == yu
+    then pure (x + y, xu)
+    else do
+      x' <- toPts xu x
+      y' <- toPts yu y
+      pure (x' + y', LPt)
+
+timesLength :: Double -> Length -> Length
+timesLength f (LExact l u) = LExact (f * l) u
+timesLength f (LRatio r) = LRatio (toRational f * r)
+timesLength f (LSum l1 l2) = LSum (timesLength f l1) (timesLength f l2)
+
+toPts :: LUnit -> Double -> Maybe Double
+toPts LPt x = Just x
+toPts LEm _ = Nothing
+toPts LIn x = Just $ x * 72.0
+toPts LCm x = Just $ x * 28.35
+toPts LMm x = Just $ x * 283.5
+
+-- boolean is true if we need to include parens for LSum
+renderLength :: Bool -> Length -> Text
+renderLength parens (LSum l1 l2) =
+  (if parens then (\x -> "(" <> x <> ")") else id)
+    (renderLength True l1 <> " + " <> renderLength True l2)
+renderLength _ (LExact x u) =
+  T.pack (show x) <> renderUnit u
+renderLength _ (LRatio x) = toPercent x
+
+renderUnit :: LUnit -> Text
+renderUnit LEm = "em"
+renderUnit LPt = "pt"
+renderUnit LIn = "in"
+renderUnit LCm = "cm"
+renderUnit LMm = "mm"
+
+compareLength :: Length -> Length -> Maybe Ordering
+compareLength (LExact x xu) (LExact y yu)
+  | xu == yu = pure $ compare x y
+  | otherwise = do
+      x' <- toPts xu x
+      y' <- toPts yu y
+      pure $ compare x' y'
+compareLength (LRatio x) (LRatio y) = pure (compare x y)
+compareLength (LSum x1 y1) (LSum x2 y2) = do
+  z <- compareLength x1 x2
+  if z == EQ
+    then compareLength y1 y2
+    else mzero
+compareLength _ _ = mzero
+
+negateLength :: Length -> Length
+negateLength (LExact x u) = LExact (negate x) u
+negateLength (LRatio x) = LRatio (negate x)
+negateLength (LSum x y) = LSum (negateLength x) (negateLength y)
+
+data Horiz = HorizStart | HorizEnd | HorizLeft | HorizCenter | HorizRight
+  deriving (Show, Eq, Ord, Typeable)
+
+data Vert = VertTop | VertHorizon | VertBottom
+  deriving (Show, Eq, Ord, Typeable)
+
+data Color
+  = RGB Rational Rational Rational Rational
+  | CMYK Rational Rational Rational Rational
+  | Luma Rational
+  deriving (Show, Eq, Ord, Typeable)
+
+data Direction = Ltr | Rtl | Ttb | Btt
+  deriving (Show, Eq, Ord, Typeable)
+
+prettyVal :: Val -> P.Doc
+prettyVal expr =
+  case expr of
+    VContent cs -> prettyContent cs
+    VString t -> "\"" <> escString t <> "\""
+    VRegex re -> P.text (show re)
+    VAuto -> "auto"
+    VNone -> "none"
+    VBoolean True -> "true"
+    VBoolean False -> "false"
+    VFloat x -> P.text $ show x
+    VRatio x -> text $ toPercent x
+    VInteger x -> P.text $ show x
+    VAngle x -> P.text (show x <> "deg")
+    VLength len -> text $ renderLength False len
+    VAlignment x y -> text $
+      case (x, y) of
+        (Nothing, Nothing) -> mempty
+        (Just x', Nothing) -> renderHoriz x'
+        (Nothing, Just y') -> renderVert y'
+        (Just x', Just y') ->
+          "Axes(" <> renderHoriz x' <> ", " <> renderVert y' <> ")"
+      where
+        renderHoriz = T.toLower . T.drop 5 . T.pack . show
+        renderVert = T.toLower . T.drop 4 . T.pack . show
+    VFraction x -> P.text (show x <> "fr")
+    VArray xs ->
+      P.parens
+        ( P.cat $
+            P.punctuate ", " $
+              map prettyVal (V.toList xs)
+        )
+    VTermItem t d -> prettyVal (VArray [VContent t, VContent d])
+    VDict m ->
+      P.parens
+        ( P.sep $
+            P.punctuate "," $
+              ( map
+                  ( \(Identifier k, v) ->
+                      text k <> ": " <> prettyVal v
+                  )
+                  (OM.assocs m)
+              )
+        )
+    VDirection d -> text $ T.toLower $ T.pack $ show d
+    VFunction _ _ _ -> mempty
+    VLabel _ -> mempty
+    VCounter _ -> mempty
+    VColor (RGB r g b o) ->
+      "rgb("
+        <> text (toPercent r)
+        <> ","
+        <> text (toPercent g)
+        <> ","
+        <> text (toPercent b)
+        <> ","
+        <> text (toPercent o)
+        <> ")"
+    VColor (CMYK c m y k) ->
+      "cmyk("
+        <> text (toPercent c)
+        <> ","
+        <> text (toPercent m)
+        <> ","
+        <> text (toPercent y)
+        <> ","
+        <> text (toPercent k)
+        <> ")"
+    VColor (Luma g) -> "luma(" <> text (toPercent g) <> ")"
+    VModule (Identifier modid) _ -> "<module " <> text modid <> ">"
+    VArguments args ->
+      P.parens
+        ( P.sep
+            ( P.punctuate
+                ","
+                ( [ P.sep
+                      ( P.punctuate
+                          ","
+                          ( map
+                              ( \(Identifier k, v) ->
+                                  text k <> ": " <> prettyVal v
+                              )
+                              (OM.assocs (named args))
+                          )
+                      )
+                    | not (OM.null (named args))
+                  ]
+                    ++ [ P.cat (P.punctuate ", " $ map prettyVal (positional args))
+                         | not (null (positional args))
+                       ]
+                )
+            )
+        )
+    VSymbol (Symbol t _ _) -> text t
+    VSelector _ -> mempty
+    VStyles -> mempty
+
+escString :: Text -> P.Doc
+escString =
+  P.text . concatMap go . T.unpack
+  where
+    go :: Char -> String
+    go '"' = "\\\""
+    go '\\' = "\\\\"
+    go '\n' = "\\n"
+    go '\r' = "\\r"
+    go '\t' = "\\t"
+    go x = [x]
+
+prettyContent :: Seq Content -> P.Doc
+prettyContent cs
+  | Seq.length cs == 1 = foldMap go cs
+  | otherwise =
+      P.braces
+        ( P.space
+            <> P.cat (P.punctuate ", " (map go (F.toList cs)))
+            <> P.space
+        )
+  where
+    go (Txt t) = "[" <> text t <> "]"
+    go (Lab l) = "<" <> text l <> ">"
+    go (Elt (Identifier name) _ fields) =
+      text name
+        <> P.parens
+          ( P.cat $
+              P.punctuate
+                ", "
+                ( map
+                    ( \(Identifier k, v) ->
+                        text k <> ": " <> prettyVal v
+                    )
+                    (M.toList fields)
+                )
+          )
+
+valToContent :: Val -> Seq Content
+valToContent (VContent x) = x
+valToContent VNone = mempty
+valToContent (VString t) = Seq.singleton $ Txt t
+valToContent (VLabel t) = Seq.singleton $ Lab t
+valToContent x = Seq.singleton $ Txt $ repr x
+
+renderStyle :: P.Style
+renderStyle = P.Style P.PageMode 60 2.0
+
+repr :: Val -> Text
+repr = T.pack . P.renderStyle renderStyle . prettyVal
+
+toPercent :: Rational -> Text
+toPercent n =
+  T.pack (show (floor (100 * n) :: Integer)) <> "%"
+
+text :: Text -> P.Doc
+text t = P.text $ T.unpack t
+
+lookupIdentifier :: Monad m => Identifier -> MP m Val
+lookupIdentifier ident = do
+  let go [] = fail $ show ident <> " not found"
+      go ((_, i) : is) = case M.lookup ident i of
+        Just v -> pure v
+        Nothing -> go is
+  getState >>= go . evalIdentifiers
diff --git a/src/Typst/Util.hs b/src/Typst/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Typst/Util.hs
@@ -0,0 +1,172 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+
+module Typst.Util
+  ( TypeSpec (..),
+    makeElement,
+    makeElementWithScope,
+    makeFunction,
+    makeFunctionWithScope,
+    makeSymbolMap,
+    argsToFields,
+    nthArg,
+    namedArg,
+    allArgs
+  )
+where
+
+import Control.Monad (foldM)
+import Control.Monad.Reader (ReaderT (runReaderT), asks)
+import Data.List (foldl')
+import qualified Data.Map as M
+import qualified Data.Map.Ordered as OM
+import qualified Data.Sequence as Seq
+import qualified Data.Set as Set
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Vector as V
+import Text.Parsec (getPosition)
+import Typst.Types
+
+data TypeSpec
+  = One ValType
+  | Many ValType
+  deriving (Show, Eq)
+
+insertOM :: Ord k => k -> v -> OM.OMap k v -> OM.OMap k v
+insertOM k v m = m OM.|> (k, v)
+
+-- | Create element function with names for positional parameters.
+makeElement :: Maybe Identifier -> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
+makeElement mbNamespace name specs =
+  makeElementWithScope mbNamespace name specs mempty
+
+-- | Create element function with names for positional parameters.
+makeElementWithScope ::
+  Maybe Identifier ->
+  Identifier ->
+  [(Identifier, TypeSpec)] ->
+  M.Map Identifier Val ->
+  (Identifier, Val)
+makeElementWithScope mbNamespace name specs scope =
+  ( name,
+    VFunction (Just qname) scope $
+      Function $ \args -> do
+        pos <- getPosition
+        fields <- argsToFields specs args
+        pure $ VContent . Seq.singleton $ Elt qname (Just pos) fields
+  )
+  where
+    qname = case mbNamespace of
+      Nothing -> name
+      Just ns -> ns <> "." <> name
+
+argsToFields ::
+  MonadFail m =>
+  [(Identifier, TypeSpec)] ->
+  Arguments ->
+  m (M.Map Identifier Val)
+argsToFields specs args' =
+  OM.toMap . named <$> foldM go args' specs
+  where
+    hasType' TContent VContent {} = True
+    hasType' TContent VString {} = True
+    hasType' TContent VSymbol {} = True
+    hasType' TString (VContent _) = True
+    hasType' TTermItem VArray {} = True
+    hasType' x y = hasType x y
+    toType TContent x = VContent $ valToContent x
+    toType TTermItem (VArray [VContent t, VContent d]) = VTermItem t d
+    toType TTermItem (VArray [VContent t]) = VTermItem t mempty
+    toType TTermItem _ = VTermItem mempty mempty
+    toType TLabel (VContent [Lab t]) = VLabel t
+    toType _ x = x
+    go args (posname, Many ty) = do
+      let (as, bs) = span (hasType' ty) (positional args)
+      pure $
+        args
+          { named =
+              insertOM
+                posname
+                (VArray $ V.fromList $ map (toType ty) as)
+                (named args),
+            positional = bs
+          }
+    go args (posname, One ty) =
+      case break (hasType' ty) (positional args) of
+        ([], []) -> pure args
+        (as, b : bs) ->
+          pure $
+            args
+              { named = insertOM posname (toType ty b) (named args),
+                positional = as ++ bs
+              }
+        (_, []) ->
+          pure args
+
+makeFunction ::
+  (forall m'. Monad m' => ReaderT Arguments (MP m') Val) -> Val
+makeFunction f = VFunction Nothing mempty $ Function $ runReaderT f
+
+makeFunctionWithScope ::
+  (forall m'. Monad m' => ReaderT Arguments (MP m') Val) ->
+  M.Map Identifier Val ->
+  Val
+makeFunctionWithScope f m = VFunction Nothing m $ Function $ runReaderT f
+
+nthArg ::
+  (Monad m, FromVal a) =>
+  Int ->
+  ReaderT Arguments (MP m) a
+nthArg num = getPositional (num - 1) >>= fromVal
+
+getPositional :: Monad m => Int -> ReaderT Arguments (MP m) Val
+getPositional idx = do
+  xs <- asks positional
+  if idx >= length xs
+    then pure VNone
+    else pure $ xs !! idx
+
+getNamed :: Monad m => Identifier -> ReaderT Arguments (MP m) (Maybe Val)
+getNamed ident = do
+  m <- asks named
+  pure $ OM.lookup ident m
+
+namedArg ::
+  (Monad m, FromVal a) =>
+  Identifier ->
+  ReaderT Arguments (MP m) a
+namedArg ident@(Identifier ident') = do
+  mbval <- getNamed ident
+  case mbval of
+    Just val -> fromVal val
+    Nothing -> fail $ "named argument " <> T.unpack ident' <> " not defined"
+
+allArgs :: Monad m => ReaderT Arguments (MP m) [Val]
+allArgs = asks positional
+
+makeSymbolMap :: [(Text, Bool, Text)] -> M.Map Identifier Symbol
+makeSymbolMap = foldl' go mempty
+  where
+    go :: M.Map Identifier Symbol -> (Text, Bool, Text) -> M.Map Identifier Symbol
+    go m (name, accent, v) =
+      case T.split (== '.') name of
+        [] -> m
+        (k : ks) ->
+          M.alter
+            ( \case
+                Nothing ->
+                  Just $ Symbol v accent (addVariant ks v mempty)
+                Just (Symbol dv da vs) ->
+                  Just $ Symbol dv da (addVariant ks v vs)
+            )
+            (Identifier k)
+            m
+    addVariant ::
+      [Text] ->
+      Text ->
+      [(Set.Set Text, Text)] ->
+      [(Set.Set Text, Text)]
+    addVariant ks v = ((Set.fromList ks, v) :)
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main (main) where
+
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+import Data.Text.IO as TIO
+import System.FilePath (replaceExtension)
+import Test.Tasty (TestTree, Timeout (..), defaultMain, localOption, testGroup)
+import Test.Tasty.Golden (findByExtension, goldenVsStringDiff)
+import Text.Show.Pretty (ppShow)
+import Typst.Evaluate (evaluateTypst)
+import Typst.Parse (parseTypst)
+import Typst.Types (Val (VContent), repr)
+
+main :: IO ()
+main = defaultMain =<< goldenTests
+
+goldenTests :: IO TestTree
+goldenTests = do
+  inputs <- findByExtension [".typ"] "test/typ"
+  pure $
+    localOption (Timeout 100000 "100ms") $
+      testGroup "golden tests" (map runTest inputs)
+
+runTest :: FilePath -> TestTree
+runTest input =
+  goldenVsStringDiff
+    input
+    (\ref new -> ["diff", "-u", ref, new])
+    ("test/out" <> drop 8 (replaceExtension input ".out"))
+    (writeTest input)
+
+writeTest :: FilePath -> IO BL.ByteString
+writeTest input = do
+  let fromText = BL.fromStrict . TE.encodeUtf8 . (<> "\n")
+  let testCommand =
+        "#let test = (x,y) => { if x == y [✅] else [❌(#repr(x) /= #repr(y))] }\n"
+  contents <- TIO.readFile input
+  if "// Error"
+    `T.isInfixOf` contents
+    || "cycle1.typ"
+    `T.isInfixOf` contents
+    || "cycle2.typ"
+    `T.isInfixOf` contents
+    then pure $ fromText "--- skipped ---\n"
+    else do
+      let parseResult = parseTypst input (testCommand <> contents)
+      case parseResult of
+        Left e -> pure $ fromText $ T.pack $ show e
+        Right parsed -> do
+          evalResult <- evaluateTypst BS.readFile input parsed
+          let parseOutput = "--- parse tree ---\n" <> T.pack (ppShow parsed) <> "\n"
+          case evalResult of
+            Left e ->
+              pure $
+                fromText $
+                  parseOutput <> T.pack (show e)
+            Right cs -> do
+              let evalOutput = "--- evaluated ---\n" <> repr (VContent cs)
+              pure $ fromText $ parseOutput <> evalOutput
diff --git a/test/assets/files/1-writing-app.png b/test/assets/files/1-writing-app.png
new file mode 100644
Binary files /dev/null and b/test/assets/files/1-writing-app.png differ
diff --git a/test/assets/files/1-writing-upload.png b/test/assets/files/1-writing-upload.png
new file mode 100644
Binary files /dev/null and b/test/assets/files/1-writing-upload.png differ
diff --git a/test/assets/files/2-formatting-autocomplete.png b/test/assets/files/2-formatting-autocomplete.png
new file mode 100644
Binary files /dev/null and b/test/assets/files/2-formatting-autocomplete.png differ
diff --git a/test/assets/files/3-advanced-paper.png b/test/assets/files/3-advanced-paper.png
new file mode 100644
Binary files /dev/null and b/test/assets/files/3-advanced-paper.png differ
diff --git a/test/assets/files/3-advanced-team-settings.png b/test/assets/files/3-advanced-team-settings.png
new file mode 100644
Binary files /dev/null and b/test/assets/files/3-advanced-team-settings.png differ
diff --git a/test/assets/files/bad.bib b/test/assets/files/bad.bib
new file mode 100644
--- /dev/null
+++ b/test/assets/files/bad.bib
@@ -0,0 +1,6 @@
+@article{arrgh,
+    title    = {An‐arrgh‐chy: The Law and Economics of Pirate Organization},
+    author   = {Leeson, Peter T.},
+    crossref = {polecon},
+    date     = {19XXX-XX-XX},
+}
diff --git a/test/assets/files/bad.csv b/test/assets/files/bad.csv
new file mode 100644
--- /dev/null
+++ b/test/assets/files/bad.csv
@@ -0,0 +1,4 @@
+A,B
+1,2
+3,4,5
+6,7
diff --git a/test/assets/files/bad.json b/test/assets/files/bad.json
new file mode 100644
--- /dev/null
+++ b/test/assets/files/bad.json
@@ -0,0 +1,4 @@
+{
+  "valid": true,
+  "invalid": True
+}
diff --git a/test/assets/files/bad.svg b/test/assets/files/bad.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/bad.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
+  <style>
+  </g>
+</svg>
diff --git a/test/assets/files/bad.toml b/test/assets/files/bad.toml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/bad.toml
@@ -0,0 +1,1 @@
+"only a string"
diff --git a/test/assets/files/bad.txt b/test/assets/files/bad.txt
new file mode 100644
Binary files /dev/null and b/test/assets/files/bad.txt differ
diff --git a/test/assets/files/bad.xml b/test/assets/files/bad.xml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/bad.xml
@@ -0,0 +1,3 @@
+<data>
+  <hello name="hi">1
+</data>
diff --git a/test/assets/files/bad.yaml b/test/assets/files/bad.yaml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/bad.yaml
@@ -0,0 +1,1 @@
+this_will_break: [)
diff --git a/test/assets/files/cylinder.svg b/test/assets/files/cylinder.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/cylinder.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg id="uuid-687246ef-c282-44c1-b632-089ccaaded98" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
+  <defs>
+    <style>
+      .uuid-b242de72-c4d3-4028-9f50-e25a891b77c6 {
+        fill: #a3a7b7;
+      }
+
+      .uuid-b242de72-c4d3-4028-9f50-e25a891b77c6, .uuid-0c7f9eba-fb5c-4f1c-9149-e06b72f4e892 {
+        stroke: #000;
+        stroke-miterlimit: 10;
+        stroke-width: .5px;
+      }
+
+      .uuid-0c7f9eba-fb5c-4f1c-9149-e06b72f4e892 {
+        fill: url(#uuid-216aa58e-14ce-460d-a686-ba949a4e197d);
+      }
+    </style>
+    <linearGradient id="uuid-216aa58e-14ce-460d-a686-ba949a4e197d" data-name="Unbenannter Verlauf 15" x1="8.321" y1="16.001" x2="23.679" y2="16.001" gradientUnits="userSpaceOnUse">
+      <stop offset=".699" stop-color="#fff"/>
+      <stop offset="1" stop-color="#caccd6"/>
+    </linearGradient>
+  </defs>
+  <path class="uuid-0c7f9eba-fb5c-4f1c-9149-e06b72f4e892" d="m23.679,7.031v17.941c0,1.407-3.435,2.56-7.679,2.56s-7.679-1.152-7.679-2.56V7.031c0-1.418,3.435-2.56,7.679-2.56s7.679,1.141,7.679,2.56Z"/>
+  <ellipse class="uuid-b242de72-c4d3-4028-9f50-e25a891b77c6" cx="16" cy="7.029" rx="7.681" ry="2.56"/>
+</svg>
diff --git a/test/assets/files/data.csv b/test/assets/files/data.csv
new file mode 100644
--- /dev/null
+++ b/test/assets/files/data.csv
@@ -0,0 +1,3 @@
+0..2,small
+3..5,medium
+6..,big
diff --git a/test/assets/files/data.html b/test/assets/files/data.html
new file mode 100644
--- /dev/null
+++ b/test/assets/files/data.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8" />
+    <title>Example document</title>
+  </head>
+  <body>
+    <h1>Hello, world!</h1>
+  </body>
+</html>
diff --git a/test/assets/files/data.xml b/test/assets/files/data.xml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/data.xml
@@ -0,0 +1,7 @@
+<data>
+  <hello name="hi">1</hello>
+  <data>
+    <hello>World</hello>
+    <hello>World</hello>
+  </data>
+</data>
diff --git a/test/assets/files/details.toml b/test/assets/files/details.toml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/details.toml
@@ -0,0 +1,3 @@
+title = "Secret project"
+version = 2
+authors = ["Mr Robert", "Miss Enola"]
diff --git a/test/assets/files/diagram.svg b/test/assets/files/diagram.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/diagram.svg
@@ -0,0 +1,14 @@
+<svg width="550" height="356" viewBox="0 0 550 356" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="550" height="356" fill="white"/>
+<path d="M19.7071 18.2929C19.3166 17.9024 18.6834 17.9024 18.2929 18.2929L11.9289 24.6569C11.5384 25.0474 11.5384 25.6805 11.9289 26.0711C12.3194 26.4616 12.9526 26.4616 13.3431 26.0711L19 20.4142L24.6568 26.0711C25.0474 26.4616 25.6805 26.4616 26.0711 26.0711C26.4616 25.6805 26.4616 25.0474 26.0711 24.6569L19.7071 18.2929ZM20 336L20 19L18 19L18 336L20 336Z" fill="black"/>
+<path d="M525.707 336.707C526.098 336.317 526.098 335.683 525.707 335.293L519.343 328.929C518.953 328.538 518.319 328.538 517.929 328.929C517.538 329.319 517.538 329.953 517.929 330.343L523.586 336L517.929 341.657C517.538 342.047 517.538 342.681 517.929 343.071C518.319 343.462 518.953 343.462 519.343 343.071L525.707 336.707ZM19 337H525V335H19V337Z" fill="black"/>
+<text fill="black" font-family="Stupid, Inria Serif" font-size="24" letter-spacing="0em"><tspan x="34.0469" y="43.9274">Height</tspan></text>
+<text fill="black" font-family="Stupid, Inria Serif" font-size="24" font-style="italic" letter-spacing="0em"><tspan x="34.0469" y="72.9274">Height</tspan></text>
+<text fill="black" font-family="Stupid, Inria Serif" font-size="24" font-weight="bold" letter-spacing="0em"><tspan x="34.0469" y="101.927">Height</tspan></text>
+<text fill="black" font-family="Stupid, Inria Serif" font-size="24" font-style="italic" font-weight="bold" letter-spacing="0em"><tspan x="34.0469" y="130.927">Height</tspan></text>
+<text fill="black" font-size="22" font-weight="bold" letter-spacing="0em"><tspan x="99.0469" y="278.783">Without family</tspan></text>
+<text fill="black" font-family="Inter" font-size="22" font-style="italic" letter-spacing="0em"><tspan x="58.0469" y="315">With non-existing family</tspan></text>
+<text fill="black" font-family="Roboto" font-size="24" letter-spacing="0em" text-decoration="underline"><tspan x="466" y="310.703">Time</tspan></text>
+<path d="M20 335C20 335 59.8833 265.479 102 241C143.386 216.945 162.368 211.763 210 207C270 201 321.161 208.851 374 178C398.284 163.821 431 134 431 134L518 65" stroke="#2B80FF" stroke-width="2"/>
+<text transform="translate(428.859 89.5114) rotate(-38.8045)" fill="#2B80FF" xml:space="preserve" style="white-space: pre" font-family="DejaVu Sans Mono" font-size="24" font-weight="bold" letter-spacing="0em"><tspan x="0" y="22.3086">Curve</tspan></text>
+</svg>
diff --git a/test/assets/files/docs.svg b/test/assets/files/docs.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/docs.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 27.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFFFFF;filter:url(#Adobe_OpacityMaskFilter);}
+	.st1{mask:url(#path-1-inside-1_1588_6259_00000173119138975477980210000007733088185808470454_);}
+	.st2{fill:none;stroke:#000000;stroke-width:1.25;}
+	.st3{fill:none;stroke:#000000;}
+</style>
+<defs>
+	<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="-1.6" y="-2" width="18.5" height="20">
+		<feColorMatrix  type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0"/>
+	</filter>
+</defs>
+<mask maskUnits="userSpaceOnUse" x="-1.6" y="-2" width="18.5" height="20" id="path-1-inside-1_1588_6259_00000173119138975477980210000007733088185808470454_">
+	<path class="st0" d="M0.9,3.3c0-1.8,1.5-3.3,3.3-3.3h10.7v15.9H4.1c-1.8,0-3.3-1.5-3.3-3.3V3.3z"/>
+</mask>
+<path class="st1" d="M-1.6,3.3C-1.6,0.4,0.8-2,3.7-2h13.2l-4.1,4.1H4.1c-0.5,0-0.8,0.5-0.8,1.2H-1.6z M16.9,18H3.7
+	c-2.9,0-5.3-2.4-5.3-5.3h4.9c0,0.7,0.4,1.2,0.8,1.2h8.7L16.9,18z M3.7,18c-2.9,0-5.3-2.4-5.3-5.3V3.3C-1.6,0.4,0.8-2,3.7-2l0.4,4.1
+	c-0.5,0-0.8,0.5-0.8,1.2v9.4c0,0.7,0.4,1.2,0.8,1.2L3.7,18z M16.9-2v20l-4.1-4.1V2.1L16.9-2z"/>
+<line class="st2" x1="5" y1="5.3" x2="9.9" y2="5.3"/>
+<line class="st3" x1="5" y1="8.8" x2="7.8" y2="8.8"/>
+</svg>
diff --git a/test/assets/files/example.xml b/test/assets/files/example.xml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/example.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<news>
+  <article>
+    <title>2022 Budget approved</title>
+    <author>John Doe</author>
+    <date>2022-12-19</date>
+    <content>
+      <p>The 2022 budget has been approved by the Senate.</p>
+      <p>The budget is $1.2 trillion.</p>
+      <p>It is expected to be signed by the President next week.</p>
+    </content>
+  </article>
+  <article>
+    <title>Tigers win the World Series</title>
+    <author>Jane Doe</author>
+    <date>2022-12-20</date>
+    <content>
+      <p>The Tigers have won the World Series.</p>
+      <p>They beat the Giants 4 to 3.</p>
+    </content>
+  </article>
+</news>
diff --git a/test/assets/files/glacier.jpg b/test/assets/files/glacier.jpg
new file mode 100644
Binary files /dev/null and b/test/assets/files/glacier.jpg differ
diff --git a/test/assets/files/graph.png b/test/assets/files/graph.png
new file mode 100644
Binary files /dev/null and b/test/assets/files/graph.png differ
diff --git a/test/assets/files/hello.txt b/test/assets/files/hello.txt
new file mode 100644
--- /dev/null
+++ b/test/assets/files/hello.txt
@@ -0,0 +1,1 @@
+Hello, world!
diff --git a/test/assets/files/logo.svg b/test/assets/files/logo.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/logo.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.90387 2.23401C2.91909 4.55853 3.351 8.1331 5.64329 10.2912C8.24577 12.7414 11.8071 12.7414 14.6835 12.7414" stroke="#001666" stroke-width="1.25"/>
+<path d="M1.4903 8.35903C1.50283 10.6836 1.4903 14.3902 4.49755 14.3902C8.65229 14.3902 6.67331 7.41699 14.8248 7.41699" stroke="#001666" stroke-width="1.25"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5745 10.7414L12.0165 11.1834L13.5745 12.7414L12.0165 14.2995L11.5745 14.7414L12.4584 15.6253L12.9003 15.1834L14.9003 13.1834L15.3423 12.7414L14.9003 12.2995L12.9003 10.2995L12.4584 9.85754L11.5745 10.7414Z" fill="#001666"/>
+</svg>
diff --git a/test/assets/files/molecular.jpg b/test/assets/files/molecular.jpg
new file mode 100644
Binary files /dev/null and b/test/assets/files/molecular.jpg differ
diff --git a/test/assets/files/monday.json b/test/assets/files/monday.json
new file mode 100644
--- /dev/null
+++ b/test/assets/files/monday.json
@@ -0,0 +1,5 @@
+{
+  "temperature": 18.5,
+  "unit": "C",
+  "weather": "sunny"
+}
diff --git a/test/assets/files/monkey.svg b/test/assets/files/monkey.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/monkey.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Monkey emoji by Vincent Le Moign of the Streamline Emoji Project. Sourced
+     from [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:440-monkey.svg)
+     on 2021-06-12 and partially minified using SVGO. Used under the Creative
+	 Commons Attribution 4.0 International license -->
+<!--Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)-->
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48" xml:space="preserve">
+  <style>
+    .st3 {
+      fill: none;
+      stroke: #45413c;
+      stroke-linecap: round;
+      stroke-linejoin: round;
+      stroke-miterlimit: 10
+    }
+    .st8 {
+      fill: #fff48c
+    }
+    .st34 {
+      fill: #bf8256
+    }
+    .st35 {
+      fill: #dea47a
+    }
+    .st84 {
+      fill: #45413c
+    }
+  </style>
+  <g>
+    <ellipse cx="20.5" cy="44.5" rx="18" ry="1.5" style="opacity:.15;fill:#45413c"/>
+    <path d="M8.7 28.8 8 27.1c-.3-.7-.9-1.1-1.6-1-.9.1-1.6.9-1.5 1.9.7 5-.6 6.6-3 9.4-.5.5-.5 1.3-.1 1.9.4.6 1 .8 1.9.6 4.5-1.6 6.9-6.6 5-11.1z" style="fill:#ffe500"/>
+    <g>
+      <path class="st8" d="M5 29.6c.2-.6.8-1 1.4-1 .7-.1 1.4.4 1.6 1l.7 1.8c.3.6.5 1.1.6 1.7.2-1.4 0-2.9-.6-4.3L8 27.1c-.3-.7-.9-1.1-1.6-1-.9.1-1.6.9-1.5 1.9 0 .5.1 1.1.1 1.6zM2.1 39.6c2.1-2.5 3.2-4.1 2.8-8.3-.2 2.6-1.3 4-3.1 6-.5.5-.5 1.3-.1 1.9l.4.4z"/>
+    </g>
+    <path class="st3" d="M8.7 28.8 8 27.1c-.3-.7-.9-1.1-1.6-1-.9.1-1.6.9-1.5 1.9.7 5-.6 6.6-3 9.4-.5.5-.5 1.3-.1 1.9.4.6 1 .8 1.9.6 4.5-1.6 6.9-6.6 5-11.1z"/>
+    <path class="st3" d="m6.1 26.1-.7-1.8"/>
+    <path class="st3" d="m7.1 23.6-3.5 1.5"/>
+    <path class="st34" d="M30.7 19.4c-.5.9-.2 2.1.7 2.6.9.5 2.1.2 2.6-.7.9-1.7 3-2.3 4.7-1.6 3.5 1.5 5.4 5.4 4.4 9.1-1.7 6.7-7.7 11.3-14.6 11.3h-8l-.6 3.9h8.8c8.7 0 16.4-5.9 18.5-14.4 1.3-5.4-1.3-10.9-6.3-13.3-3.7-1.8-8.1-.5-10.2 3.1z"/>
+    <g>
+      <path class="st35" d="M43.4 27.9c0 .3-.1.6-.2.8C41.5 35.4 35.5 40 28.6 40h-8l-.4 2.2h8.4c6.9 0 12.9-4.6 14.6-11.3.3-1 .3-2 .2-3zM30.7 19.4c-.4.7-.3 1.5.1 2.1 2.1-3.4 6.5-4.7 10.1-3 3.8 1.8 6.2 5.4 6.6 9.4.4-4.8-2.1-9.4-6.6-11.6-3.7-1.8-8.1-.5-10.2 3.1z"/>
+    </g>
+    <path class="st3" d="M30.7 19.4c-.5.9-.2 2.1.7 2.6.9.5 2.1.2 2.6-.7.9-1.7 3-2.3 4.7-1.6 3.5 1.5 5.4 5.4 4.4 9.1-1.7 6.7-7.7 11.3-14.6 11.3h-8l-.6 3.9h8.8c8.7 0 16.4-5.9 18.5-14.4 1.3-5.4-1.3-10.9-6.3-13.3-3.7-1.8-8.1-.5-10.2 3.1z"/>
+    <path class="st34" d="M31.2 30.6c-1.6-8.2-8.8-14.2-17.2-14.2v12l-4.3-.8c-1.6-.3-2.9 1.2-2.4 2.7.2.8.9 1.4 1.7 1.5l5 .8V35c-1 1-1.6 2.5-1.5 4.1l.1 1h-.8c-1.7 0-3 1.6-2.7 3.2.1.5.5.8 1 .8h14.1c4.2 0 7.6-3.4 7.6-7.6-.1-2-.3-4-.6-5.9z"/>
+    <path d="M14 26.3c4.5 0 8.4-2.7 10.2-6.5-2.9-2.1-6.4-3.3-10.2-3.3v9.8z" style="fill:#915e3a"/>
+    <path class="st3" d="M31.2 30.6c-1.6-8.2-8.8-14.2-17.2-14.2v12l-4.3-.8c-1.6-.3-2.9 1.2-2.4 2.7.2.8.9 1.4 1.7 1.5l5 .8V35c-1 1-1.6 2.5-1.5 4.1l.1 1h-.8c-1.7 0-3 1.6-2.7 3.2.1.5.5.8 1 .8h14.1c4.2 0 7.6-3.4 7.6-7.6-.1-2-.3-4-.6-5.9z"/>
+    <path class="st34" d="M22.5 9.2h-.2C21.4 5.4 18 2.6 14 2.6S6.5 5.4 5.7 9.2h-.2c-1.8 0-3.3 1.5-3.3 3.3v.7c0 1.8 1.5 3.3 3.3 3.3h.2C6.5 20.2 9.9 23 14 23s7.4-2.8 8.3-6.6h.2c1.8 0 3.3-1.5 3.3-3.3v-.7c0-1.8-1.5-3.2-3.3-3.2z"/>
+    <path class="st35" d="M22.5 9.2h-.2C21.4 5.4 18 2.6 14 2.6c-4 0-7.4 2.8-8.3 6.6h-.2c-1.8 0-3.3 1.5-3.3 3.3v.7c0 .4.1.7.2 1 .4-1.3 1.7-2.3 3.1-2.3h.2c.8-3.8 4.2-6.6 8.3-6.6 4 0 7.4 2.8 8.3 6.6h.2c1.5 0 2.7 1 3.1 2.3.1-.3.2-.7.2-1v-.7c0-1.9-1.5-3.3-3.3-3.3z"/>
+    <path class="st3" d="M22.5 9.2h-.2C21.4 5.4 18 2.6 14 2.6S6.5 5.4 5.7 9.2h-.2c-1.8 0-3.3 1.5-3.3 3.3v.7c0 1.8 1.5 3.3 3.3 3.3h.2C6.5 20.2 9.9 23 14 23s7.4-2.8 8.3-6.6h.2c1.8 0 3.3-1.5 3.3-3.3v-.7c0-1.8-1.5-3.2-3.3-3.2z"/>
+    <path d="M18.6 15.1c1.1 1 1.7 2.4 1.7 4 0 .5-.1.9-.2 1.3C18.5 22 16.4 23 14 23c-2.8 0-5.2-1.3-6.8-3.3 0 0 0 0 0 0 0-.2-.1-.4-.1-.6 0-1.5.7-2.9 1.7-4-1-.7-1.7-1.9-1.7-3.3 0-2.2 1.8-3.9 3.9-3.9 1 0 1.9.4 2.6 1 .7-.6 1.6-1 2.6-1 2.2 0 3.9 1.8 3.9 3.9.2 1.4-.5 2.6-1.5 3.3z" style="fill:#ffdcd1;stroke:#45413c;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/>
+    <circle transform="matrix(.05447 -.9985 .9985 .05447 4.528 28.393)" class="st84" cx="17.3" cy="11.8" r="1.3"/>
+    <circle transform="matrix(.05447 -.9985 .9985 .05447 -1.682 21.835)" class="st84" cx="10.7" cy="11.8" r="1.3"/>
+    <path class="st3" d="M11.3 18.4s1.1 1.3 2.6 1.3c1.6 0 2.6-1.3 2.6-1.3"/>
+    <path class="st3" d="m14 28.4 3.5.6"/>
+    <path class="st3" d="m21.4 25 1.6 4.4c.8 2.2-1.1 4.4-3.3 4l-5.7-.8"/>
+    <path class="st3" d="M22.9 39.3c.2-3.2-2.4-5.9-5.7-5.8-1.3.1-2.4.6-3.2 1.5"/>
+  </g>
+</svg>
diff --git a/test/assets/files/pattern.svg b/test/assets/files/pattern.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/pattern.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Adapted from
+   https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Patterns under
+   CC0 / Public Domain Licensing -->
+<svg width="200" height="150" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="Gradient1">
+      <stop offset="5%" stop-color="white"/>
+      <stop offset="95%" stop-color="blue"/>
+    </linearGradient>
+    <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
+      <stop offset="5%" stop-color="red"/>
+      <stop offset="95%" stop-color="orange"/>
+    </linearGradient>
+    <pattern id="Pattern" x="40" y="10" width="50" height="50" patternUnits="userSpaceOnUse">
+      <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
+      <rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/>
+      <circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
+    </pattern>
+  </defs>
+  <rect fill="url(#Pattern)" stroke="black" width="200" height="150"/>
+</svg>
diff --git a/test/assets/files/rhino.png b/test/assets/files/rhino.png
new file mode 100644
Binary files /dev/null and b/test/assets/files/rhino.png differ
diff --git a/test/assets/files/scifi-authors.yaml b/test/assets/files/scifi-authors.yaml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/scifi-authors.yaml
@@ -0,0 +1,11 @@
+"Arthur C. Clarke": 
+  - title: Against the Fall of Night
+    published: "1978"
+  - title: The songs of distant earth
+    published: "1986"
+
+"Isaac Asimov": 
+  - title: Quasar, Quasar, Burning Bright
+    published: "1977"
+  - title: Far as Human Eye Could See 
+    published: 1987
diff --git a/test/assets/files/tetrahedron.svg b/test/assets/files/tetrahedron.svg
new file mode 100644
--- /dev/null
+++ b/test/assets/files/tetrahedron.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg id="uuid-22146e6c-a168-4821-bd5a-dea57c5059e7" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
+  <defs>
+    <style>
+      .uuid-2456d980-f63b-4fa8-8dc4-6bc7ec43cb9d {
+        fill: #a3a7b7;
+      }
+
+      .uuid-603863eb-1f17-44fc-809f-235048ac00d5 {
+        fill: none;
+        stroke: #000;
+        stroke-miterlimit: 10;
+        stroke-width: .5px;
+      }
+    </style>
+  </defs>
+  <polygon class="uuid-2456d980-f63b-4fa8-8dc4-6bc7ec43cb9d" points="29.689 20.18 15.999 26.07 15.999 5.93 29.689 20.18"/>
+  <polygon class="uuid-603863eb-1f17-44fc-809f-235048ac00d5" points="29.686 20.177 15.999 26.067 2.311 20.177 15.999 5.933 29.686 20.177"/>
+  <line class="uuid-603863eb-1f17-44fc-809f-235048ac00d5" x1="15.999" y1="5.933" x2="15.999" y2="26.067"/>
+</svg>
diff --git a/test/assets/files/tiger.jpg b/test/assets/files/tiger.jpg
new file mode 100644
Binary files /dev/null and b/test/assets/files/tiger.jpg differ
diff --git a/test/assets/files/toml-types.toml b/test/assets/files/toml-types.toml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/toml-types.toml
@@ -0,0 +1,11 @@
+string = "wonderful"
+integer = 42
+float = 3.14
+boolean = true
+date_time = 2023-02-01T15:38:57Z
+array = [1, "string", 3.0, false]
+inline_table = { first = "amazing", second = "greater" }
+
+[table]
+element = 5
+others = [false, "indeed", 7]
diff --git a/test/assets/files/tuesday.json b/test/assets/files/tuesday.json
new file mode 100644
--- /dev/null
+++ b/test/assets/files/tuesday.json
@@ -0,0 +1,5 @@
+{
+  "temperature": 14.5,
+  "unit": "C",
+  "weather": "windy"
+}
diff --git a/test/assets/files/typing.jpg b/test/assets/files/typing.jpg
new file mode 100644
Binary files /dev/null and b/test/assets/files/typing.jpg differ
diff --git a/test/assets/files/works.bib b/test/assets/files/works.bib
new file mode 100644
--- /dev/null
+++ b/test/assets/files/works.bib
@@ -0,0 +1,94 @@
+@article{netwok,
+  title={At-scale impact of the {Net Wok}: A culinarically holistic investigation of distributed dumplings},
+  author={Astley, Rick and Morris, Linda},
+  journal={Armenian Journal of Proceedings},
+  volume={61},
+  pages={192--219},
+  year={2020},
+  publisher={Automattic Inc.}
+}
+
+@www{issue201,
+	title={Use of ids field creates unstable references},
+	author={{cfr42}},
+	url={https://github.com/plk/biblatex/issues/201},
+	date={2014-02-02/2014-02-07},
+	ids={unstable, github}
+}
+
+@article{arrgh,
+	title={The Pirate Organization},
+	author={Leeson, Peter T.},
+}
+
+@article{quark,
+	title={The Quark Organization},
+	author={Leeson, Peter T.},
+}
+
+@misc{distress,
+	title={An Insight into Bibliographical Distress},
+	author={Aldrin, Buzz}
+}
+
+@article{glacier-melt,
+	author = {Regine Hock},
+	title ={Glacier melt: a review of processes and their modelling},
+	journal = {Progress in Physical Geography: Earth and Environment},
+	volume = {29},
+	number = {3},
+	pages = {362-391},
+	year = {2005},
+	doi = {10.1191/0309133305pp453ra},
+}
+
+@book{tolkien54,
+    maintitle = {The Lord of the Rings},
+    title = {The Fellowship of the Ring},
+    author = {J. R. R. Tolkien},
+    date = {1954-07-29},
+    publisher = {Allen & Unwin},
+    location = {London},
+    volume = {1},
+}
+
+
+@article{sharing,
+	title = {Do sharing people behave differently? An empirical evaluation of the distinctive mobility patterns of free-floating car-sharing members},
+	volume = {42},
+	pages = {449--469},
+	number = {3},
+	journal = {Transportation},
+	author = {Kopp, Johanna and Gerike, Regine and Axhausen, Kay W.},
+	year = {2015}
+}
+
+@book{restful,
+	location = {Sebastopol, {CA}, {USA}},
+	edition = {1},
+	title = {{RESTful} Web Services},
+	pagetotal = {448},
+	publisher = {O'Reilly Media},
+	author = {Richardson, Leonard and Ruby, Sam},
+	year = {2008}
+}
+
+@article{mcintosh_anxiety,
+	title = {Anxiety and Health Problems Related to Air Travel},
+	volume = {5},
+	issn = {1195-1982},
+	pages = {198--204},
+	number = {4},
+	journal = {Journal of Travel Medicine},
+	author = {{McIntosh}, Iain B. and Swanson, Vivien and Power, Kevin G. and Raeside, Fiona and Dempster, Craig},
+	year = {2006}
+}
+
+@book{psychology25,
+	location = {New York, {NY}, {USA}},
+	edition = {1},
+	title = {The psychology of selling and advertising},
+	publisher = {{McGraw}-Hill Book Co.},
+	author = {Strong, Edward},
+	year = {1925}
+}
diff --git a/test/assets/files/works_too.bib b/test/assets/files/works_too.bib
new file mode 100644
--- /dev/null
+++ b/test/assets/files/works_too.bib
@@ -0,0 +1,10 @@
+@article{keshav2007read,
+  title     = {How to read a paper},
+  author    = {Keshav, Srinivasan},
+  journal   = {ACM SIGCOMM Computer Communication Review},
+  volume    = {37},
+  number    = {3},
+  pages     = {83--84},
+  year      = {2007},
+  publisher = {ACM New York, NY, USA}
+}
diff --git a/test/assets/files/yaml-types.yaml b/test/assets/files/yaml-types.yaml
new file mode 100644
--- /dev/null
+++ b/test/assets/files/yaml-types.yaml
@@ -0,0 +1,8 @@
+null_key: [null, ~]
+"string": text
+integer: 5
+float: 1.12
+mapping: { '1': "one", '2': "two"}
+seq: [1, 2, 3, 4]
+bool: false
+true: bool
diff --git a/test/assets/files/zoo.csv b/test/assets/files/zoo.csv
new file mode 100644
--- /dev/null
+++ b/test/assets/files/zoo.csv
@@ -0,0 +1,4 @@
+Name,Species,Weight,Length
+Debby,Rhinoceros,1900kg,390cm
+Fluffy,Tiger,115kg,310cm
+Sleepy,Dolphin,150kg,180cm
diff --git a/test/assets/files/zoo.json b/test/assets/files/zoo.json
new file mode 100644
--- /dev/null
+++ b/test/assets/files/zoo.json
@@ -0,0 +1,20 @@
+[
+  {
+    "name": "Debby",
+    "species": "Rhinoceros",
+    "weight": 1900,
+    "length": 390
+  },
+  {
+    "name": "Fluffy",
+    "species": "Tiger",
+    "weight": 115,
+    "length": 310
+  },
+  {
+    "name": "Sleepy",
+    "species": "Dolphin",
+    "weight": 150,
+    "length": 180
+  }
+]
diff --git a/test/out/bugs/args-sink-00.out b/test/out/bugs/args-sink-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/args-sink-00.out
@@ -0,0 +1,79 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/args-sink-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/args-sink-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/args-sink-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/args-sink-00.typ"
+    ( line 2 , column 2 )
+    (LetFunc
+       (Identifier "foo")
+       [ SinkParam (Just (Identifier "body")) ]
+       (FuncCall
+          (Ident (Identifier "repr"))
+          [ NormalArg
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "pos")) (Ident (Identifier "body")))
+                 [])
+          ]))
+, SoftBreak
+, Code
+    "test/typ/bugs/args-sink-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "foo"))
+       [ KeyValArg (Identifier "a") (Literal (String "1"))
+       , KeyValArg (Identifier "b") (Literal (String "2"))
+       , NormalArg (Literal (Int 1))
+       , NormalArg (Literal (Int 2))
+       , NormalArg (Literal (Int 3))
+       , NormalArg (Literal (Int 4))
+       , NormalArg (Literal (Int 5))
+       , NormalArg (Literal (Int 6))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [(1, 2, 3, 4, 5, 6)]), 
+  parbreak() }
diff --git a/test/out/bugs/args-underscore-00.out b/test/out/bugs/args-underscore-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/args-underscore-00.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/args-underscore-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/args-underscore-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/args-underscore-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/args-underscore-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "len"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "map"))
+                       (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+                    [ NormalArg (FuncExpr [ SkipParam ] (Block (CodeBlock []))) ]))
+              [])
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/bugs/columns-1-00.out b/test/out/bugs/columns-1-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/columns-1-00.out
@@ -0,0 +1,86 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/columns-1-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/columns-1-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/columns-1-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/columns-1-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 70.0 Pt)) ])
+, ParBreak
+, Text "Hallo"
+, SoftBreak
+, Code
+    "test/typ/bugs/columns-1-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "columns"))
+       [ NormalArg (Literal (Int 2))
+       , BlockArg
+           [ SoftBreak
+           , Heading 1 [ Text "A" ]
+           , Text "Text"
+           , SoftBreak
+           , Heading 1 [ Text "B" ]
+           , Text "Text"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Hallo
+]), 
+  columns(body: { text(body: [
+]), 
+                  heading(body: text(body: [A]), 
+                          level: 1), 
+                  text(body: [Text
+]), 
+                  heading(body: text(body: [B]), 
+                          level: 1), 
+                  text(body: [Text]), 
+                  parbreak() }, 
+          count: 2), 
+  parbreak() }
diff --git a/test/out/bugs/flow-1-00.out b/test/out/bugs/flow-1-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/flow-1-00.out
@@ -0,0 +1,140 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/flow-1-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/flow-1-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/flow-1-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-1-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 70.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-1-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ BlockArg
+           [ Text "This"
+           , Space
+           , Text "file"
+           , Space
+           , Text "tests"
+           , Space
+           , Text "a"
+           , Space
+           , Text "bug"
+           , Space
+           , Text "where"
+           , Space
+           , Text "an"
+           , Space
+           , Text "almost"
+           , Space
+           , Text "empty"
+           , Space
+           , Text "page"
+           , Space
+           , Text "occurs"
+           , Text "."
+           ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-1-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ BlockArg
+           [ SoftBreak
+           , Text "The"
+           , Space
+           , Text "text"
+           , Space
+           , Text "in"
+           , Space
+           , Text "this"
+           , Space
+           , Text "second"
+           , Space
+           , Text "block"
+           , Space
+           , Text "was"
+           , Space
+           , Text "torn"
+           , Space
+           , Text "apart"
+           , Space
+           , Text "and"
+           , Space
+           , Text "split"
+           , Space
+           , Text "up"
+           , Space
+           , Text "for"
+           , SoftBreak
+           , Text "some"
+           , Space
+           , Text "reason"
+           , Space
+           , Text "beyond"
+           , Space
+           , Text "my"
+           , Space
+           , Text "knowledge"
+           , Text "."
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  block(body: text(body: [This file tests a bug where an almost empty page occurs.])), 
+  text(body: [
+]), 
+  block(body: { text(body: [
+The text in this second block was torn apart and split up for
+some reason beyond my knowledge.]), 
+                parbreak() }), 
+  parbreak() }
diff --git a/test/out/bugs/flow-2-00.out b/test/out/bugs/flow-2-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/flow-2-00.out
@@ -0,0 +1,113 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/flow-2-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/flow-2-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/flow-2-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-2-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-2-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 19.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-2-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ BlockArg
+           [ SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , Text "yonder"
+           , Space
+           , Text "window"
+           , Space
+           , Text "breaks?"
+           , SoftBreak
+           , Text "It"
+           , Space
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "east,"
+           , Space
+           , Text "and"
+           , Space
+           , Text "Juliet"
+           , Space
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "sun"
+           , Text "."
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  v(amount: 19.0pt), 
+  text(body: [
+]), 
+  block(body: { text(body: [
+But, soft! what light through yonder window breaks?
+It is the east, and Juliet is the sun.]), 
+                parbreak() }), 
+  parbreak() }
diff --git a/test/out/bugs/flow-3-00.out b/test/out/bugs/flow-3-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/flow-3-00.out
@@ -0,0 +1,111 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/flow-3-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/flow-3-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/flow-3-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-3-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-3-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "columns"))
+              [ NormalArg (Literal (Int 2))
+              , BlockArg
+                  [ SoftBreak
+                  , Text "Text"
+                  , SoftBreak
+                  , Code
+                      "test/typ/bugs/flow-3-00.typ"
+                      ( line 5 , column 4 )
+                      (FuncCall
+                         (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 12.0 Pt)) ])
+                  , SoftBreak
+                  , Text "Hi"
+                  , SoftBreak
+                  , Code
+                      "test/typ/bugs/flow-3-00.typ"
+                      ( line 7 , column 4 )
+                      (FuncCall
+                         (Ident (Identifier "v"))
+                         [ NormalArg (Literal (Numeric 10.0 Pt))
+                         , KeyValArg (Identifier "weak") (Literal (Boolean True))
+                         ])
+                  , SoftBreak
+                  , Text "At"
+                  , Space
+                  , Text "column"
+                  , Space
+                  , Text "break"
+                  , Text "."
+                  , ParBreak
+                  ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  rect(body: columns(body: { text(body: [
+Text
+]), 
+                             v(amount: 12.0pt), 
+                             text(body: [
+Hi
+]), 
+                             v(amount: 10.0pt, 
+                               weak: true), 
+                             text(body: [
+At column break.]), 
+                             parbreak() }, 
+                     count: 2), 
+       inset: 0.0pt), 
+  parbreak() }
diff --git a/test/out/bugs/flow-4-00.out b/test/out/bugs/flow-4-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/flow-4-00.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/flow-4-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/flow-4-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/flow-4-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-4-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 105.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/flow-4-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  block(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut]), 
+  parbreak() }
diff --git a/test/out/bugs/grid-1-00.out b/test/out/bugs/grid-1-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/grid-1-00.out
@@ -0,0 +1,95 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/grid-1-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/grid-1-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/grid-1-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-1-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 150.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-1-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array [ Literal (Numeric 1.5 Cm) , Literal Auto ])
+       , KeyValArg
+           (Identifier "rows") (Array [ Literal Auto , Literal Auto ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  table(children: (rect(fill: rgb(100%,25%,21%,100%), 
+                        width: 100%), 
+                   rect(fill: rgb(0%,45%,85%,100%), 
+                        width: 100%), 
+                   rect(fill: rgb(18%,80%,25%,100%), 
+                        height: 50%, 
+                        width: 100%)), 
+        columns: (1.5cm, auto), 
+        rows: (auto, auto)), 
+  parbreak() }
diff --git a/test/out/bugs/grid-1-01.out b/test/out/bugs/grid-1-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/grid-1-01.out
@@ -0,0 +1,87 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/grid-1-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/grid-1-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/grid-1-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-1-01.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+       ])
+, SoftBreak
+, BulletListItem
+    [ Code
+        "test/typ/bugs/grid-1-01.typ"
+        ( line 3 , column 4 )
+        (FuncCall
+           (Ident (Identifier "rect"))
+           [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+           , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+           ])
+    , SoftBreak
+    , BulletListItem
+        [ Code
+            "test/typ/bugs/grid-1-01.typ"
+            ( line 4 , column 6 )
+            (FuncCall
+               (Ident (Identifier "rect"))
+               [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+               , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+               ])
+        , ParBreak
+        ]
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  rect(height: 1.0em, 
+       width: 100%), 
+  text(body: [
+]), 
+  list(children: ({ rect(height: 1.0em, 
+                         width: 100%), 
+                    text(body: [
+]), 
+                    list(children: ({ rect(height: 1.0em, 
+                                           width: 100%), 
+                                      parbreak() })) })) }
diff --git a/test/out/bugs/grid-2-00.out b/test/out/bugs/grid-2-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/grid-2-00.out
@@ -0,0 +1,161 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/grid-2-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/grid-2-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/grid-2-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-2-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-2-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array [ Literal (Numeric 2.0 Cm) , Literal Auto ])
+       , KeyValArg
+           (Identifier "rows") (Array [ Literal Auto , Literal Auto ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 80.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "hello"
+                 , Space
+                 , HardBreak
+                 , Text "darkness"
+                 , Space
+                 , Code
+                     "test/typ/bugs/grid-2-00.typ"
+                     ( line 9 , column 22 )
+                     (Ident (Identifier "parbreak"))
+                 , Space
+                 , Text "my"
+                 , Space
+                 , HardBreak
+                 , Text "old"
+                 , Space
+                 , HardBreak
+                 , Text "friend"
+                 , Space
+                 , HardBreak
+                 , Text "I"
+                 ]))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 20.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "polygon"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              , NormalArg
+                  (Array
+                     [ Literal (Numeric 0.0 Percent) , Literal (Numeric 0.0 Percent) ])
+              , NormalArg
+                  (Array
+                     [ Literal (Numeric 100.0 Percent)
+                     , Literal (Numeric 0.0 Percent)
+                     ])
+              , NormalArg
+                  (Array
+                     [ Literal (Numeric 100.0 Percent)
+                     , Literal (Numeric 20.0 Percent)
+                     ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (rect(fill: rgb(100%,25%,21%,100%), 
+                       width: 100%), 
+                  rect(fill: rgb(0%,45%,85%,100%), 
+                       width: 100%), 
+                  rect(fill: rgb(18%,80%,25%,100%), 
+                       height: 80%, 
+                       width: 100%), 
+                  { text(body: [hello ]), 
+                    linebreak(), 
+                    text(body: [darkness ]), 
+                    text(body: [ my ]), 
+                    linebreak(), 
+                    text(body: [old ]), 
+                    linebreak(), 
+                    text(body: [friend ]), 
+                    linebreak(), 
+                    text(body: [I]) }, 
+                  rect(fill: rgb(0%,45%,85%,100%), 
+                       height: 20%, 
+                       width: 100%), 
+                  polygon(fill: rgb(100%,25%,21%,100%), 
+                          vertices: ((0%, 0%), 
+                                     (100%, 0%), 
+                                     (100%, 20%)))), 
+       columns: (2.0cm, auto), 
+       rows: (auto, auto)), 
+  parbreak() }
diff --git a/test/out/bugs/grid-2-01.out b/test/out/bugs/grid-2-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/grid-2-01.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/grid-2-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/grid-2-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/grid-2-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-2-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-2-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 5)) ])
+, SoftBreak
+, BulletListItem
+    [ Code
+        "test/typ/bugs/grid-2-01.typ"
+        ( line 4 , column 4 )
+        (FuncCall
+           (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 5)) ])
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet,]), 
+  text(body: [
+]), 
+  list(children: ({ text(body: [Lorem ipsum dolor sit amet,]), 
+                    parbreak() })) }
diff --git a/test/out/bugs/grid-3-00.out b/test/out/bugs/grid-3-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/grid-3-00.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/grid-3-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/grid-3-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/grid-3-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-3-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 70.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/grid-3-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 40.0 Pt)) ])
+, SoftBreak
+, Text "The"
+, Space
+, Text "following"
+, Text ":"
+, SoftBreak
+, EnumListItem Nothing [ Text "A" ]
+, SoftBreak
+, EnumListItem Nothing [ Text "B" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  v(amount: 40.0pt), 
+  text(body: [
+The following:
+]), 
+  enum(children: (text(body: [A]), 
+                  { text(body: [B]), 
+                    parbreak() })) }
diff --git a/test/out/bugs/math-realize-00.out b/test/out/bugs/math-realize-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/math-realize-00.out
@@ -0,0 +1,236 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/math-realize-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/math-realize-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/math-realize-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/math-realize-00.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "my")))
+       (Block
+          (Content
+             [ Equation
+                 False
+                 [ Code
+                     "test/typ/bugs/math-realize-00.typ"
+                     ( line 2 , column 12 )
+                     (Ident (Identifier "pi"))
+                 ]
+             ])))
+, SoftBreak
+, Code
+    "test/typ/bugs/math-realize-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "f1")))
+       (FuncCall
+          (Ident (Identifier "box"))
+          [ KeyValArg (Identifier "baseline") (Literal (Numeric 10.0 Pt))
+          , NormalArg (Block (Content [ Text "f" ]))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/bugs/math-realize-00.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "f2")))
+       (FuncCall
+          (Ident (Identifier "style"))
+          [ NormalArg
+              (FuncExpr
+                 [ NormalParam (Identifier "sty") ] (Ident (Identifier "f1")))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/bugs/math-realize-00.typ"
+    ( line 5 , column 2 )
+    (Show
+       (Just
+          (FieldAccess
+             (Ident (Identifier "vec")) (Ident (Identifier "math"))))
+       (Block (Content [ Text "nope" ])))
+, ParBreak
+, Equation
+    True
+    [ Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 7 , column 3 )
+        (Ident (Identifier "pi"))
+    , Text "a"
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 8 , column 3 )
+        (Ident (Identifier "my"))
+    , Text "a"
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "1"
+    , Text "+"
+    , Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 9 , column 7 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg [ MFrac (Text "x") (Text "2") ] ])
+    , Text "+"
+    , Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 9 , column 19 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ NormalArg
+               (FuncCall
+                  (Ident (Identifier "hide"))
+                  [ NormalArg
+                      (Block
+                         (Content [ Equation False [ MFrac (Text "x") (Text "2") ] ]))
+                  ])
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "a"
+    , Text "x"
+    , Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 10 , column 8 )
+        (FuncCall
+           (Ident (Identifier "link"))
+           [ NormalArg (Literal (String "url"))
+           , NormalArg
+               (Block (Content [ Equation False [ Text "+" , Text "b" ] ]))
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "f"
+    , Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 11 , column 5 )
+        (Ident (Identifier "f1"))
+    , Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 11 , column 8 )
+        (Ident (Identifier "f2"))
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/bugs/math-realize-00.typ"
+        ( line 12 , column 3 )
+        (FuncCall
+           (Ident (Identifier "vec"))
+           [ BlockArg [ Text "1" ] , BlockArg [ Text "2" ] ])
+    , Text "*"
+    , Text "2"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  math.equation(block: true, 
+                body: { text(body: [π]), 
+                        text(body: [a]) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.equation(block: false, 
+                                      body: text(body: [π]), 
+                                      numbering: none), 
+                        text(body: [a]) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [1]), 
+                        text(body: [+]), 
+                        math.sqrt(radicand: math.frac(denom: text(body: [2]), 
+                                                      num: text(body: [x]))), 
+                        text(body: [+]), 
+                        math.sqrt(radicand: hide(body: math.equation(block: false, 
+                                                                     body: math.frac(denom: text(body: [2]), 
+                                                                                     num: text(body: [x])), 
+                                                                     numbering: none))) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [a]), 
+                        text(body: [x]), 
+                        link(body: math.equation(block: false, 
+                                                 body: { text(body: [+]), 
+                                                         text(body: [b]) }, 
+                                                 numbering: none), 
+                             dest: "url") }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [f]), 
+                        box(baseline: 10.0pt, 
+                            body: text(body: [f])), 
+                        style(func: ) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [nope]), 
+                        text(body: [*]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/bugs/math-realize-01.out b/test/out/bugs/math-realize-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/math-realize-01.out
@@ -0,0 +1,147 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/math-realize-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/math-realize-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/math-realize-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Equation
+    True
+    [ MAttach Nothing (Just (Text "2")) (Text "x")
+    , Code
+        "test/typ/bugs/math-realize-01.typ"
+        ( line 2 , column 8 )
+        (FuncCall
+           (Ident (Identifier "hide"))
+           [ BlockArg
+               [ Equation
+                   False
+                   [ MGroup
+                       (Just "(")
+                       (Just ")")
+                       [ Text "\8805"
+                       , Code
+                           "test/typ/bugs/math-realize-01.typ"
+                           ( line 2 , column 18 )
+                           (FieldAccess (Ident (Identifier "alt")) (Ident (Identifier "phi")))
+                       ]
+                   , Code
+                       "test/typ/bugs/math-realize-01.typ"
+                       ( line 2 , column 27 )
+                       (Ident (Identifier "union"))
+                   , MAttach Nothing (Just (Text "2")) (Text "y")
+                   , Text "0"
+                   ]
+               ]
+           ])
+    , MAttach Nothing (Just (Text "2")) (Text "z")
+    ]
+, SoftBreak
+, Text "Hello"
+, Space
+, Code
+    "test/typ/bugs/math-realize-01.typ"
+    ( line 3 , column 8 )
+    (FuncCall
+       (Ident (Identifier "hide"))
+       [ BlockArg [ Text "there" , Space , Equation False [ Text "x" ] ]
+       ])
+, SoftBreak
+, Text "and"
+, Space
+, Code
+    "test/typ/bugs/math-realize-01.typ"
+    ( line 4 , column 6 )
+    (FuncCall
+       (Ident (Identifier "hide"))
+       [ BlockArg
+           [ Equation
+               True
+               [ MGroup
+                   Nothing
+                   Nothing
+                   [ Text "f" , MGroup (Just "(") (Just ")") [ Text "x" ] ]
+               , Text ":"
+               , Text "="
+               , MAttach Nothing (Just (Text "2")) (Text "x")
+               ]
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: none, 
+                                    base: text(body: [x]), 
+                                    t: text(body: [2])), 
+                        hide(body: math.equation(block: false, 
+                                                 body: { math.lr(body: ({ [(], 
+                                                                          text(body: [≥]), 
+                                                                          text(body: [ϕ]), 
+                                                                          [)] })), 
+                                                         text(body: [∪]), 
+                                                         math.attach(b: none, 
+                                                                     base: text(body: [y]), 
+                                                                     t: text(body: [2])), 
+                                                         text(body: [0]) }, 
+                                                 numbering: none)), 
+                        math.attach(b: none, 
+                                    base: text(body: [z]), 
+                                    t: text(body: [2])) }, 
+                numbering: none), 
+  text(body: [
+Hello ]), 
+  hide(body: { text(body: [there ]), 
+               math.equation(block: false, 
+                             body: text(body: [x]), 
+                             numbering: none) }), 
+  text(body: [
+and ]), 
+  hide(body: math.equation(block: true, 
+                           body: { text(body: [f]), 
+                                   math.lr(body: ({ [(], 
+                                                    text(body: [x]), 
+                                                    [)] })), 
+                                   text(body: [:]), 
+                                   text(body: [=]), 
+                                   math.attach(b: none, 
+                                               base: text(body: [x]), 
+                                               t: text(body: [2])) }, 
+                           numbering: none)), 
+  parbreak() }
diff --git a/test/out/bugs/math-realize-02.out b/test/out/bugs/math-realize-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/math-realize-02.out
@@ -0,0 +1,455 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/math-realize-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/math-realize-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/math-realize-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/bugs/math-realize-02.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "foo")
+       [ NormalParam (Identifier "v1") , NormalParam (Identifier "v2") ]
+       (Block
+          (CodeBlock
+             [ Block
+                 (Content
+                    [ Equation
+                        False
+                        [ Code
+                            "test/typ/bugs/math-realize-02.typ"
+                            ( line 6 , column 4 )
+                            (Ident (Identifier "v1"))
+                        , MAttach
+                            Nothing
+                            (Just (Text "2"))
+                            (Code
+                               "test/typ/bugs/math-realize-02.typ"
+                               ( line 6 , column 7 )
+                               (Ident (Identifier "v2")))
+                        ]
+                    ])
+             ])))
+, SoftBreak
+, Code
+    "test/typ/bugs/math-realize-02.typ"
+    ( line 8 , column 2 )
+    (LetFunc
+       (Identifier "bar")
+       [ NormalParam (Identifier "v1") , NormalParam (Identifier "v2") ]
+       (Block
+          (CodeBlock
+             [ Block
+                 (Content
+                    [ Equation
+                        True
+                        [ Code
+                            "test/typ/bugs/math-realize-02.typ"
+                            ( line 11 , column 5 )
+                            (Ident (Identifier "v1"))
+                        , MAttach
+                            Nothing
+                            (Just (Text "2"))
+                            (Code
+                               "test/typ/bugs/math-realize-02.typ"
+                               ( line 11 , column 8 )
+                               (Ident (Identifier "v2")))
+                        ]
+                    ])
+             ])))
+, SoftBreak
+, Code
+    "test/typ/bugs/math-realize-02.typ"
+    ( line 13 , column 2 )
+    (LetFunc
+       (Identifier "baz")
+       [ SinkParam (Just (Identifier "sink")) ]
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "join"))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "map"))
+                          (FuncCall
+                             (FieldAccess
+                                (Ident (Identifier "pos")) (Ident (Identifier "sink")))
+                             []))
+                       [ NormalArg
+                           (FuncExpr
+                              [ NormalParam (Identifier "x") ]
+                              (Block
+                                 (Content
+                                    [ Equation
+                                        False
+                                        [ Code
+                                            "test/typ/bugs/math-realize-02.typ"
+                                            ( line 15 , column 24 )
+                                            (FuncCall
+                                               (Ident (Identifier "hat"))
+                                               [ NormalArg (Ident (Identifier "x")) ])
+                                        ]
+                                    ])))
+                       ]))
+                 [ NormalArg
+                     (FieldAccess (Ident (Identifier "and")) (Ident (Identifier "sym")))
+                 ]
+             ])))
+, ParBreak
+, Text "Inline"
+, Space
+, Equation
+    False
+    [ Text "2"
+    , Code
+        "test/typ/bugs/math-realize-02.typ"
+        ( line 18 , column 11 )
+        (FuncCall
+           (Ident (Identifier "foo"))
+           [ BlockArg
+               [ Code
+                   "test/typ/bugs/math-realize-02.typ"
+                   ( line 18 , column 15 )
+                   (Ident (Identifier "alpha"))
+               ]
+           , BlockArg
+               [ MGroup
+                   (Just "(")
+                   (Just ")")
+                   [ Text "M"
+                   , Text "+"
+                   , Code
+                       "test/typ/bugs/math-realize-02.typ"
+                       ( line 18 , column 25 )
+                       (FuncCall
+                          (Ident (Identifier "foo"))
+                          [ BlockArg [ Text "a" ] , BlockArg [ Text "b" ] ])
+                   ]
+               ]
+           ])
+    ]
+, Text "."
+, ParBreak
+, Text "Inline"
+, Space
+, Equation
+    False
+    [ Text "2"
+    , Code
+        "test/typ/bugs/math-realize-02.typ"
+        ( line 20 , column 11 )
+        (FuncCall
+           (Ident (Identifier "bar"))
+           [ BlockArg
+               [ Code
+                   "test/typ/bugs/math-realize-02.typ"
+                   ( line 20 , column 15 )
+                   (Ident (Identifier "alpha"))
+               ]
+           , BlockArg
+               [ MGroup
+                   (Just "(")
+                   (Just ")")
+                   [ Text "M"
+                   , Text "+"
+                   , Code
+                       "test/typ/bugs/math-realize-02.typ"
+                       ( line 20 , column 25 )
+                       (FuncCall
+                          (Ident (Identifier "foo"))
+                          [ BlockArg [ Text "a" ] , BlockArg [ Text "b" ] ])
+                   ]
+               ]
+           ])
+    ]
+, Text "."
+, ParBreak
+, Text "Inline"
+, Space
+, Equation
+    False
+    [ Text "2"
+    , Code
+        "test/typ/bugs/math-realize-02.typ"
+        ( line 22 , column 11 )
+        (FuncCall
+           (Ident (Identifier "baz"))
+           [ BlockArg [ Text "x" ]
+           , BlockArg [ Text "y" ]
+           , BlockArg
+               [ Code
+                   "test/typ/bugs/math-realize-02.typ"
+                   ( line 22 , column 19 )
+                   (FuncCall
+                      (Ident (Identifier "baz"))
+                      [ BlockArg [ Text "u" ] , BlockArg [ Text "v" ] ])
+               ]
+           ])
+    ]
+, Text "."
+, ParBreak
+, Equation
+    True
+    [ Text "2"
+    , Code
+        "test/typ/bugs/math-realize-02.typ"
+        ( line 24 , column 5 )
+        (FuncCall
+           (Ident (Identifier "foo"))
+           [ BlockArg
+               [ Code
+                   "test/typ/bugs/math-realize-02.typ"
+                   ( line 24 , column 9 )
+                   (Ident (Identifier "alpha"))
+               ]
+           , BlockArg
+               [ MGroup
+                   (Just "(")
+                   (Just ")")
+                   [ Text "M"
+                   , Text "+"
+                   , Code
+                       "test/typ/bugs/math-realize-02.typ"
+                       ( line 24 , column 19 )
+                       (FuncCall
+                          (Ident (Identifier "foo"))
+                          [ BlockArg [ Text "a" ] , BlockArg [ Text "b" ] ])
+                   ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "2"
+    , Code
+        "test/typ/bugs/math-realize-02.typ"
+        ( line 25 , column 5 )
+        (FuncCall
+           (Ident (Identifier "bar"))
+           [ BlockArg
+               [ Code
+                   "test/typ/bugs/math-realize-02.typ"
+                   ( line 25 , column 9 )
+                   (Ident (Identifier "alpha"))
+               ]
+           , BlockArg
+               [ MGroup
+                   (Just "(")
+                   (Just ")")
+                   [ Text "M"
+                   , Text "+"
+                   , Code
+                       "test/typ/bugs/math-realize-02.typ"
+                       ( line 25 , column 19 )
+                       (FuncCall
+                          (Ident (Identifier "foo"))
+                          [ BlockArg [ Text "a" ] , BlockArg [ Text "b" ] ])
+                   ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "2"
+    , Code
+        "test/typ/bugs/math-realize-02.typ"
+        ( line 26 , column 5 )
+        (FuncCall
+           (Ident (Identifier "baz"))
+           [ BlockArg [ Text "x" ]
+           , BlockArg [ Text "y" ]
+           , BlockArg
+               [ Code
+                   "test/typ/bugs/math-realize-02.typ"
+                   ( line 26 , column 13 )
+                   (FuncCall
+                      (Ident (Identifier "baz"))
+                      [ BlockArg [ Text "u" ] , BlockArg [ Text "v" ] ])
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Inline ]), 
+  math.equation(block: false, 
+                body: { text(body: [2]), 
+                        math.equation(block: false, 
+                                      body: { text(body: [α]), 
+                                              math.attach(b: none, 
+                                                          base: math.lr(body: ({ [(], 
+                                                                                 text(body: [M]), 
+                                                                                 text(body: [+]), 
+                                                                                 math.equation(block: false, 
+                                                                                               body: { text(body: [a]), 
+                                                                                                       math.attach(b: none, 
+                                                                                                                   base: text(body: [b]), 
+                                                                                                                   t: text(body: [2])) }, 
+                                                                                               numbering: none), 
+                                                                                 [)] })), 
+                                                          t: text(body: [2])) }, 
+                                      numbering: none) }, 
+                numbering: none), 
+  text(body: [.]), 
+  parbreak(), 
+  text(body: [Inline ]), 
+  math.equation(block: false, 
+                body: { text(body: [2]), 
+                        text(body: [|]), 
+                        text(body: [(]), 
+                        text(body: [α]), 
+                        text(body: [,]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [M]), 
+                                         text(body: [+]), 
+                                         math.equation(block: false, 
+                                                       body: { text(body: [a]), 
+                                                               math.attach(b: none, 
+                                                                           base: text(body: [b]), 
+                                                                           t: text(body: [2])) }, 
+                                                       numbering: none), 
+                                         [)] })), 
+                        text(body: [)]) }, 
+                numbering: none), 
+  text(body: [.]), 
+  parbreak(), 
+  text(body: [Inline ]), 
+  math.equation(block: false, 
+                body: { text(body: [2]), 
+                        math.equation(block: false, 
+                                      body: math.accent(accent: ^, 
+                                                        base: text(body: [x])), 
+                                      numbering: none), 
+                        text(body: [∧]), 
+                        math.equation(block: false, 
+                                      body: math.accent(accent: ^, 
+                                                        base: text(body: [y])), 
+                                      numbering: none), 
+                        text(body: [∧]), 
+                        math.equation(block: false, 
+                                      body: math.accent(accent: ^, 
+                                                        base: { math.equation(block: false, 
+                                                                              body: math.accent(accent: ^, 
+                                                                                                base: text(body: [u])), 
+                                                                              numbering: none), 
+                                                                text(body: [∧]), 
+                                                                math.equation(block: false, 
+                                                                              body: math.accent(accent: ^, 
+                                                                                                base: text(body: [v])), 
+                                                                              numbering: none) }), 
+                                      numbering: none) }, 
+                numbering: none), 
+  text(body: [.]), 
+  parbreak(), 
+  math.equation(block: true, 
+                body: { text(body: [2]), 
+                        math.equation(block: false, 
+                                      body: { text(body: [α]), 
+                                              math.attach(b: none, 
+                                                          base: math.lr(body: ({ [(], 
+                                                                                 text(body: [M]), 
+                                                                                 text(body: [+]), 
+                                                                                 math.equation(block: false, 
+                                                                                               body: { text(body: [a]), 
+                                                                                                       math.attach(b: none, 
+                                                                                                                   base: text(body: [b]), 
+                                                                                                                   t: text(body: [2])) }, 
+                                                                                               numbering: none), 
+                                                                                 [)] })), 
+                                                          t: text(body: [2])) }, 
+                                      numbering: none) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [2]), 
+                        text(body: [|]), 
+                        text(body: [(]), 
+                        text(body: [α]), 
+                        text(body: [,]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [M]), 
+                                         text(body: [+]), 
+                                         math.equation(block: false, 
+                                                       body: { text(body: [a]), 
+                                                               math.attach(b: none, 
+                                                                           base: text(body: [b]), 
+                                                                           t: text(body: [2])) }, 
+                                                       numbering: none), 
+                                         [)] })), 
+                        text(body: [)]) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [2]), 
+                        math.equation(block: false, 
+                                      body: math.accent(accent: ^, 
+                                                        base: text(body: [x])), 
+                                      numbering: none), 
+                        text(body: [∧]), 
+                        math.equation(block: false, 
+                                      body: math.accent(accent: ^, 
+                                                        base: text(body: [y])), 
+                                      numbering: none), 
+                        text(body: [∧]), 
+                        math.equation(block: false, 
+                                      body: math.accent(accent: ^, 
+                                                        base: { math.equation(block: false, 
+                                                                              body: math.accent(accent: ^, 
+                                                                                                base: text(body: [u])), 
+                                                                              numbering: none), 
+                                                                text(body: [∧]), 
+                                                                math.equation(block: false, 
+                                                                              body: math.accent(accent: ^, 
+                                                                                                base: text(body: [v])), 
+                                                                              numbering: none) }), 
+                                      numbering: none) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/bugs/parameter-pattern-00.out b/test/out/bugs/parameter-pattern-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/parameter-pattern-00.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/parameter-pattern-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/parameter-pattern-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/parameter-pattern-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/parameter-pattern-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "map"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "zip"))
+                       (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+                    [ NormalArg
+                        (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+                    ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ DestructuringParam
+                         [ Simple Nothing , Simple (Just (Identifier "x")) ]
+                     ]
+                     (Ident (Identifier "x")))
+              ])
+       , NormalArg
+           (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/bugs/place-base-00.out b/test/out/bugs/place-base-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/place-base-00.out
@@ -0,0 +1,108 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/place-base-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/place-base-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/place-base-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/place-base-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 80.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/bugs/place-base-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "place"))
+       [ NormalArg (Ident (Identifier "right"))
+       , KeyValArg
+           (Identifier "dx") (Negated (Literal (Numeric 70.0 Percent)))
+       , KeyValArg (Identifier "dy") (Literal (Numeric 20.0 Percent))
+       , NormalArg (Block (Content [ Text "First" ]))
+       ])
+, SoftBreak
+, Code
+    "test/typ/bugs/place-base-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "place"))
+       [ NormalArg (Ident (Identifier "left"))
+       , KeyValArg (Identifier "dx") (Literal (Numeric 20.0 Percent))
+       , KeyValArg (Identifier "dy") (Literal (Numeric 60.0 Percent))
+       , NormalArg (Block (Content [ Text "Second" ]))
+       ])
+, SoftBreak
+, Code
+    "test/typ/bugs/place-base-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "place"))
+       [ NormalArg
+           (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+       , KeyValArg (Identifier "dx") (Literal (Numeric 25.0 Percent))
+       , KeyValArg (Identifier "dy") (Literal (Numeric 25.0 Percent))
+       , NormalArg (Block (Content [ Text "Third" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  place(alignment: right, 
+        body: text(body: [First]), 
+        dx: -70%, 
+        dy: 20%), 
+  text(body: [
+]), 
+  place(alignment: left, 
+        body: text(body: [Second]), 
+        dx: 20%, 
+        dy: 60%), 
+  text(body: [
+]), 
+  place(alignment: Axes(center, horizon), 
+        body: text(body: [Third]), 
+        dx: 25%, 
+        dy: 25%), 
+  parbreak() }
diff --git a/test/out/bugs/smartquotes-in-outline-00.out b/test/out/bugs/smartquotes-in-outline-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/smartquotes-in-outline-00.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/smartquotes-in-outline-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/smartquotes-in-outline-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/smartquotes-in-outline-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/smartquotes-in-outline-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 15.0 Em)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/smartquotes-in-outline-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall (Ident (Identifier "outline")) [])
+, ParBreak
+, Heading
+    1
+    [ Quote '"'
+    , Text "This"
+    , Quote '"'
+    , Space
+    , Quote '"'
+    , Text "is"
+    , Quote '"'
+    , Space
+    , Quote '"'
+    , Text "a"
+    , Quote '"'
+    , Space
+    , Quote '"'
+    , Text "test"
+    , Quote '"'
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  outline(), 
+  parbreak(), 
+  heading(body: text(body: [“This” “is” “a” “test”]), 
+          level: 1) }
diff --git a/test/out/bugs/square-base-00.out b/test/out/bugs/square-base-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/bugs/square-base-00.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/bugs/square-base-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/bugs/square-base-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/bugs/square-base-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/bugs/square-base-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 80.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/bugs/square-base-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 40.0 Percent))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 60.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 80.0 Percent))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  square(body: rect(height: 80%, 
+                    width: 60%), 
+         width: 40%), 
+  parbreak() }
diff --git a/test/out/coma-00.out b/test/out/coma-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/coma-00.out
@@ -0,0 +1,414 @@
+--- parse tree ---
+[ Code
+    "test/typ/coma-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/coma-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/coma-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/coma-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 450.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 1.0 Cm))
+       ])
+, ParBreak
+, Strong
+    [ Text "Technische"
+    , Space
+    , Text "Universit\228t"
+    , Space
+    , Text "Berlin"
+    ]
+, Space
+, Code
+    "test/typ/coma-00.typ"
+    ( line 4 , column 34 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Strong
+    [ Text "WiSe" , Space , Text "2019" , Text "/" , Text "2020" ]
+, Space
+, HardBreak
+, Strong
+    [ Text "Fakult\228t"
+    , Space
+    , Text "II,"
+    , Space
+    , Text "Institut"
+    , Space
+    , Text "for"
+    , Space
+    , Text "Mathematik"
+    ]
+, Space
+, Code
+    "test/typ/coma-00.typ"
+    ( line 5 , column 41 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "Woche"
+, Space
+, Text "3"
+, Space
+, HardBreak
+, Text "Sekretariat"
+, Space
+, Text "MA"
+, Space
+, HardBreak
+, Text "Dr"
+, Text "."
+, Space
+, Text "Max"
+, Space
+, Text "Mustermann"
+, Space
+, HardBreak
+, Text "Ola"
+, Space
+, Text "Nordmann,"
+, Space
+, Text "John"
+, Space
+, Text "Doe"
+, ParBreak
+, Code
+    "test/typ/coma-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Mm)) ])
+, SoftBreak
+, Code
+    "test/typ/coma-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/coma-00.typ"
+               ( line 12 , column 4 )
+               (Set
+                  (Ident (Identifier "par"))
+                  [ KeyValArg (Identifier "leading") (Literal (Numeric 3.0 Mm)) ])
+           , SoftBreak
+           , Code
+               "test/typ/coma-00.typ"
+               ( line 13 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "text"))
+                  [ NormalArg (Literal (Numeric 1.2 Em))
+                  , BlockArg
+                      [ Strong
+                          [ Text "3"
+                          , Text "."
+                          , Space
+                          , Text "\220bungsblatt"
+                          , Space
+                          , Text "Computerorientierte"
+                          , Space
+                          , Text "Mathematik"
+                          , Space
+                          , Text "II"
+                          ]
+                      ]
+                  ])
+           , Space
+           , HardBreak
+           , Strong
+               [ Text "Abgabe"
+               , Text ":"
+               , Space
+               , Text "03"
+               , Text "."
+               , Text "05"
+               , Text "."
+               , Text "2019"
+               ]
+           , Space
+           , Text "("
+           , Text "bis"
+           , Space
+           , Text "10"
+           , Text ":"
+           , Text "10"
+           , Space
+           , Text "Uhr"
+           , Space
+           , Text "in"
+           , Space
+           , Text "MA"
+           , Space
+           , Text "001)"
+           , Space
+           , HardBreak
+           , Strong
+               [ Text "Alle"
+               , Space
+               , Text "Antworten"
+               , Space
+               , Text "sind"
+               , Space
+               , Text "zu"
+               , Space
+               , Text "beweisen"
+               , Text "."
+               ]
+           , ParBreak
+           ]
+       ])
+, ParBreak
+, Strong [ Text "1" , Text "." , Space , Text "Aufgabe" ]
+, Space
+, Code
+    "test/typ/coma-00.typ"
+    ( line 18 , column 15 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "("
+, Text "1"
+, Space
+, Text "+"
+, Space
+, Text "1"
+, Space
+, Text "+"
+, Space
+, Text "2"
+, Space
+, Text "Punkte)"
+, ParBreak
+, Text "Ein"
+, Space
+, Emph [ Text "Bin\228rbaum" ]
+, Space
+, Text "ist"
+, Space
+, Text "ein"
+, Space
+, Text "Wurzelbaum,"
+, Space
+, Text "in"
+, Space
+, Text "dem"
+, Space
+, Text "jeder"
+, Space
+, Text "Knoten"
+, Space
+, Text "\8804"
+, Space
+, Text "2"
+, Space
+, Text "Kinder"
+, Space
+, Text "hat"
+, Text "."
+, SoftBreak
+, Text "Die"
+, Space
+, Text "Tiefe"
+, Space
+, Text "eines"
+, Space
+, Text "Knotens"
+, Space
+, Emph [ Text "v" ]
+, Space
+, Text "ist"
+, Space
+, Text "die"
+, Space
+, Text "L\228nge"
+, Space
+, Text "des"
+, Space
+, Text "eindeutigen"
+, Space
+, Text "Weges"
+, Space
+, Text "von"
+, Space
+, Text "der"
+, Space
+, Text "Wurzel"
+, SoftBreak
+, Text "zu"
+, Space
+, Emph [ Text "v" ]
+, Text ","
+, Space
+, Text "und"
+, Space
+, Text "die"
+, Space
+, Text "H\246he"
+, Space
+, Text "von"
+, Space
+, Emph [ Text "v" ]
+, Space
+, Text "ist"
+, Space
+, Text "die"
+, Space
+, Text "L\228nge"
+, Space
+, Text "eines"
+, Space
+, Text "l\228ngsten"
+, Space
+, Text "("
+, Text "absteigenden)"
+, Space
+, Text "Weges"
+, SoftBreak
+, Text "von"
+, Space
+, Emph [ Text "v" ]
+, Space
+, Text "zu"
+, Space
+, Text "einem"
+, Space
+, Text "Blatt"
+, Text "."
+, Space
+, Text "Die"
+, Space
+, Text "H\246he"
+, Space
+, Text "des"
+, Space
+, Text "Baumes"
+, Space
+, Text "ist"
+, Space
+, Text "die"
+, Space
+, Text "H\246he"
+, Space
+, Text "der"
+, Space
+, Text "Wurzel"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/coma-00.typ"
+    ( line 25 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "/graph.png"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 75.0 Percent))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  strong(body: text(body: [Technische Universität Berlin])), 
+  text(body: [ ]), 
+  h(amount: 1.0fr), 
+  text(body: [ ]), 
+  strong(body: text(body: [WiSe 2019/2020])), 
+  text(body: [ ]), 
+  linebreak(), 
+  strong(body: text(body: [Fakultät II, Institut for Mathematik])), 
+  text(body: [ ]), 
+  h(amount: 1.0fr), 
+  text(body: [ Woche 3 ]), 
+  linebreak(), 
+  text(body: [Sekretariat MA ]), 
+  linebreak(), 
+  text(body: [Dr. Max Mustermann ]), 
+  linebreak(), 
+  text(body: [Ola Nordmann, John Doe]), 
+  parbreak(), 
+  v(amount: 3.0mm), 
+  text(body: [
+]), 
+  align(alignment: center, 
+        body: { text(body: [
+]), 
+                text(body: [
+]), 
+                text(body: strong(body: text(body: [3. Übungsblatt Computerorientierte Mathematik II])), 
+                     size: 1.2em), 
+                text(body: [ ]), 
+                linebreak(), 
+                strong(body: text(body: [Abgabe: 03.05.2019])), 
+                text(body: [ (bis 10:10 Uhr in MA 001) ]), 
+                linebreak(), 
+                strong(body: text(body: [Alle Antworten sind zu beweisen.])), 
+                parbreak() }), 
+  parbreak(), 
+  strong(body: text(body: [1. Aufgabe])), 
+  text(body: [ ]), 
+  h(amount: 1.0fr), 
+  text(body: [ (1 + 1 + 2 Punkte)]), 
+  parbreak(), 
+  text(body: [Ein ]), 
+  emph(body: text(body: [Binärbaum])), 
+  text(body: [ ist ein Wurzelbaum, in dem jeder Knoten ≤ 2 Kinder hat.
+Die Tiefe eines Knotens ]), 
+  emph(body: text(body: [v])), 
+  text(body: [ ist die Länge des eindeutigen Weges von der Wurzel
+zu ]), 
+  emph(body: text(body: [v])), 
+  text(body: [, und die Höhe von ]), 
+  emph(body: text(body: [v])), 
+  text(body: [ ist die Länge eines längsten (absteigenden) Weges
+von ]), 
+  emph(body: text(body: [v])), 
+  text(body: [ zu einem Blatt. Die Höhe des Baumes ist die Höhe der Wurzel.]), 
+  parbreak(), 
+  align(alignment: center, 
+        body: image(path: "/graph.png", 
+                    width: 75%)), 
+  parbreak() }
diff --git a/test/out/compiler/array-00.out b/test/out/compiler/array-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-00.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/array-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 150.0 Pt)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/array-00.typ" ( line 7 , column 2 ) (Array [])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/array-00.typ"
+    ( line 10 , column 2 )
+    (Literal (Int 1))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/array-00.typ"
+    ( line 13 , column 2 )
+    (Array [ Negated (Literal (Int 1)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/array-00.typ"
+    ( line 16 , column 2 )
+    (Array [ Literal (Boolean True) , Literal (Boolean False) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/array-00.typ"
+    ( line 19 , column 2 )
+    (Array
+       [ Literal (String "1")
+       , FuncCall
+           (Ident (Identifier "rgb")) [ NormalArg (Literal (String "002")) ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [()]), 
+  parbreak(), 
+  text(body: [1]), 
+  parbreak(), 
+  text(body: [(-1)]), 
+  parbreak(), 
+  text(body: [(true, false)]), 
+  parbreak(), 
+  text(body: [("1", rgb(0%,0%,0%,100%))]), 
+  parbreak() }
diff --git a/test/out/compiler/array-01.out b/test/out/compiler/array-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-01.out
@@ -0,0 +1,79 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall (FieldAccess (Ident (Identifier "len")) (Array [])) [])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "len"))
+                 (Array
+                    [ Literal (String "A")
+                    , Literal (String "B")
+                    , Literal (String "C")
+                    ]))
+              [])
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-02.out b/test/out/compiler/array-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-02.out
@@ -0,0 +1,79 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-02.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "array")))
+              (Array [ Literal (Int 1) , Literal (Int 2) ])
+          , Assign
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "at")) (Ident (Identifier "array")))
+                 [ NormalArg (Literal (Int 1)) ])
+              (Plus
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "at")) (Ident (Identifier "array")))
+                    [ NormalArg (Literal (Int 1)) ])
+                 (Plus
+                    (Literal (Int 5))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "at")) (Ident (Identifier "array")))
+                       [ NormalArg (Literal (Int 0)) ])))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "array"))
+              , NormalArg (Array [ Literal (Int 1) , Literal (Int 8) ])
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-03.out b/test/out/compiler/array-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-03.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-03.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "array")))
+              (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+          , Assign
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "first")) (Ident (Identifier "array")))
+                 [])
+              (Literal (Int 7))
+          , Assign
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "at")) (Ident (Identifier "array")))
+                 [ NormalArg (Literal (Int 1)) ])
+              (Times
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "at")) (Ident (Identifier "array")))
+                    [ NormalArg (Literal (Int 1)) ])
+                 (Literal (Int 8)))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "array"))
+              , NormalArg
+                  (Array [ Literal (Int 7) , Literal (Int 16) , Literal (Int 3) ])
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-04.out b/test/out/compiler/array-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-05.out b/test/out/compiler/array-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-06.out b/test/out/compiler/array-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-06.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-06.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "at"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [ NormalArg (Literal (Int 2))
+              , KeyValArg (Identifier "default") (Literal (Int 5))
+              ])
+       , NormalArg (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-06.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "at"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [ NormalArg (Literal (Int 3))
+              , KeyValArg (Identifier "default") (Literal (Int 5))
+              ])
+       , NormalArg (Literal (Int 5))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-07.out b/test/out/compiler/array-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-08.out b/test/out/compiler/array-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-09.out b/test/out/compiler/array-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-09.out
@@ -0,0 +1,112 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-09.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "array")))
+              (Array
+                 [ Literal (Int 1)
+                 , Literal (Int 2)
+                 , Literal (Int 3)
+                 , Literal (Int 4)
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "at")) (Ident (Identifier "array")))
+                     [ NormalArg (Literal (Int 0)) ])
+              , NormalArg (Literal (Int 1))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "at")) (Ident (Identifier "array")))
+                     [ NormalArg (Negated (Literal (Int 1))) ])
+              , NormalArg (Literal (Int 4))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "at")) (Ident (Identifier "array")))
+                     [ NormalArg (Negated (Literal (Int 2))) ])
+              , NormalArg (Literal (Int 3))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "at")) (Ident (Identifier "array")))
+                     [ NormalArg (Negated (Literal (Int 3))) ])
+              , NormalArg (Literal (Int 2))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "at")) (Ident (Identifier "array")))
+                     [ NormalArg (Negated (Literal (Int 4))) ])
+              , NormalArg (Literal (Int 1))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-10.out b/test/out/compiler/array-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-10.out
@@ -0,0 +1,111 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-10.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-10.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-10.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-10.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "first")) (Array [ Literal (Int 1) ]))
+              [])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-10.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "last")) (Array [ Literal (Int 2) ]))
+              [])
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-10.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "first"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-10.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "last"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [])
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-11.out b/test/out/compiler/array-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-12.out b/test/out/compiler/array-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-13.out b/test/out/compiler/array-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-13.out
@@ -0,0 +1,107 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-13.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-13.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-13.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-13.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "tasks")))
+              (Dict
+                 [ ( Identifier "a"
+                   , Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]
+                   )
+                 , ( Identifier "b"
+                   , Array [ Literal (Int 4) , Literal (Int 5) , Literal (Int 6) ]
+                   )
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "pop"))
+                        (FuncCall
+                           (FieldAccess
+                              (Ident (Identifier "at")) (Ident (Identifier "tasks")))
+                           [ NormalArg (Literal (String "a")) ]))
+                     [])
+              , NormalArg (Literal (Int 3))
+              ]
+          , FuncCall
+              (FieldAccess
+                 (Ident (Identifier "push"))
+                 (FieldAccess
+                    (Ident (Identifier "b")) (Ident (Identifier "tasks"))))
+              [ NormalArg (Literal (Int 7)) ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FieldAccess (Ident (Identifier "a")) (Ident (Identifier "tasks")))
+              , NormalArg (Array [ Literal (Int 1) , Literal (Int 2) ])
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "at")) (Ident (Identifier "tasks")))
+                     [ NormalArg (Literal (String "b")) ])
+              , NormalArg
+                  (Array
+                     [ Literal (Int 4)
+                     , Literal (Int 5)
+                     , Literal (Int 6)
+                     , Literal (Int 7)
+                     ])
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-14.out b/test/out/compiler/array-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-14.out
@@ -0,0 +1,90 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-14.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-14.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-14.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-14.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "array")))
+              (Array
+                 [ Literal (Int 0)
+                 , Literal (Int 1)
+                 , Literal (Int 2)
+                 , Literal (Int 4)
+                 , Literal (Int 5)
+                 ])
+          , FuncCall
+              (FieldAccess
+                 (Ident (Identifier "insert")) (Ident (Identifier "array")))
+              [ NormalArg (Literal (Int 3)) , NormalArg (Literal (Int 3)) ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "array"))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "range")) [ NormalArg (Literal (Int 6)) ])
+              ]
+          , FuncCall
+              (FieldAccess
+                 (Ident (Identifier "remove")) (Ident (Identifier "array")))
+              [ NormalArg (Literal (Int 1)) ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "array"))
+              , NormalArg
+                  (Array
+                     [ Literal (Int 0)
+                     , Literal (Int 2)
+                     , Literal (Int 3)
+                     , Literal (Int 4)
+                     , Literal (Int 5)
+                     ])
+              ]
+          ]))
+, ParBreak
+]
+"test/typ/compiler/array-14.typ" (line 3, column 2):
+unexpected end of input
+expecting end of input
+Can't combine VContent (fromList [Elt {eltName = Identifier "text", eltPos = Just "test/typ/compiler/array-14.typ" (line 3, column 2), eltFields = fromList [(Identifier "body",VContent (fromList [Txt "\9989"]))]}]) and VInteger 1
diff --git a/test/out/compiler/array-15.out b/test/out/compiler/array-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-15.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-16.out b/test/out/compiler/array-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-16.out
@@ -0,0 +1,215 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-16.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-16.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-16.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice"))
+                 (Array
+                    [ Literal (Int 1)
+                    , Literal (Int 2)
+                    , Literal (Int 3)
+                    , Literal (Int 4)
+                    ]))
+              [ NormalArg (Literal (Int 2)) ])
+       , NormalArg (Array [ Literal (Int 3) , Literal (Int 4) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice"))
+                 (FuncCall
+                    (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ]))
+              [ NormalArg (Literal (Int 2)) , NormalArg (Literal (Int 6)) ])
+       , NormalArg
+           (Array
+              [ Literal (Int 2)
+              , Literal (Int 3)
+              , Literal (Int 4)
+              , Literal (Int 5)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice"))
+                 (FuncCall
+                    (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ]))
+              [ NormalArg (Literal (Int 4))
+              , KeyValArg (Identifier "count") (Literal (Int 3))
+              ])
+       , NormalArg
+           (Array [ Literal (Int 4) , Literal (Int 5) , Literal (Int 6) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice"))
+                 (FuncCall
+                    (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ]))
+              [ NormalArg (Negated (Literal (Int 5)))
+              , KeyValArg (Identifier "count") (Literal (Int 2))
+              ])
+       , NormalArg (Array [ Literal (Int 5) , Literal (Int 6) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [ NormalArg (Literal (Int 2))
+              , NormalArg (Negated (Literal (Int 2)))
+              ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [ NormalArg (Negated (Literal (Int 2)))
+              , NormalArg (Literal (Int 2))
+              ])
+       , NormalArg (Array [ Literal (Int 2) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [ NormalArg (Negated (Literal (Int 3)))
+              , NormalArg (Literal (Int 2))
+              ])
+       , NormalArg (Array [ Literal (Int 1) , Literal (Int 2) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-16.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "join"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "slice"))
+                       (FuncCall
+                          (FieldAccess
+                             (Ident (Identifier "split")) (Literal (String "ABCD")))
+                          [ NormalArg (Literal (String "")) ]))
+                    [ NormalArg (Literal (Int 1))
+                    , NormalArg (Negated (Literal (Int 1)))
+                    ]))
+              [ NormalArg (Literal (String "-")) ])
+       , NormalArg (Literal (String "A-B-C-D"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-17.out b/test/out/compiler/array-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-17.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-18.out b/test/out/compiler/array-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-18.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-19.out b/test/out/compiler/array-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-19.out
@@ -0,0 +1,127 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-19.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-19.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-19.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-19.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "position"))
+                 (Array
+                    [ Literal (String "Hi")
+                    , Literal (String "\10084\65039")
+                    , Literal (String "Love")
+                    ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "s") ]
+                     (Equals
+                        (Ident (Identifier "s")) (Literal (String "\10084\65039"))))
+              ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-19.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "position"))
+                 (Array
+                    [ Literal (String "Bye")
+                    , Literal (String "\128152")
+                    , Literal (String "Apart")
+                    ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "s") ]
+                     (Equals
+                        (Ident (Identifier "s")) (Literal (String "\10084\65039"))))
+              ])
+       , NormalArg (Literal None)
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-19.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "position"))
+                 (Array
+                    [ Literal (String "A")
+                    , Literal (String "B")
+                    , Literal (String "CDEF")
+                    , Literal (String "G")
+                    ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "v") ]
+                     (GreaterThan
+                        (FuncCall
+                           (FieldAccess (Ident (Identifier "len")) (Ident (Identifier "v")))
+                           [])
+                        (Literal (Int 2))))
+              ])
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-20.out b/test/out/compiler/array-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-20.out
@@ -0,0 +1,116 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-20.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-20.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-20.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-20.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "filter")) (Array []))
+              [ NormalArg
+                  (FieldAccess
+                     (Ident (Identifier "even")) (Ident (Identifier "calc")))
+              ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-20.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "filter"))
+                 (Array
+                    [ Literal (Int 1)
+                    , Literal (Int 2)
+                    , Literal (Int 3)
+                    , Literal (Int 4)
+                    ]))
+              [ NormalArg
+                  (FieldAccess
+                     (Ident (Identifier "even")) (Ident (Identifier "calc")))
+              ])
+       , NormalArg (Array [ Literal (Int 2) , Literal (Int 4) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-20.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "filter"))
+                 (Array
+                    [ Literal (Int 7)
+                    , Literal (Int 3)
+                    , Literal (Int 2)
+                    , Literal (Int 5)
+                    , Literal (Int 1)
+                    ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ]
+                     (LessThan (Ident (Identifier "x")) (Literal (Int 5))))
+              ])
+       , NormalArg
+           (Array [ Literal (Int 3) , Literal (Int 2) , Literal (Int 1) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-21.out b/test/out/compiler/array-21.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-21.out
@@ -0,0 +1,85 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-21.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-21.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-21.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-21.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "map")) (Array []))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ]
+                     (Times (Ident (Identifier "x")) (Literal (Int 2))))
+              ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-21.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "map"))
+                 (Array [ Literal (Int 2) , Literal (Int 3) ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ]
+                     (Times (Ident (Identifier "x")) (Literal (Int 2))))
+              ])
+       , NormalArg (Array [ Literal (Int 4) , Literal (Int 6) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-22.out b/test/out/compiler/array-22.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-22.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-22.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-22.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-22.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-22.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "fold")) (Array []))
+              [ NormalArg (Literal (String "hi"))
+              , NormalArg (Ident (Identifier "grid"))
+              ])
+       , NormalArg (Literal (String "hi"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-22.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "fold"))
+                 (Array
+                    [ Literal (Int 1)
+                    , Literal (Int 2)
+                    , Literal (Int 3)
+                    , Literal (Int 4)
+                    ]))
+              [ NormalArg (Literal (Int 0))
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "s") , NormalParam (Identifier "x") ]
+                     (Plus (Ident (Identifier "s")) (Ident (Identifier "x"))))
+              ])
+       , NormalArg (Literal (Int 10))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-23.out b/test/out/compiler/array-23.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-23.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-24.out b/test/out/compiler/array-24.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-24.out
@@ -0,0 +1,92 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-24.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-24.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-24.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-24.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "sum")) (Array []))
+              [ KeyValArg (Identifier "default") (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-24.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "sum")) (Array []))
+              [ KeyValArg (Identifier "default") (Block (Content [])) ])
+       , NormalArg (Block (Content []))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-24.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sum"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [])
+       , NormalArg (Literal (Int 6))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-25.out b/test/out/compiler/array-25.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-25.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-26.out b/test/out/compiler/array-26.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-26.out
@@ -0,0 +1,110 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-26.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-26.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-26.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-26.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "product")) (Array []))
+              [ KeyValArg (Identifier "default") (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-26.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "product")) (Array []))
+              [ KeyValArg (Identifier "default") (Block (Content [])) ])
+       , NormalArg (Block (Content []))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-26.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "product"))
+                 (Array [ Block (Content [ Text "ab" ]) , Literal (Int 3) ]))
+              [])
+       , NormalArg
+           (Times (Block (Content [ Text "ab" ])) (Literal (Int 3)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-26.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "product"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ]))
+              [])
+       , NormalArg (Literal (Int 6))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-27.out b/test/out/compiler/array-27.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-27.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-28.out b/test/out/compiler/array-28.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-28.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-28.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-28.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-28.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-28.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "rev"))
+                 (FuncCall
+                    (Ident (Identifier "range")) [ NormalArg (Literal (Int 3)) ]))
+              [])
+       , NormalArg
+           (Array [ Literal (Int 2) , Literal (Int 1) , Literal (Int 0) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-29.out b/test/out/compiler/array-29.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-29.out
@@ -0,0 +1,120 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-29.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-29.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-29.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-29.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall (FieldAccess (Ident (Identifier "join")) (Array [])) [])
+       , NormalArg (Literal None)
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-29.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "join")) (Array [ Literal (Int 1) ]))
+              [])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-29.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "join"))
+                 (Array
+                    [ Literal (String "a")
+                    , Literal (String "b")
+                    , Literal (String "c")
+                    ]))
+              [])
+       , NormalArg (Literal (String "abc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-29.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (Plus
+                 (Literal (String "("))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "join"))
+                       (Array
+                          [ Literal (String "a")
+                          , Literal (String "b")
+                          , Literal (String "c")
+                          ]))
+                    [ NormalArg (Literal (String ", ")) ]))
+              (Literal (String ")")))
+       , NormalArg (Literal (String "(a, b, c)"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-30.out b/test/out/compiler/array-30.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-30.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-31.out b/test/out/compiler/array-31.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-31.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-32.out b/test/out/compiler/array-32.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-32.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-32.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-32.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-32.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/array-32.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "join"))
+          (Array
+             [ Block (Content [ Text "One" ])
+             , Block (Content [ Text "Two" ])
+             , Block (Content [ Text "Three" ])
+             ]))
+       [ NormalArg (Block (Content [ Text "," , Space ]))
+       , KeyValArg
+           (Identifier "last")
+           (Block (Content [ Space , Text "and" , Space ]))
+       ])
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [One]), 
+  text(body: [, ]), 
+  text(body: [Two]), 
+  text(body: [ and ]), 
+  text(body: [Three]), 
+  text(body: [.]), 
+  parbreak() }
diff --git a/test/out/compiler/array-33.out b/test/out/compiler/array-33.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-33.out
@@ -0,0 +1,318 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-33.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-33.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-33.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "sorted")) (Array [])) [])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "sorted")) (Array []))
+              [ KeyValArg
+                  (Identifier "key")
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ] (Ident (Identifier "x")))
+              ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sorted"))
+                 (Times
+                    (Array [ Literal (Boolean True) , Literal (Boolean False) ])
+                    (Literal (Int 10))))
+              [])
+       , NormalArg
+           (Plus
+              (Times (Array [ Literal (Boolean False) ]) (Literal (Int 10)))
+              (Times (Array [ Literal (Boolean True) ]) (Literal (Int 10))))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sorted"))
+                 (Array
+                    [ Literal (String "it")
+                    , Literal (String "the")
+                    , Literal (String "hi")
+                    , Literal (String "text")
+                    ]))
+              [])
+       , NormalArg
+           (Array
+              [ Literal (String "hi")
+              , Literal (String "it")
+              , Literal (String "text")
+              , Literal (String "the")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sorted"))
+                 (Array
+                    [ Literal (String "I")
+                    , Literal (String "the")
+                    , Literal (String "hi")
+                    , Literal (String "text")
+                    ]))
+              [ KeyValArg
+                  (Identifier "key")
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ] (Ident (Identifier "x")))
+              ])
+       , NormalArg
+           (Array
+              [ Literal (String "I")
+              , Literal (String "hi")
+              , Literal (String "text")
+              , Literal (String "the")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sorted"))
+                 (Array
+                    [ Literal (String "I")
+                    , Literal (String "the")
+                    , Literal (String "hi")
+                    , Literal (String "text")
+                    ]))
+              [ KeyValArg
+                  (Identifier "key")
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ]
+                     (FuncCall
+                        (FieldAccess (Ident (Identifier "len")) (Ident (Identifier "x")))
+                        []))
+              ])
+       , NormalArg
+           (Array
+              [ Literal (String "I")
+              , Literal (String "hi")
+              , Literal (String "the")
+              , Literal (String "text")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sorted"))
+                 (Array
+                    [ Literal (Int 2)
+                    , Literal (Int 1)
+                    , Literal (Int 3)
+                    , Literal (Int 10)
+                    , Literal (Int 5)
+                    , Literal (Int 8)
+                    , Literal (Int 6)
+                    , Negated (Literal (Int 7))
+                    , Literal (Int 2)
+                    ]))
+              [])
+       , NormalArg
+           (Array
+              [ Negated (Literal (Int 7))
+              , Literal (Int 1)
+              , Literal (Int 2)
+              , Literal (Int 2)
+              , Literal (Int 3)
+              , Literal (Int 5)
+              , Literal (Int 6)
+              , Literal (Int 8)
+              , Literal (Int 10)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sorted"))
+                 (Array
+                    [ Literal (Int 2)
+                    , Literal (Int 1)
+                    , Literal (Int 3)
+                    , Negated (Literal (Int 10))
+                    , Negated (Literal (Int 5))
+                    , Literal (Int 8)
+                    , Literal (Int 6)
+                    , Negated (Literal (Int 7))
+                    , Literal (Int 2)
+                    ]))
+              [ KeyValArg
+                  (Identifier "key")
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ] (Ident (Identifier "x")))
+              ])
+       , NormalArg
+           (Array
+              [ Negated (Literal (Int 10))
+              , Negated (Literal (Int 7))
+              , Negated (Literal (Int 5))
+              , Literal (Int 1)
+              , Literal (Int 2)
+              , Literal (Int 2)
+              , Literal (Int 3)
+              , Literal (Int 6)
+              , Literal (Int 8)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-33.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "sorted"))
+                 (Array
+                    [ Literal (Int 2)
+                    , Literal (Int 1)
+                    , Literal (Int 3)
+                    , Negated (Literal (Int 10))
+                    , Negated (Literal (Int 5))
+                    , Literal (Int 8)
+                    , Literal (Int 6)
+                    , Negated (Literal (Int 7))
+                    , Literal (Int 2)
+                    ]))
+              [ KeyValArg
+                  (Identifier "key")
+                  (FuncExpr
+                     [ NormalParam (Identifier "x") ]
+                     (Times (Ident (Identifier "x")) (Ident (Identifier "x"))))
+              ])
+       , NormalArg
+           (Array
+              [ Literal (Int 1)
+              , Literal (Int 2)
+              , Literal (Int 2)
+              , Literal (Int 3)
+              , Negated (Literal (Int 5))
+              , Literal (Int 6)
+              , Negated (Literal (Int 7))
+              , Literal (Int 8)
+              , Negated (Literal (Int 10))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-34.out b/test/out/compiler/array-34.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-34.out
@@ -0,0 +1,185 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/array-34.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/array-34.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/array-34.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/array-34.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "zip")) (Array []))
+              [ NormalArg (Array []) ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-34.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "zip")) (Array [ Literal (Int 1) ]))
+              [ NormalArg (Array []) ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-34.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "zip")) (Array [ Literal (Int 1) ]))
+              [ NormalArg (Array [ Literal (Int 2) ]) ])
+       , NormalArg (Array [ Array [ Literal (Int 1) , Literal (Int 2) ] ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-34.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "zip"))
+                 (Array [ Literal (Int 1) , Literal (Int 2) ]))
+              [ NormalArg (Array [ Literal (Int 3) , Literal (Int 4) ]) ])
+       , NormalArg
+           (Array
+              [ Array [ Literal (Int 1) , Literal (Int 3) ]
+              , Array [ Literal (Int 2) , Literal (Int 4) ]
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-34.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "zip"))
+                 (Array
+                    [ Literal (Int 1)
+                    , Literal (Int 2)
+                    , Literal (Int 3)
+                    , Literal (Int 4)
+                    ]))
+              [ NormalArg (Array [ Literal (Int 5) , Literal (Int 6) ]) ])
+       , NormalArg
+           (Array
+              [ Array [ Literal (Int 1) , Literal (Int 5) ]
+              , Array [ Literal (Int 2) , Literal (Int 6) ]
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-34.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "zip"))
+                 (Array
+                    [ Array [ Literal (Int 1) , Literal (Int 2) ] , Literal (Int 3) ]))
+              [ NormalArg (Array [ Literal (Int 4) , Literal (Int 5) ]) ])
+       , NormalArg
+           (Array
+              [ Array
+                  [ Array [ Literal (Int 1) , Literal (Int 2) ] , Literal (Int 4) ]
+              , Array [ Literal (Int 3) , Literal (Int 5) ]
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/array-34.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "zip"))
+                 (Array [ Literal (Int 1) , Literal (String "hi") ]))
+              [ NormalArg
+                  (Array [ Literal (Boolean True) , Literal (Boolean False) ])
+              ])
+       , NormalArg
+           (Array
+              [ Array [ Literal (Int 1) , Literal (Boolean True) ]
+              , Array [ Literal (String "hi") , Literal (Boolean False) ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/array-35.out b/test/out/compiler/array-35.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-35.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-36.out b/test/out/compiler/array-36.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-36.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-37.out b/test/out/compiler/array-37.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-37.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/array-38.out b/test/out/compiler/array-38.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/array-38.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/bench-00.out b/test/out/compiler/bench-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/bench-00.out
@@ -0,0 +1,476 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/bench-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/bench-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 450.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 1.0 Cm))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 8 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "city"))) (Literal (String "Berlin")))
+, ParBreak
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 13 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "university")))
+       (Block
+          (Content
+             [ Strong
+                 [ Text "Technische"
+                 , Space
+                 , Text "Universit\228t"
+                 , Space
+                 , Code
+                     "test/typ/compiler/bench-00.typ"
+                     ( line 13 , column 45 )
+                     (Ident (Identifier "city"))
+                 ]
+             ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 14 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "faculty")))
+       (Block
+          (Content
+             [ Strong
+                 [ Text "Fakult\228t"
+                 , Space
+                 , Text "II,"
+                 , Space
+                 , Text "Institut"
+                 , Space
+                 , Text "for"
+                 , Space
+                 , Text "Mathematik"
+                 ]
+             ])))
+, ParBreak
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ BlockArg
+           [ SoftBreak
+           , Comment
+           , Space
+           , Code
+               "test/typ/compiler/bench-00.typ"
+               ( line 21 , column 4 )
+               (Ident (Identifier "university"))
+           , Space
+           , HardBreak
+           , Code
+               "test/typ/compiler/bench-00.typ"
+               ( line 22 , column 4 )
+               (Ident (Identifier "faculty"))
+           , Space
+           , HardBreak
+           , Text "Sekretariat"
+           , Space
+           , Text "MA"
+           , Space
+           , HardBreak
+           , Text "Dr"
+           , Text "."
+           , Space
+           , Text "Max"
+           , Space
+           , Text "Mustermann"
+           , Space
+           , HardBreak
+           , Text "Ola"
+           , Space
+           , Text "Nordmann,"
+           , Space
+           , Text "John"
+           , Space
+           , Text "Doe"
+           , ParBreak
+           ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 27 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "right"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "box"))
+              [ BlockArg
+                  [ Strong
+                      [ Text "WiSe" , Space , Text "2019" , Text "/" , Text "2020" ]
+                  , Space
+                  , HardBreak
+                  , Text "Woche"
+                  , Space
+                  , Text "3"
+                  ]
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 30 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 6.0 Mm)) ])
+, ParBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 34 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , BlockArg
+           [ SoftBreak
+           , Comment
+           , Space
+           , Heading
+               4
+               [ Text "3"
+               , Text "."
+               , Space
+               , Text "\220bungsblatt"
+               , Space
+               , Text "Computerorientierte"
+               , Space
+               , Text "Mathematik"
+               , Space
+               , Text "II"
+               , Space
+               , Code
+                   "test/typ/compiler/bench-00.typ"
+                   ( line 36 , column 58 )
+                   (FuncCall
+                      (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 4.0 Mm)) ])
+               ]
+           , Strong
+               [ Text "Abgabe"
+               , Text ":"
+               , Space
+               , Text "03"
+               , Text "."
+               , Text "05"
+               , Text "."
+               , Text "2019"
+               ]
+           , Space
+           , Text "("
+           , Text "bis"
+           , Space
+           , Text "10"
+           , Text ":"
+           , Text "10"
+           , Space
+           , Text "Uhr"
+           , Space
+           , Text "in"
+           , Space
+           , Text "MA"
+           , Space
+           , Text "001)"
+           , Space
+           , Code
+               "test/typ/compiler/bench-00.typ"
+               ( line 37 , column 51 )
+               (FuncCall
+                  (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 4.0 Mm)) ])
+           , SoftBreak
+           , Strong
+               [ Text "Alle"
+               , Space
+               , Text "Antworten"
+               , Space
+               , Text "sind"
+               , Space
+               , Text "zu"
+               , Space
+               , Text "beweisen"
+               , Text "."
+               ]
+           , ParBreak
+           ]
+       ])
+, ParBreak
+, Strong [ Text "1" , Text "." , Space , Text "Aufgabe" ]
+, Space
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 41 , column 15 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "right"))
+       , BlockArg
+           [ Text "("
+           , Text "1"
+           , Space
+           , Text "+"
+           , Space
+           , Text "1"
+           , Space
+           , Text "+"
+           , Space
+           , Text "2"
+           , Space
+           , Text "Punkte)"
+           ]
+       ])
+, ParBreak
+, Text "Ein"
+, Space
+, Emph [ Text "Bin\228rbaum" ]
+, Space
+, Text "ist"
+, Space
+, Text "ein"
+, Space
+, Text "Wurzelbaum,"
+, Space
+, Text "in"
+, Space
+, Text "dem"
+, Space
+, Text "jeder"
+, Space
+, Text "Knoten"
+, Space
+, Text "\8804"
+, Space
+, Text "2"
+, Space
+, Text "Kinder"
+, Space
+, Text "hat"
+, Text "."
+, SoftBreak
+, Text "Die"
+, Space
+, Text "Tiefe"
+, Space
+, Text "eines"
+, Space
+, Text "Knotens"
+, Space
+, Emph [ Text "v" ]
+, Space
+, Text "ist"
+, Space
+, Text "die"
+, Space
+, Text "L\228nge"
+, Space
+, Text "des"
+, Space
+, Text "eindeutigen"
+, Space
+, Text "Weges"
+, Space
+, Text "von"
+, Space
+, Text "der"
+, Space
+, Text "Wurzel"
+, SoftBreak
+, Text "zu"
+, Space
+, Emph [ Text "v" ]
+, Text ","
+, Space
+, Text "und"
+, Space
+, Text "die"
+, Space
+, Text "H\246he"
+, Space
+, Text "von"
+, Space
+, Emph [ Text "v" ]
+, Space
+, Text "ist"
+, Space
+, Text "die"
+, Space
+, Text "L\228nge"
+, Space
+, Text "eines"
+, Space
+, Text "l\228ngsten"
+, Space
+, Text "("
+, Text "absteigenden)"
+, Space
+, Text "Weges"
+, SoftBreak
+, Text "von"
+, Space
+, Emph [ Text "v" ]
+, Space
+, Text "zu"
+, Space
+, Text "einem"
+, Space
+, Text "Blatt"
+, Text "."
+, Space
+, Text "Die"
+, Space
+, Text "H\246he"
+, Space
+, Text "des"
+, Space
+, Text "Baumes"
+, Space
+, Text "ist"
+, Space
+, Text "die"
+, Space
+, Text "H\246he"
+, Space
+, Text "der"
+, Space
+, Text "Wurzel"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/compiler/bench-00.typ"
+    ( line 48 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 6.0 Mm)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [
+]), 
+  parbreak(), 
+  box(body: { text(body: [
+]), 
+              text(body: [ ]), 
+              strong(body: { text(body: [Technische Universität ]), 
+                             text(body: [Berlin]) }), 
+              text(body: [ ]), 
+              linebreak(), 
+              strong(body: text(body: [Fakultät II, Institut for Mathematik])), 
+              text(body: [ ]), 
+              linebreak(), 
+              text(body: [Sekretariat MA ]), 
+              linebreak(), 
+              text(body: [Dr. Max Mustermann ]), 
+              linebreak(), 
+              text(body: [Ola Nordmann, John Doe]), 
+              parbreak() }), 
+  text(body: [
+]), 
+  align(alignment: right, 
+        body: box(body: { strong(body: text(body: [WiSe 2019/2020])), 
+                          text(body: [ ]), 
+                          linebreak(), 
+                          text(body: [Woche 3]) })), 
+  parbreak(), 
+  v(amount: 6.0mm), 
+  parbreak(), 
+  align(alignment: center, 
+        body: { text(body: [
+]), 
+                text(body: [ ]), 
+                heading(body: { text(body: [3. Übungsblatt Computerorientierte Mathematik II ]), 
+                                v(amount: 4.0mm) }, 
+                        level: 4), 
+                strong(body: text(body: [Abgabe: 03.05.2019])), 
+                text(body: [ (bis 10:10 Uhr in MA 001) ]), 
+                v(amount: 4.0mm), 
+                text(body: [
+]), 
+                strong(body: text(body: [Alle Antworten sind zu beweisen.])), 
+                parbreak() }), 
+  parbreak(), 
+  strong(body: text(body: [1. Aufgabe])), 
+  text(body: [ ]), 
+  align(alignment: right, 
+        body: text(body: [(1 + 1 + 2 Punkte)])), 
+  parbreak(), 
+  text(body: [Ein ]), 
+  emph(body: text(body: [Binärbaum])), 
+  text(body: [ ist ein Wurzelbaum, in dem jeder Knoten ≤ 2 Kinder hat.
+Die Tiefe eines Knotens ]), 
+  emph(body: text(body: [v])), 
+  text(body: [ ist die Länge des eindeutigen Weges von der Wurzel
+zu ]), 
+  emph(body: text(body: [v])), 
+  text(body: [, und die Höhe von ]), 
+  emph(body: text(body: [v])), 
+  text(body: [ ist die Länge eines längsten (absteigenden) Weges
+von ]), 
+  emph(body: text(body: [v])), 
+  text(body: [ zu einem Blatt. Die Höhe des Baumes ist die Höhe der Wurzel.]), 
+  parbreak(), 
+  v(amount: 6.0mm), 
+  parbreak() }
diff --git a/test/out/compiler/block-00.out b/test/out/compiler/block-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-00.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/block-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/block-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/block-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/block-00.typ"
+    ( line 5 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "parts")))
+              (Array [ Literal (String "my fri") , Literal (String "end.") ])
+          , Block (Content [ Text "Hello," , Space ])
+          , For
+              (BasicBind (Just (Identifier "s")))
+              (Ident (Identifier "parts"))
+              (Block
+                 (Content
+                    [ Code
+                        "test/typ/compiler/block-00.typ"
+                        ( line 8 , column 20 )
+                        (Ident (Identifier "s"))
+                    ]))
+          ]))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/block-00.typ"
+    ( line 12 , column 2 )
+    (Block
+       (CodeBlock
+          [ Block (Content [ Text "How" ])
+          , If
+              [ ( Literal (Boolean True)
+                , Block (CodeBlock [ Literal (String " are") ])
+                )
+              ]
+          , Block (Content [ Space ])
+          , If
+              [ ( Literal (Boolean False) , Block (Content [ Text "Nope" ]) ) ]
+          , Plus (Block (Content [ Text "you" ])) (Literal (String "?"))
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Hello, ]), 
+  text(body: [my fri]), 
+  text(body: [end.]), 
+  parbreak(), 
+  text(body: [How]), 
+  text(body: [ are]), 
+  text(body: [ ]), 
+  text(body: [you]), 
+  text(body: [?]), 
+  parbreak() }
diff --git a/test/out/compiler/block-01.out b/test/out/compiler/block-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-01.out
@@ -0,0 +1,135 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/block-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/block-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/block-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/block-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Block (CodeBlock [])) , NormalArg (Literal None) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/block-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Block
+              (CodeBlock
+                 [ Let (BasicBind (Just (Identifier "v"))) (Literal (Int 0)) ]))
+       , NormalArg (Literal None)
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/block-01.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Block (CodeBlock [ Literal (String "hello") ]))
+       , NormalArg (Literal (String "hello"))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/block-01.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Block
+              (CodeBlock
+                 [ Let (BasicBind (Just (Identifier "x"))) (Literal (String "m"))
+                 , Plus (Ident (Identifier "x")) (Literal (String "y"))
+                 ]))
+       , NormalArg (Literal (String "my"))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/block-01.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Block
+              (CodeBlock
+                 [ Let (BasicBind (Just (Identifier "x"))) (Literal (Int 1))
+                 , Let (BasicBind (Just (Identifier "y"))) (Literal (Int 2))
+                 , Plus (Ident (Identifier "x")) (Ident (Identifier "y"))
+                 ]))
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/block-01.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Block
+              (CodeBlock
+                 [ FuncCall
+                     (Ident (Identifier "type")) [ NormalArg (Literal (String "")) ]
+                 , Literal None
+                 ]))
+       , NormalArg (Literal (String "string"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/block-02.out b/test/out/compiler/block-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/block-03.out b/test/out/compiler/block-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/block-04.out b/test/out/compiler/block-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/block-05.out b/test/out/compiler/block-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/block-06.out b/test/out/compiler/block-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-06.out
@@ -0,0 +1,87 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/block-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/block-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/block-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/block-06.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let (BasicBind (Just (Identifier "a"))) (Literal (String "a1"))
+          , Block
+              (CodeBlock
+                 [ Let (BasicBind (Just (Identifier "a"))) (Literal (String "a2"))
+                 , Block
+                     (CodeBlock
+                        [ FuncCall
+                            (Ident (Identifier "test"))
+                            [ NormalArg (Ident (Identifier "a"))
+                            , NormalArg (Literal (String "a2"))
+                            ]
+                        , Let (BasicBind (Just (Identifier "a"))) (Literal (String "a3"))
+                        , FuncCall
+                            (Ident (Identifier "test"))
+                            [ NormalArg (Ident (Identifier "a"))
+                            , NormalArg (Literal (String "a3"))
+                            ]
+                        ])
+                 , FuncCall
+                     (Ident (Identifier "test"))
+                     [ NormalArg (Ident (Identifier "a"))
+                     , NormalArg (Literal (String "a2"))
+                     ]
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "a"))
+              , NormalArg (Literal (String "a1"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/block-07.out b/test/out/compiler/block-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/block-08.out b/test/out/compiler/block-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/block-09.out b/test/out/compiler/block-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/block-10.out b/test/out/compiler/block-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/block-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/break-continue-00.out b/test/out/compiler/break-continue-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-00.out
@@ -0,0 +1,112 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-00.typ"
+    ( line 4 , column 2 )
+    (Let (BasicBind (Just (Identifier "var"))) (Literal (Int 0)))
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-00.typ"
+    ( line 5 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "error"))) (Literal (Boolean False)))
+, ParBreak
+, Code
+    "test/typ/compiler/break-continue-00.typ"
+    ( line 7 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ])
+       (Block
+          (CodeBlock
+             [ Assign
+                 (Ident (Identifier "var"))
+                 (Plus (Ident (Identifier "var")) (Ident (Identifier "i")))
+             , If
+                 [ ( GreaterThan (Ident (Identifier "i")) (Literal (Int 5))
+                   , Block
+                       (CodeBlock
+                          [ Break
+                          , Assign
+                              (Binding (BasicBind (Just (Identifier "error"))))
+                              (Literal (Boolean True))
+                          ])
+                   )
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/break-continue-00.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "var"))
+       , NormalArg (Literal (Int 21))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-00.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "error"))
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-01.out b/test/out/compiler/break-continue-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-01.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-01.typ"
+    ( line 4 , column 2 )
+    (Let (BasicBind (Just (Identifier "i"))) (Literal (Int 0)))
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-01.typ"
+    ( line 5 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "x")))
+       (While
+          (Literal (Boolean True))
+          (Block
+             (CodeBlock
+                [ Assign
+                    (Ident (Identifier "i"))
+                    (Plus (Ident (Identifier "i")) (Literal (Int 1)))
+                , FuncCall
+                    (Ident (Identifier "str")) [ NormalArg (Ident (Identifier "i")) ]
+                , If
+                    [ ( GreaterThanOrEqual (Ident (Identifier "i")) (Literal (Int 5))
+                      , Block (CodeBlock [ Literal (String ".") , Break ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/compiler/break-continue-01.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (String "12345."))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-02.out b/test/out/compiler/break-continue-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-02.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-02.typ"
+    ( line 4 , column 2 )
+    (Let (BasicBind (Just (Identifier "i"))) (Literal (Int 0)))
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-02.typ"
+    ( line 5 , column 2 )
+    (Let (BasicBind (Just (Identifier "x"))) (Literal (Int 0)))
+, ParBreak
+, Code
+    "test/typ/compiler/break-continue-02.typ"
+    ( line 7 , column 2 )
+    (While
+       (LessThan (Ident (Identifier "x")) (Literal (Int 8)))
+       (Block
+          (CodeBlock
+             [ Assign
+                 (Ident (Identifier "i"))
+                 (Plus (Ident (Identifier "i")) (Literal (Int 1)))
+             , If
+                 [ ( Equals
+                       (FuncCall
+                          (FieldAccess
+                             (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+                          [ NormalArg (Ident (Identifier "i"))
+                          , NormalArg (Literal (Int 3))
+                          ])
+                       (Literal (Int 0))
+                   , Block (CodeBlock [ Continue ])
+                   )
+                 ]
+             , Assign
+                 (Ident (Identifier "x"))
+                 (Plus (Ident (Identifier "x")) (Ident (Identifier "i")))
+             ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/break-continue-02.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Int 12))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-03.out b/test/out/compiler/break-continue-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-03.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-03.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "x")))
+       (For
+          (BasicBind (Just (Identifier "i")))
+          (FuncCall
+             (Ident (Identifier "range")) [ NormalArg (Literal (Int 5)) ])
+          (Block
+             (CodeBlock
+                [ Literal (String "a")
+                , If
+                    [ ( Equals
+                          (FuncCall
+                             (FieldAccess
+                                (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+                             [ NormalArg (Ident (Identifier "i"))
+                             , NormalArg (Literal (Int 3))
+                             ])
+                          (Literal (Int 0))
+                      , Block (CodeBlock [ Literal (String "_") , Continue ])
+                      )
+                    ]
+                , FuncCall
+                    (Ident (Identifier "str")) [ NormalArg (Ident (Identifier "i")) ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/compiler/break-continue-03.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (String "a_a1a2a_a4"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-04.out b/test/out/compiler/break-continue-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/break-continue-05.out b/test/out/compiler/break-continue-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-05.out
@@ -0,0 +1,86 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/break-continue-05.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "identity")
+       [ NormalParam (Identifier "x") ]
+       (Ident (Identifier "x")))
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-05.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "out")))
+       (For
+          (BasicBind (Just (Identifier "i")))
+          (FuncCall
+             (Ident (Identifier "range")) [ NormalArg (Literal (Int 5)) ])
+          (Block
+             (CodeBlock
+                [ Literal (String "A")
+                , FuncCall
+                    (Ident (Identifier "identity"))
+                    [ NormalArg (Block (CodeBlock [ Literal (String "B") , Break ])) ]
+                , Literal (String "C")
+                ]))))
+, ParBreak
+, Code
+    "test/typ/compiler/break-continue-05.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "out"))
+       , NormalArg (Literal (String "AB"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-06.out b/test/out/compiler/break-continue-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/break-continue-07.out b/test/out/compiler/break-continue-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/break-continue-08.out b/test/out/compiler/break-continue-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-08.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/break-continue-08.typ"
+    ( line 4 , column 2 )
+    (For
+       (BasicBind Nothing)
+       (FuncCall
+          (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ])
+       (Block
+          (CodeBlock
+             [ Block (Content [ Text "Hello" , Space ])
+             , Block
+                 (Content
+                    [ Text "World"
+                    , Space
+                    , Code
+                        "test/typ/compiler/break-continue-08.typ"
+                        ( line 6 , column 11 )
+                        (Block (CodeBlock [ Block (Content [ Text "\127758" ]) , Break ]))
+                    ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Hello ]), 
+  text(body: [World ]), 
+  text(body: [🌎]), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-09.out b/test/out/compiler/break-continue-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-09.out
@@ -0,0 +1,160 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/break-continue-09.typ"
+    ( line 5 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "color")))
+       (Array
+          [ Ident (Identifier "red")
+          , Ident (Identifier "blue")
+          , Ident (Identifier "green")
+          , Ident (Identifier "yellow")
+          ])
+       (Block
+          (Content
+             [ SoftBreak
+             , Code
+                 "test/typ/compiler/break-continue-09.typ"
+                 ( line 6 , column 4 )
+                 (Set
+                    (Ident (Identifier "text"))
+                    [ KeyValArg (Identifier "font") (Literal (String "Roboto")) ])
+             , SoftBreak
+             , Code
+                 "test/typ/compiler/break-continue-09.typ"
+                 ( line 7 , column 4 )
+                 (Show
+                    Nothing
+                    (FuncExpr
+                       [ NormalParam (Identifier "it") ]
+                       (FuncCall
+                          (Ident (Identifier "text"))
+                          [ KeyValArg (Identifier "fill") (Ident (Identifier "color"))
+                          , NormalArg (Ident (Identifier "it"))
+                          ])))
+             , SoftBreak
+             , Code
+                 "test/typ/compiler/break-continue-09.typ"
+                 ( line 8 , column 4 )
+                 (FuncCall
+                    (Ident (Identifier "smallcaps"))
+                    [ NormalArg
+                        (If
+                           [ ( Not
+                                 (Equals (Ident (Identifier "color")) (Ident (Identifier "green")))
+                             , Block (Content [ SoftBreak , Text "Some" , ParBreak ])
+                             )
+                           , ( Literal (Boolean True)
+                             , Block
+                                 (Content
+                                    [ SoftBreak
+                                    , Text "Last"
+                                    , SoftBreak
+                                    , Code
+                                        "test/typ/compiler/break-continue-09.typ"
+                                        ( line 12 , column 6 )
+                                        Break
+                                    , ParBreak
+                                    ])
+                             )
+                           ])
+                    ])
+             , ParBreak
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       font: "Roboto"), 
+  text(body: { text(body: [
+], 
+                    font: "Roboto"), 
+               smallcaps(body: { text(body: [
+Some], 
+                                      font: "Roboto"), 
+                                 parbreak() }), 
+               parbreak() }, 
+       fill: rgb(100%,25%,21%,100%), 
+       font: "Roboto"), 
+  text(body: [
+], 
+       font: "Roboto"), 
+  text(body: [
+], 
+       font: "Roboto"), 
+  text(body: { text(body: [
+], 
+                    font: "Roboto"), 
+               smallcaps(body: { text(body: [
+Some], 
+                                      font: "Roboto"), 
+                                 parbreak() }), 
+               parbreak() }, 
+       fill: rgb(0%,45%,85%,100%), 
+       font: "Roboto"), 
+  text(body: [
+], 
+       font: "Roboto"), 
+  text(body: [
+], 
+       font: "Roboto"), 
+  text(body: { text(body: [
+], 
+                    font: "Roboto"), 
+               smallcaps(body: { text(body: [
+Last
+], 
+                                      font: "Roboto"), 
+                                 parbreak() }), 
+               parbreak() }, 
+       fill: rgb(18%,80%,25%,100%), 
+       font: "Roboto"), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-10.out b/test/out/compiler/break-continue-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-10.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-10.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-10.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-10.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/break-continue-10.typ"
+    ( line 5 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ])
+       (Block
+          (CodeBlock
+             [ Block (Content [ Text "Hello" ])
+             , Set
+                 (Ident (Identifier "text"))
+                 [ NormalArg (Ident (Identifier "blue")) , SpreadArg Break ]
+             , Block (Content [ Text "Not" , Space , Text "happening" ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Hello]), 
+  parbreak() }
diff --git a/test/out/compiler/break-continue-11.out b/test/out/compiler/break-continue-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/break-continue-11.out
@@ -0,0 +1,113 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/break-continue-11.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/break-continue-11.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/break-continue-11.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/break-continue-11.typ"
+    ( line 5 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "table"))
+                 [ NormalArg
+                     (Block (CodeBlock [ Block (Content [ Text "A" ]) , Break ]))
+                 , NormalArg
+                     (For
+                        (BasicBind Nothing)
+                        (FuncCall
+                           (Ident (Identifier "range")) [ NormalArg (Literal (Int 3)) ])
+                        (Block (Content [ Text "B" ])))
+                 ]
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  table(children: (text(body: [A]), 
+                   { text(body: [B]), 
+                     text(body: [B]), 
+                     text(body: [B]) })), 
+  parbreak() }
diff --git a/test/out/compiler/call-00.out b/test/out/compiler/call-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-00.out
@@ -0,0 +1,203 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/call-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/call-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/call-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 5 , column 2 )
+    (LetFunc (Identifier "f") [] (Block (CodeBlock [])))
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 6 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/compiler/call-00.typ"
+              ( line 6 , column 4 )
+              (FuncCall (Ident (Identifier "f")) [])
+          , Strong [ Text "Bold" ]
+          ]))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 9 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "x") , NormalParam (Identifier "body") ]
+       (FuncExpr
+          [ NormalParam (Identifier "y") ]
+          (Plus
+             (Plus
+                (Block
+                   (Content
+                      [ Code
+                          "test/typ/compiler/call-00.typ"
+                          ( line 9 , column 28 )
+                          (Ident (Identifier "x"))
+                      ]))
+                (Ident (Identifier "body")))
+             (Block
+                (Content
+                   [ Code
+                       "test/typ/compiler/call-00.typ"
+                       ( line 9 , column 42 )
+                       (Ident (Identifier "y"))
+                   ])))))
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (FuncCall
+          (Ident (Identifier "f"))
+          [ NormalArg (Literal (Int 1)) , BlockArg [ Text "2" ] ])
+       [ NormalArg (Literal (Int 3)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 13 , column 2 )
+    (Ident (Identifier "test"))
+, Space
+, Text "("
+, Text "it)"
+, ParBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 15 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "body") ]
+       (Ident (Identifier "body")))
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 16 , column 2 )
+    (FuncCall (Ident (Identifier "f")) [ BlockArg [ Text "A" ] ])
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 17 , column 2 )
+    (FuncCall (Ident (Identifier "f")) [ BlockArg [ Text "A" ] ])
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "f"))
+       [ NormalArg (Block (Content [ Text "A" ])) ])
+, ParBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 20 , column 2 )
+    (LetFunc
+       (Identifier "g")
+       [ NormalParam (Identifier "a") , NormalParam (Identifier "b") ]
+       (Plus (Ident (Identifier "a")) (Ident (Identifier "b"))))
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "g"))
+       [ BlockArg [ Text "A" ] , BlockArg [ Text "B" ] ])
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "g"))
+       [ NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Block (Content [ Text "B" ]))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/call-00.typ"
+    ( line 23 , column 2 )
+    (FuncCall
+       (Ident (Identifier "g"))
+       [ BlockArg [ Text "A" ] , BlockArg [ Text "B" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  strong(body: text(body: [Bold])), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [1]), 
+  text(body: [2]), 
+  text(body: [3]), 
+  parbreak(), 
+  text(body: [ (it)]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [
+]), 
+  text(body: [A]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [B]), 
+  text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [B]), 
+  text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [B]), 
+  parbreak() }
diff --git a/test/out/compiler/call-01.out b/test/out/compiler/call-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-01.out
@@ -0,0 +1,114 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/call-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/call-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/call-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/call-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Plus (Literal (Int 1)) (Literal (Int 1)))
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/call-01.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "alias")))
+       (Ident (Identifier "type")))
+, SoftBreak
+, Code
+    "test/typ/compiler/call-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "alias"))
+              [ NormalArg (Ident (Identifier "alias")) ])
+       , NormalArg (Literal (String "function"))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/call-01.typ"
+    ( line 10 , column 2 )
+    (Block
+       (CodeBlock
+          [ FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "type")) [ NormalArg (Literal (String "hi")) ])
+              , NormalArg (Literal (String "string"))
+              ]
+          , LetFunc
+              (Identifier "adder")
+              [ NormalParam (Identifier "dx") ]
+              (FuncExpr
+                 [ NormalParam (Identifier "x") ]
+                 (Plus (Ident (Identifier "x")) (Ident (Identifier "dx"))))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FuncCall
+                        (Ident (Identifier "adder")) [ NormalArg (Literal (Int 2)) ])
+                     [ NormalArg (Literal (Int 5)) ])
+              , NormalArg (Literal (Int 7))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/call-02.out b/test/out/compiler/call-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-03.out b/test/out/compiler/call-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-04.out b/test/out/compiler/call-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-05.out b/test/out/compiler/call-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-06.out b/test/out/compiler/call-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-07.out b/test/out/compiler/call-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-08.out b/test/out/compiler/call-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-09.out b/test/out/compiler/call-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/call-10.out b/test/out/compiler/call-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/call-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-00.out b/test/out/compiler/closure-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-00.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/closure-00.typ"
+    ( line 5 , column 2 )
+    (Let (BasicBind (Just (Identifier "x"))) (Literal (String "x")))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-00.typ"
+    ( line 8 , column 2 )
+    (FuncExpr
+       [ NormalParam (Identifier "x") ] (Ident (Identifier "y")))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak() }
diff --git a/test/out/compiler/closure-01.out b/test/out/compiler/closure-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-01.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-01.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "adder")))
+              (FuncExpr
+                 [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+                 (Plus (Ident (Identifier "x")) (Ident (Identifier "y"))))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "adder"))
+                     [ NormalArg (Literal (Int 2)) , NormalArg (Literal (Int 3)) ])
+              , NormalArg (Literal (Int 5))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-02.out b/test/out/compiler/closure-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-02.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/closure-02.typ"
+    ( line 4 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "chain")))
+              (FuncExpr
+                 [ NormalParam (Identifier "f") , NormalParam (Identifier "g") ]
+                 (FuncExpr
+                    [ NormalParam (Identifier "x") ]
+                    (FuncCall
+                       (Ident (Identifier "f"))
+                       [ NormalArg
+                           (FuncCall
+                              (Ident (Identifier "g")) [ NormalArg (Ident (Identifier "x")) ])
+                       ])))
+          , Let
+              (BasicBind (Just (Identifier "f")))
+              (FuncExpr
+                 [ NormalParam (Identifier "x") ]
+                 (Plus (Ident (Identifier "x")) (Literal (Int 1))))
+          , Let
+              (BasicBind (Just (Identifier "g")))
+              (FuncExpr
+                 [ NormalParam (Identifier "x") ]
+                 (Times (Literal (Int 2)) (Ident (Identifier "x"))))
+          , Let
+              (BasicBind (Just (Identifier "h")))
+              (FuncCall
+                 (Ident (Identifier "chain"))
+                 [ NormalArg (Ident (Identifier "f"))
+                 , NormalArg (Ident (Identifier "g"))
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall (Ident (Identifier "h")) [ NormalArg (Literal (Int 2)) ])
+              , NormalArg (Literal (Int 5))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-03.out b/test/out/compiler/closure-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-03.out
@@ -0,0 +1,92 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-03.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let (BasicBind (Just (Identifier "mark"))) (Literal (String "!"))
+          , Let
+              (BasicBind (Just (Identifier "greet")))
+              (Block
+                 (CodeBlock
+                    [ Let (BasicBind (Just (Identifier "hi"))) (Literal (String "Hi"))
+                    , FuncExpr
+                        [ NormalParam (Identifier "name") ]
+                        (Block
+                           (CodeBlock
+                              [ Plus
+                                  (Plus
+                                     (Plus (Ident (Identifier "hi")) (Literal (String ", ")))
+                                     (Ident (Identifier "name")))
+                                  (Ident (Identifier "mark"))
+                              ]))
+                    ]))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "greet"))
+                     [ NormalArg (Literal (String "Typst")) ])
+              , NormalArg (Literal (String "Hi, Typst!"))
+              ]
+          , Assign
+              (Binding (BasicBind (Just (Identifier "mark"))))
+              (Literal (String "?"))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "greet"))
+                     [ NormalArg (Literal (String "Typst")) ])
+              , NormalArg (Literal (String "Hi, Typst!"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-04.out b/test/out/compiler/closure-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-04.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-04.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let (BasicBind (Just (Identifier "x"))) (Literal (Int 1))
+          , LetFunc
+              (Identifier "f")
+              []
+              (Block
+                 (CodeBlock
+                    [ Let
+                        (BasicBind (Just (Identifier "x")))
+                        (Plus (Ident (Identifier "x")) (Literal (Int 2)))
+                    , Ident (Identifier "x")
+                    ]))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (FuncCall (Ident (Identifier "f")) [])
+              , NormalArg (Literal (Int 3))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-05.out b/test/out/compiler/closure-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-05.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-05.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "b"))) (Literal (String "module.typ"))
+          , LetFunc
+              (Identifier "f")
+              []
+              (Block
+                 (CodeBlock
+                    [ Import
+                        (Ident (Identifier "b")) (SomeIdentifiers [ Identifier "b" ])
+                    , Ident (Identifier "b")
+                    ]))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (FuncCall (Ident (Identifier "f")) [])
+              , NormalArg (Literal (Int 1))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-06.out b/test/out/compiler/closure-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-06.out
@@ -0,0 +1,80 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-06.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "v")))
+              (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+          , LetFunc
+              (Identifier "f")
+              []
+              (Block
+                 (CodeBlock
+                    [ Let (BasicBind (Just (Identifier "s"))) (Literal (Int 0))
+                    , For
+                        (BasicBind (Just (Identifier "v")))
+                        (Ident (Identifier "v"))
+                        (Block
+                           (CodeBlock
+                              [ Assign
+                                  (Ident (Identifier "s"))
+                                  (Plus (Ident (Identifier "s")) (Ident (Identifier "v")))
+                              ]))
+                    , Ident (Identifier "s")
+                    ]))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (FuncCall (Ident (Identifier "f")) [])
+              , NormalArg (Literal (Int 6))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-07.out b/test/out/compiler/closure-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-07.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-07.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let (BasicBind (Just (Identifier "g"))) (Literal (String "hi"))
+          , LetFunc
+              (Identifier "f")
+              []
+              (Block
+                 (CodeBlock
+                    [ LetFunc (Identifier "g") [] (Literal (String "bye"))
+                    , FuncCall (Ident (Identifier "g")) []
+                    ]))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (FuncCall (Ident (Identifier "f")) [])
+              , NormalArg (Literal (String "bye"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-08.out b/test/out/compiler/closure-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-08.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/closure-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/closure-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/closure-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/closure-08.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let (BasicBind (Just (Identifier "x"))) (Literal (Int 5))
+          , LetFunc
+              (Identifier "g")
+              []
+              (Block
+                 (CodeBlock
+                    [ LetFunc
+                        (Identifier "f")
+                        [ NormalParam (Identifier "x")
+                        , DefaultParam (Identifier "y") (Ident (Identifier "x"))
+                        ]
+                        (Plus (Ident (Identifier "x")) (Ident (Identifier "y")))
+                    , Ident (Identifier "f")
+                    ]))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FuncCall (Ident (Identifier "g")) [])
+                     [ NormalArg (Literal (Int 8)) ])
+              , NormalArg (Literal (Int 13))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [16]), 
+  text(body: [ /= ]), 
+  text(body: [13]), 
+  text(body: [)]), 
+  parbreak() }
diff --git a/test/out/compiler/closure-09.out b/test/out/compiler/closure-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-10.out b/test/out/compiler/closure-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-11.out b/test/out/compiler/closure-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-12.out b/test/out/compiler/closure-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-13.out b/test/out/compiler/closure-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-13.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-14.out b/test/out/compiler/closure-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-14.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-15.out b/test/out/compiler/closure-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-15.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-16.out b/test/out/compiler/closure-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-16.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-17.out b/test/out/compiler/closure-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-17.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-18.out b/test/out/compiler/closure-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-18.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-19.out b/test/out/compiler/closure-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-19.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/closure-20.out b/test/out/compiler/closure-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/closure-20.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/color-00.out b/test/out/compiler/color-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/color-00.out
@@ -0,0 +1,213 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/color-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/color-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/color-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/color-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "c")))
+       (FuncCall
+          (Ident (Identifier "cmyk"))
+          [ NormalArg (Literal (Numeric 50.0 Percent))
+          , NormalArg (Literal (Numeric 64.0 Percent))
+          , NormalArg (Literal (Numeric 16.0 Percent))
+          , NormalArg (Literal (Numeric 17.0 Percent))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/color-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Cm))
+              , KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "cmyk"))
+                     [ NormalArg (Literal (Numeric 69.0 Percent))
+                     , NormalArg (Literal (Numeric 11.0 Percent))
+                     , NormalArg (Literal (Numeric 69.0 Percent))
+                     , NormalArg (Literal (Numeric 41.0 Percent))
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Cm))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "c"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Cm))
+              , KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "negate")) (Ident (Identifier "c")))
+                     [])
+              ])
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/color-00.typ"
+    ( line 12 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "x")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 11)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "box"))
+                 [ NormalArg
+                     (FuncCall
+                        (Ident (Identifier "square"))
+                        [ KeyValArg (Identifier "size") (Literal (Numeric 9.0 Pt))
+                        , KeyValArg
+                            (Identifier "fill")
+                            (FuncCall
+                               (FieldAccess
+                                  (Ident (Identifier "lighten")) (Ident (Identifier "c")))
+                               [ NormalArg
+                                   (Times (Ident (Identifier "x")) (Literal (Numeric 10.0 Percent)))
+                               ])
+                        ])
+                 ]
+             ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/color-00.typ"
+    ( line 15 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "x")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 11)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "box"))
+                 [ NormalArg
+                     (FuncCall
+                        (Ident (Identifier "square"))
+                        [ KeyValArg (Identifier "size") (Literal (Numeric 9.0 Pt))
+                        , KeyValArg
+                            (Identifier "fill")
+                            (FuncCall
+                               (FieldAccess
+                                  (Ident (Identifier "darken")) (Ident (Identifier "c")))
+                               [ NormalArg
+                                   (Times (Ident (Identifier "x")) (Literal (Numeric 10.0 Percent)))
+                               ])
+                        ])
+                 ]
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  stack(children: (rect(fill: cmyk(69%,11%,69%,41%), 
+                        width: 1.0cm), 
+                   rect(fill: cmyk(50%,64%,16%,17%), 
+                        width: 1.0cm), 
+                   rect(fill: cmyk(50%,36%,84%,17%), 
+                        width: 1.0cm)), 
+        dir: ltr, 
+        spacing: 1.0fr), 
+  parbreak(), 
+  box(body: square(fill: cmyk(50%,64%,16%,17%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(55%,67%,24%,25%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(60%,71%,32%,33%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(65%,74%,41%,41%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(70%,78%,49%,50%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(75%,82%,58%,58%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(80%,85%,66%,66%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(85%,89%,74%,75%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(90%,92%,83%,83%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(95%,96%,91%,91%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(100%,100%,100%,100%), 
+                   size: 9.0pt)), 
+  text(body: [
+]), 
+  box(body: square(fill: cmyk(50%,64%,16%,17%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(45%,57%,14%,15%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(40%,51%,12%,13%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(35%,44%,11%,11%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(30%,38%,9%,10%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(25%,32%,8%,8%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(20%,25%,6%,6%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(15%,19%,4%,5%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(10%,12%,3%,3%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(5%,6%,1%,1%), 
+                   size: 9.0pt)), 
+  box(body: square(fill: cmyk(0%,0%,0%,0%), 
+                   size: 9.0pt)), 
+  parbreak() }
diff --git a/test/out/compiler/color-01.out b/test/out/compiler/color-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/color-01.out
@@ -0,0 +1,116 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/color-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/color-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/color-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/color-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lighten"))
+                 (FuncCall
+                    (Ident (Identifier "luma"))
+                    [ NormalArg (Literal (Numeric 20.0 Percent)) ]))
+              [ NormalArg (Literal (Numeric 50.0 Percent)) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "luma"))
+              [ NormalArg (Literal (Numeric 60.0 Percent)) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/color-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "darken"))
+                 (FuncCall
+                    (Ident (Identifier "luma"))
+                    [ NormalArg (Literal (Numeric 80.0 Percent)) ]))
+              [ NormalArg (Literal (Numeric 20.0 Percent)) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "luma"))
+              [ NormalArg (Literal (Numeric 63.9 Percent)) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/color-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "negate"))
+                 (FuncCall
+                    (Ident (Identifier "luma"))
+                    [ NormalArg (Literal (Numeric 80.0 Percent)) ]))
+              [])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "luma"))
+              [ NormalArg (Literal (Numeric 20.0 Percent)) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [luma(64%)]), 
+  text(body: [ /= ]), 
+  text(body: [luma(63%)]), 
+  text(body: [)]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/comment-00.out b/test/out/compiler/comment-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/comment-00.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/comment-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/comment-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/comment-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Comment
+, Text "B"
+, ParBreak
+, Comment
+, Text "C"
+, Comment
+, Text "D"
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/comment-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (String "integer"))
+       ])
+, ParBreak
+, Comment
+, Comment
+, SoftBreak
+, Comment
+, Comment
+, ParBreak
+, Text "E"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [B]), 
+  parbreak(), 
+  text(body: [C]), 
+  text(body: [D]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [E]), 
+  parbreak() }
diff --git a/test/out/compiler/comment-01.out b/test/out/compiler/comment-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/comment-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/construct-00.out b/test/out/compiler/construct-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/construct-00.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/construct-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/construct-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/construct-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/construct-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "leading") (Literal (Numeric 2.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/construct-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "list"))
+       [ KeyValArg (Identifier "body-indent") (Literal (Numeric 20.0 Pt))
+       , NormalArg (Block (Content [ Text "First" ]))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "list"))
+              [ BlockArg [ Text "A" ] , BlockArg [ Text "B" ] ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  list(body-indent: 20.0pt, 
+       children: (text(body: [First]), 
+                  list(children: (text(body: [A]), 
+                                  text(body: [B]))))), 
+  parbreak() }
diff --git a/test/out/compiler/construct-01.out b/test/out/compiler/construct-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/construct-01.out
@@ -0,0 +1,90 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/construct-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/construct-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/construct-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/construct-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "list"))
+       [ KeyValArg (Identifier "marker") (Block (Content [ Text ">" ])) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/construct-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "list"))
+       [ KeyValArg (Identifier "marker") (Block (Content [ EnDash ]))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/compiler/construct-01.typ"
+               ( line 7 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "rect"))
+                  [ KeyValArg (Identifier "width") (Literal (Numeric 2.0 Cm))
+                  , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                  , KeyValArg (Identifier "inset") (Literal (Numeric 4.0 Pt))
+                  , NormalArg
+                      (FuncCall (Ident (Identifier "list")) [ BlockArg [ Text "A" ] ])
+                  ])
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  list(children: ({ text(body: [
+]), 
+                    rect(body: list(children: (text(body: [A])), 
+                                    marker: text(body: [>])), 
+                         fill: rgb(18%,80%,25%,100%), 
+                         inset: 4.0pt, 
+                         width: 2.0cm), 
+                    parbreak() }), 
+       marker: text(body: [–])), 
+  parbreak() }
diff --git a/test/out/compiler/construct-02.out b/test/out/compiler/construct-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/construct-02.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/construct-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/construct-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/construct-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/construct-02.typ"
+    ( line 4 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/compiler/construct-02.typ"
+              ( line 4 , column 4 )
+              (Set
+                 (Ident (Identifier "rect"))
+                 [ KeyValArg (Identifier "fill") (Ident (Identifier "yellow")) ])
+          , Code
+              "test/typ/compiler/construct-02.typ"
+              ( line 4 , column 28 )
+              (FuncCall
+                 (Ident (Identifier "text"))
+                 [ NormalArg (Literal (Numeric 1.0 Em))
+                 , NormalArg
+                     (FuncCall
+                        (Ident (Identifier "rect"))
+                        [ KeyValArg (Identifier "inset") (Literal (Numeric 5.0 Pt))
+                        , NormalArg (FuncCall (Ident (Identifier "rect")) [])
+                        ])
+                 ])
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: rect(body: rect(fill: rgb(100%,86%,0%,100%)), 
+                  fill: rgb(100%,86%,0%,100%), 
+                  inset: 5.0pt), 
+       size: 1.0em), 
+  parbreak() }
diff --git a/test/out/compiler/construct-03.out b/test/out/compiler/construct-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/construct-03.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/construct-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/construct-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/construct-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Space
+, Code
+    "test/typ/compiler/construct-03.typ"
+    ( line 3 , column 4 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "yellow"))
+              , KeyValArg (Identifier "inset") (Literal (Numeric 5.0 Pt))
+              , NormalArg (FuncCall (Ident (Identifier "rect")) [])
+              ])
+       ])
+, Space
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A ]), 
+  box(body: rect(body: rect(), 
+                 fill: rgb(100%,86%,0%,100%), 
+                 inset: 5.0pt)), 
+  text(body: [ B]), 
+  parbreak() }
diff --git a/test/out/compiler/construct-04.out b/test/out/compiler/construct-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/construct-04.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/construct-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/construct-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/construct-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/construct-04.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "enum")))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "blue")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/construct-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "enum"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "(a)"))
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg
+           (FuncCall (Ident (Identifier "enum")) [ BlockArg [ Text "B" ] ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  enum(children: (text(body: [A]), 
+                  enum(children: (text(body: [B])))), 
+       numbering: "(a)"), 
+  parbreak() }
diff --git a/test/out/compiler/content-field-00.out b/test/out/compiler/content-field-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/content-field-00.out
@@ -0,0 +1,331 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/content-field-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/content-field-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/content-field-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/content-field-00.typ"
+    ( line 4 , column 2 )
+    (LetFunc
+       (Identifier "compute")
+       [ NormalParam (Identifier "equation")
+       , SinkParam (Just (Identifier "vars"))
+       ]
+       (Block
+          (CodeBlock
+             [ Let
+                 (BasicBind (Just (Identifier "vars")))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "named")) (Ident (Identifier "vars")))
+                    [])
+             , LetFunc
+                 (Identifier "f")
+                 [ NormalParam (Identifier "elem") ]
+                 (Block
+                    (CodeBlock
+                       [ Let
+                           (BasicBind (Just (Identifier "func")))
+                           (FuncCall
+                              (FieldAccess
+                                 (Ident (Identifier "func")) (Ident (Identifier "elem")))
+                              [])
+                       , If
+                           [ ( Equals (Ident (Identifier "func")) (Ident (Identifier "text"))
+                             , Block
+                                 (CodeBlock
+                                    [ Let
+                                        (BasicBind (Just (Identifier "text")))
+                                        (FieldAccess
+                                           (Ident (Identifier "text")) (Ident (Identifier "elem")))
+                                    , If
+                                        [ ( InCollection
+                                              (FuncCall
+                                                 (Ident (Identifier "regex"))
+                                                 [ NormalArg (Literal (String "^\\d+$")) ])
+                                              (Ident (Identifier "text"))
+                                          , Block
+                                              (CodeBlock
+                                                 [ FuncCall
+                                                     (Ident (Identifier "int"))
+                                                     [ NormalArg (Ident (Identifier "text")) ]
+                                                 ])
+                                          )
+                                        , ( InCollection
+                                              (Ident (Identifier "text"))
+                                              (Ident (Identifier "vars"))
+                                          , Block
+                                              (CodeBlock
+                                                 [ FuncCall
+                                                     (Ident (Identifier "int"))
+                                                     [ NormalArg
+                                                         (FuncCall
+                                                            (FieldAccess
+                                                               (Ident (Identifier "at"))
+                                                               (Ident (Identifier "vars")))
+                                                            [ NormalArg (Ident (Identifier "text"))
+                                                            ])
+                                                     ]
+                                                 ])
+                                          )
+                                        , ( Literal (Boolean True)
+                                          , Block
+                                              (CodeBlock
+                                                 [ FuncCall
+                                                     (Ident (Identifier "panic"))
+                                                     [ NormalArg
+                                                         (Plus
+                                                            (Literal
+                                                               (String "unknown math variable: "))
+                                                            (Ident (Identifier "text")))
+                                                     ]
+                                                 ])
+                                          )
+                                        ]
+                                    ])
+                             )
+                           , ( Equals
+                                 (Ident (Identifier "func"))
+                                 (FieldAccess
+                                    (Ident (Identifier "attach")) (Ident (Identifier "math")))
+                             , Block
+                                 (CodeBlock
+                                    [ Let
+                                        (BasicBind (Just (Identifier "value")))
+                                        (FuncCall
+                                           (Ident (Identifier "f"))
+                                           [ NormalArg
+                                               (FieldAccess
+                                                  (Ident (Identifier "base"))
+                                                  (Ident (Identifier "elem")))
+                                           ])
+                                    , If
+                                        [ ( FuncCall
+                                              (FieldAccess
+                                                 (Ident (Identifier "has"))
+                                                 (Ident (Identifier "elem")))
+                                              [ NormalArg (Literal (String "t")) ]
+                                          , Block
+                                              (CodeBlock
+                                                 [ Assign
+                                                     (Binding
+                                                        (BasicBind (Just (Identifier "value"))))
+                                                     (FuncCall
+                                                        (FieldAccess
+                                                           (Ident (Identifier "pow"))
+                                                           (Ident (Identifier "calc")))
+                                                        [ NormalArg (Ident (Identifier "value"))
+                                                        , NormalArg
+                                                            (FuncCall
+                                                               (Ident (Identifier "f"))
+                                                               [ NormalArg
+                                                                   (FieldAccess
+                                                                      (Ident (Identifier "t"))
+                                                                      (Ident (Identifier "elem")))
+                                                               ])
+                                                        ])
+                                                 ])
+                                          )
+                                        ]
+                                    , Ident (Identifier "value")
+                                    ])
+                             )
+                           , ( FuncCall
+                                 (FieldAccess
+                                    (Ident (Identifier "has")) (Ident (Identifier "elem")))
+                                 [ NormalArg (Literal (String "children")) ]
+                             , Block
+                                 (CodeBlock
+                                    [ FuncCall
+                                        (FieldAccess
+                                           (Ident (Identifier "fold"))
+                                           (FuncCall
+                                              (FieldAccess
+                                                 (Ident (Identifier "map"))
+                                                 (FuncCall
+                                                    (FieldAccess
+                                                       (Ident (Identifier "split"))
+                                                       (FuncCall
+                                                          (FieldAccess
+                                                             (Ident (Identifier "filter"))
+                                                             (FieldAccess
+                                                                (Ident (Identifier "children"))
+                                                                (Ident (Identifier "elem"))))
+                                                          [ NormalArg
+                                                              (FuncExpr
+                                                                 [ NormalParam (Identifier "v") ]
+                                                                 (Not
+                                                                    (Equals
+                                                                       (Ident (Identifier "v"))
+                                                                       (Block
+                                                                          (Content [ Space ])))))
+                                                          ]))
+                                                    [ BlockArg [ EnumListItem Nothing [] ] ]))
+                                              [ NormalArg
+                                                  (FuncExpr
+                                                     [ NormalParam (Identifier "xs") ]
+                                                     (FuncCall
+                                                        (FieldAccess
+                                                           (Ident (Identifier "fold"))
+                                                           (Ident (Identifier "xs")))
+                                                        [ NormalArg (Literal (Int 1))
+                                                        , NormalArg
+                                                            (FuncExpr
+                                                               [ NormalParam (Identifier "prod")
+                                                               , NormalParam (Identifier "v")
+                                                               ]
+                                                               (Times
+                                                                  (Ident (Identifier "prod"))
+                                                                  (FuncCall
+                                                                     (Ident (Identifier "f"))
+                                                                     [ NormalArg
+                                                                         (Ident (Identifier "v"))
+                                                                     ])))
+                                                        ]))
+                                              ]))
+                                        [ NormalArg (Literal (Int 0))
+                                        , NormalArg
+                                            (FuncExpr
+                                               [ NormalParam (Identifier "sum")
+                                               , NormalParam (Identifier "v")
+                                               ]
+                                               (Plus
+                                                  (Ident (Identifier "sum"))
+                                                  (Ident (Identifier "v"))))
+                                        ]
+                                    ])
+                             )
+                           ]
+                       ]))
+             , Let
+                 (BasicBind (Just (Identifier "result")))
+                 (FuncCall
+                    (Ident (Identifier "f"))
+                    [ NormalArg
+                        (FieldAccess
+                           (Ident (Identifier "body")) (Ident (Identifier "equation")))
+                    ])
+             , Block (Content [ Text "With" , Space ])
+             , FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "join"))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "map"))
+                          (FuncCall
+                             (FieldAccess
+                                (Ident (Identifier "pairs")) (Ident (Identifier "vars")))
+                             []))
+                       [ NormalArg
+                           (FuncExpr
+                              [ NormalParam (Identifier "p") ]
+                              (Block
+                                 (Content
+                                    [ Equation
+                                        False
+                                        [ Code
+                                            "test/typ/compiler/content-field-00.typ"
+                                            ( line 36 , column 17 )
+                                            (FuncCall
+                                               (FieldAccess
+                                                  (Ident (Identifier "first"))
+                                                  (Ident (Identifier "p")))
+                                               [])
+                                        , Text "="
+                                        , Code
+                                            "test/typ/compiler/content-field-00.typ"
+                                            ( line 36 , column 30 )
+                                            (FuncCall
+                                               (FieldAccess
+                                                  (Ident (Identifier "last"))
+                                                  (Ident (Identifier "p")))
+                                               [])
+                                        ]
+                                    ])))
+                       ]))
+                 [ NormalArg (Literal (String ", "))
+                 , KeyValArg (Identifier "last") (Literal (String " and "))
+                 ]
+             , Block
+                 (Content [ Space , Text "we" , Space , Text "have" , Text ":" ])
+             , Block
+                 (Content
+                    [ Equation
+                        True
+                        [ Code
+                            "test/typ/compiler/content-field-00.typ"
+                            ( line 39 , column 5 )
+                            (Ident (Identifier "equation"))
+                        , Text "="
+                        , Code
+                            "test/typ/compiler/content-field-00.typ"
+                            ( line 39 , column 16 )
+                            (Ident (Identifier "result"))
+                        ]
+                    ])
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/content-field-00.typ"
+    ( line 42 , column 2 )
+    (FuncCall
+       (Ident (Identifier "compute"))
+       [ NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     False
+                     [ Text "x"
+                     , Text "y"
+                     , Text "+"
+                     , MAttach Nothing (Just (Text "2")) (Text "y")
+                     ]
+                 ]))
+       , KeyValArg (Identifier "x") (Literal (Int 2))
+       , KeyValArg (Identifier "y") (Literal (Int 3))
+       ])
+, ParBreak
+]
+"test/typ/compiler/content-field-00.typ" (line 42, column 2):
+unexpected end of input
+expecting end of input
+named argument default not defined or VString "unknown math variable: +"
+
diff --git a/test/out/compiler/dict-00.out b/test/out/compiler/dict-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-00.out
@@ -0,0 +1,103 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/dict-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/dict-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/dict-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/dict-00.typ" ( line 5 , column 2 ) (Dict [])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/dict-00.typ"
+    ( line 8 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "dict")))
+       (Dict
+          [ ( Identifier "normal" , Literal (Int 1) )
+          , ( Identifier "spacy key" , Literal (Int 2) )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-00.typ"
+    ( line 9 , column 2 )
+    (Ident (Identifier "dict"))
+, ParBreak
+, Code
+    "test/typ/compiler/dict-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "normal")) (Ident (Identifier "dict")))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "dict")))
+              [ NormalArg (Literal (String "spacy key")) ])
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [()]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [(normal: 1, spacy key: 2)]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/dict-01.out b/test/out/compiler/dict-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-01.out
@@ -0,0 +1,129 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/dict-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/dict-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/dict-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/dict-01.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "dict")))
+              (Dict
+                 [ ( Identifier "a" , Literal (Int 1) )
+                 , ( Identifier "b b" , Literal (Int 1) )
+                 ])
+          , Assign
+              (FuncCall
+                 (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "dict")))
+                 [ NormalArg (Literal (String "b b")) ])
+              (Plus
+                 (FuncCall
+                    (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "dict")))
+                    [ NormalArg (Literal (String "b b")) ])
+                 (Literal (Int 1)))
+          , Assign
+              (FieldAccess
+                 (Ident (Identifier "state")) (Ident (Identifier "dict")))
+              (Dict
+                 [ ( Identifier "ok" , Literal (Boolean True) )
+                 , ( Identifier "err" , Literal (Boolean False) )
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "dict"))
+              , NormalArg
+                  (Dict
+                     [ ( Identifier "a" , Literal (Int 1) )
+                     , ( Identifier "b b" , Literal (Int 2) )
+                     , ( Identifier "state"
+                       , Dict
+                           [ ( Identifier "ok" , Literal (Boolean True) )
+                           , ( Identifier "err" , Literal (Boolean False) )
+                           ]
+                       )
+                     ])
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FieldAccess
+                     (Ident (Identifier "ok"))
+                     (FieldAccess
+                        (Ident (Identifier "state")) (Ident (Identifier "dict"))))
+              , NormalArg (Literal (Boolean True))
+              ]
+          , Assign
+              (FieldAccess
+                 (Ident (Identifier "ok"))
+                 (FuncCall
+                    (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "dict")))
+                    [ NormalArg (Literal (String "state")) ]))
+              (Literal (Boolean False))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FieldAccess
+                     (Ident (Identifier "ok"))
+                     (FieldAccess
+                        (Ident (Identifier "state")) (Ident (Identifier "dict"))))
+              , NormalArg (Literal (Boolean False))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FieldAccess
+                     (Ident (Identifier "err"))
+                     (FieldAccess
+                        (Ident (Identifier "state")) (Ident (Identifier "dict"))))
+              , NormalArg (Literal (Boolean False))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/dict-02.out b/test/out/compiler/dict-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/dict-03.out b/test/out/compiler/dict-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-03.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/dict-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/dict-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/dict-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/dict-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "at"))
+                 (Dict
+                    [ ( Identifier "a" , Literal (Int 1) )
+                    , ( Identifier "b" , Literal (Int 2) )
+                    ]))
+              [ NormalArg (Literal (String "b"))
+              , KeyValArg (Identifier "default") (Literal (Int 3))
+              ])
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "at"))
+                 (Dict
+                    [ ( Identifier "a" , Literal (Int 1) )
+                    , ( Identifier "b" , Literal (Int 2) )
+                    ]))
+              [ NormalArg (Literal (String "c"))
+              , KeyValArg (Identifier "default") (Literal (Int 3))
+              ])
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/dict-04.out b/test/out/compiler/dict-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/dict-05.out b/test/out/compiler/dict-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-05.out
@@ -0,0 +1,182 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/dict-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/dict-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "dict")))
+       (Dict
+          [ ( Identifier "a" , Literal (Int 3) )
+          , ( Identifier "c" , Literal (Int 2) )
+          , ( Identifier "b" , Literal (Int 1) )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection (Literal (String "c")) (Ident (Identifier "dict")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "len")) (Ident (Identifier "dict")))
+              [])
+       , NormalArg (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "values")) (Ident (Identifier "dict")))
+              [])
+       , NormalArg
+           (Array [ Literal (Int 3) , Literal (Int 2) , Literal (Int 1) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "join"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "map"))
+                       (FuncCall
+                          (FieldAccess
+                             (Ident (Identifier "pairs")) (Ident (Identifier "dict")))
+                          []))
+                    [ NormalArg
+                        (FuncExpr
+                           [ NormalParam (Identifier "p") ]
+                           (Plus
+                              (FuncCall
+                                 (FieldAccess (Ident (Identifier "first")) (Ident (Identifier "p")))
+                                 [])
+                              (FuncCall
+                                 (Ident (Identifier "str"))
+                                 [ NormalArg
+                                     (FuncCall
+                                        (FieldAccess
+                                           (Ident (Identifier "last")) (Ident (Identifier "p")))
+                                        [])
+                                 ])))
+                    ]))
+              [])
+       , NormalArg (Literal (String "a3c2b1"))
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "remove")) (Ident (Identifier "dict")))
+       [ NormalArg (Literal (String "c")) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection (Literal (String "c")) (Ident (Identifier "dict")))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/dict-05.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "dict"))
+       , NormalArg
+           (Dict
+              [ ( Identifier "a" , Literal (Int 3) )
+              , ( Identifier "b" , Literal (Int 1) )
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [2]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/dict-06.out b/test/out/compiler/dict-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/dict-07.out b/test/out/compiler/dict-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/dict-08.out b/test/out/compiler/dict-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/dict-09.out b/test/out/compiler/dict-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/dict-10.out b/test/out/compiler/dict-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/dict-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-00.out b/test/out/compiler/field-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-00.out
@@ -0,0 +1,90 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/field-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/field-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/field-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/field-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "dict")))
+       (Dict
+          [ ( Identifier "nothing" , Literal (String "ness") )
+          , ( Identifier "hello" , Literal (String "world") )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/field-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "nothing")) (Ident (Identifier "dict")))
+       , NormalArg (Literal (String "ness"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/field-00.typ"
+    ( line 5 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "world")))
+              (FieldAccess
+                 (Ident (Identifier "hello")) (Ident (Identifier "dict")))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "world"))
+              , NormalArg (Literal (String "world"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/field-01.out b/test/out/compiler/field-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-01.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/field-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/field-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/field-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/field-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ FuncCall
+                    (Ident (Identifier "test"))
+                    [ NormalArg
+                        (FuncCall
+                           (FieldAccess
+                              (Ident (Identifier "len"))
+                              (FieldAccess
+                                 (Ident (Identifier "children")) (Ident (Identifier "it"))))
+                           [])
+                    , NormalArg (Literal (Int 3))
+                    ]
+                ]))))
+, ParBreak
+, BulletListItem [ Text "A" ]
+, SoftBreak
+, BulletListItem [ Text "B" ]
+, SoftBreak
+, BulletListItem [ Text "C" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]) }
diff --git a/test/out/compiler/field-02.out b/test/out/compiler/field-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-02.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/field-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/field-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/field-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/field-02.typ"
+    ( line 3 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "item")) (Ident (Identifier "enum")))
+, SoftBreak
+, Code
+    "test/typ/compiler/field-02.typ"
+    ( line 4 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "eq")) (Ident (Identifier "assert")))
+, SoftBreak
+, Code
+    "test/typ/compiler/field-02.typ"
+    ( line 5 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "ne")) (Ident (Identifier "assert")))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/compiler/field-03.out b/test/out/compiler/field-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-04.out b/test/out/compiler/field-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-05.out b/test/out/compiler/field-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-06.out b/test/out/compiler/field-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-07.out b/test/out/compiler/field-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-08.out b/test/out/compiler/field-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-09.out b/test/out/compiler/field-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/field-10.out b/test/out/compiler/field-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/field-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/for-00.out b/test/out/compiler/for-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/for-00.out
@@ -0,0 +1,302 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/for-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/for-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/for-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 5 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "x")))
+       (Array [])
+       (Block (Content [ Text "Nope" ])))
+, ParBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 9 , column 2 )
+    (For
+       (DestructuringBind
+          [ Simple (Just (Identifier "k"))
+          , Simple (Just (Identifier "v"))
+          ])
+       (Dict
+          [ ( Identifier "Name" , Literal (String "Typst") )
+          , ( Identifier "Age" , Literal (Int 2) )
+          ])
+       (Block
+          (Content
+             [ SoftBreak
+             , Code
+                 "test/typ/compiler/for-00.typ"
+                 ( line 10 , column 4 )
+                 (Ident (Identifier "k"))
+             , Text ":"
+             , Space
+             , Code
+                 "test/typ/compiler/for-00.typ"
+                 ( line 10 , column 8 )
+                 (Ident (Identifier "v"))
+             , Text "."
+             , ParBreak
+             ])))
+, ParBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 15 , column 2 )
+    (Block
+       (CodeBlock
+          [ Literal (String "[")
+          , For
+              (BasicBind (Just (Identifier "v")))
+              (Array
+                 [ Literal (Int 1)
+                 , Literal (Int 2)
+                 , Literal (Int 3)
+                 , Literal (Int 4)
+                 ])
+              (Block
+                 (CodeBlock
+                    [ If
+                        [ ( GreaterThan (Ident (Identifier "v")) (Literal (Int 1))
+                          , Block (Content [ Text "," , Space ])
+                          )
+                        ]
+                    , Block
+                        (Content
+                           [ Code
+                               "test/typ/compiler/for-00.typ"
+                               ( line 19 , column 7 )
+                               (Ident (Identifier "v"))
+                           ])
+                    , If
+                        [ ( Equals (Ident (Identifier "v")) (Literal (Int 1))
+                          , Block (Content [ Text "st" ])
+                          )
+                        ]
+                    , If
+                        [ ( Equals (Ident (Identifier "v")) (Literal (Int 2))
+                          , Block (Content [ Text "nd" ])
+                          )
+                        ]
+                    , If
+                        [ ( Equals (Ident (Identifier "v")) (Literal (Int 3))
+                          , Block (Content [ Text "rd" ])
+                          )
+                        ]
+                    , If
+                        [ ( GreaterThanOrEqual (Ident (Identifier "v")) (Literal (Int 4))
+                          , Block (Content [ Text "th" ])
+                          )
+                        ]
+                    ]))
+          , Literal (String "]")
+          ]))
+, ParBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 30 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "v")))
+       (Array
+          [ Literal (Int 1)
+          , Literal (Int 2)
+          , Literal (Int 3)
+          , Literal (Int 4)
+          , Literal (Int 5)
+          , Literal (Int 6)
+          , Literal (Int 7)
+          ])
+       (Block
+          (Content
+             [ Code
+                 "test/typ/compiler/for-00.typ"
+                 ( line 30 , column 35 )
+                 (If
+                    [ ( And
+                          (GreaterThanOrEqual (Ident (Identifier "v")) (Literal (Int 2)))
+                          (LessThanOrEqual (Ident (Identifier "v")) (Literal (Int 5)))
+                      , Block
+                          (CodeBlock
+                             [ FuncCall
+                                 (Ident (Identifier "repr")) [ NormalArg (Ident (Identifier "v")) ]
+                             ])
+                      )
+                    ])
+             ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 33 , column 2 )
+    (LetFunc
+       (Identifier "f1")
+       [ SinkParam (Just (Identifier "args")) ]
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "map"))
+             (FuncCall
+                (FieldAccess
+                   (Ident (Identifier "pos")) (Ident (Identifier "args")))
+                []))
+          [ NormalArg (Ident (Identifier "repr")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 34 , column 2 )
+    (LetFunc
+       (Identifier "f2")
+       [ SinkParam (Just (Identifier "args")) ]
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "map"))
+             (FuncCall
+                (FieldAccess
+                   (Ident (Identifier "pairs"))
+                   (FuncCall
+                      (FieldAccess
+                         (Ident (Identifier "named")) (Ident (Identifier "args")))
+                      []))
+                []))
+          [ NormalArg
+              (FuncExpr
+                 [ NormalParam (Identifier "p") ]
+                 (Plus
+                    (Plus
+                       (FuncCall
+                          (Ident (Identifier "repr"))
+                          [ NormalArg
+                              (FuncCall
+                                 (FieldAccess (Ident (Identifier "first")) (Ident (Identifier "p")))
+                                 [])
+                          ])
+                       (Literal (String ": ")))
+                    (FuncCall
+                       (Ident (Identifier "repr"))
+                       [ NormalArg
+                           (FuncCall
+                              (FieldAccess (Ident (Identifier "last")) (Ident (Identifier "p")))
+                              [])
+                       ])))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 35 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ SinkParam (Just (Identifier "args")) ]
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "join"))
+             (Plus
+                (FuncCall
+                   (Ident (Identifier "f1"))
+                   [ SpreadArg (Ident (Identifier "args")) ])
+                (FuncCall
+                   (Ident (Identifier "f2"))
+                   [ SpreadArg (Ident (Identifier "args")) ])))
+          [ NormalArg (Literal (String ", ")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/for-00.typ"
+    ( line 36 , column 2 )
+    (FuncCall
+       (Ident (Identifier "f"))
+       [ NormalArg (Literal (Int 1))
+       , KeyValArg (Identifier "a") (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [Name]), 
+  text(body: [: ]), 
+  text(body: [Typst]), 
+  text(body: [.]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [Age]), 
+  text(body: [: ]), 
+  text(body: [2]), 
+  text(body: [.]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [[]), 
+  text(body: [1]), 
+  text(body: [st]), 
+  text(body: [, ]), 
+  text(body: [2]), 
+  text(body: [nd]), 
+  text(body: [, ]), 
+  text(body: [3]), 
+  text(body: [rd]), 
+  text(body: [, ]), 
+  text(body: [4]), 
+  text(body: [th]), 
+  text(body: []]), 
+  parbreak(), 
+  text(body: [2]), 
+  text(body: [3]), 
+  text(body: [4]), 
+  text(body: [5]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [1, "a": 2]), 
+  parbreak() }
diff --git a/test/out/compiler/for-01.out b/test/out/compiler/for-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/for-01.out
@@ -0,0 +1,252 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/for-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/for-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/for-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 2 , column 2 )
+    (Let (BasicBind (Just (Identifier "out"))) (Array []))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 5 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "v")))
+       (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+       (Block
+          (CodeBlock
+             [ Assign
+                 (Ident (Identifier "out"))
+                 (Plus
+                    (Ident (Identifier "out")) (Array [ Ident (Identifier "v") ]))
+             ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 10 , column 2 )
+    (For
+       (DestructuringBind
+          [ Simple (Just (Identifier "i"))
+          , Simple (Just (Identifier "v"))
+          ])
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "enumerate"))
+             (Array
+                [ Literal (String "1")
+                , Literal (String "2")
+                , Literal (String "3")
+                ]))
+          [])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg
+                     (FuncCall
+                        (Ident (Identifier "repr"))
+                        [ NormalArg (Plus (Ident (Identifier "i")) (Literal (Int 1))) ])
+                 , NormalArg (Ident (Identifier "v"))
+                 ]
+             ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 15 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "v")))
+       (Dict
+          [ ( Identifier "a" , Literal (Int 4) )
+          , ( Identifier "b" , Literal (Int 5) )
+          ])
+       (Block
+          (CodeBlock
+             [ Assign
+                 (Ident (Identifier "out"))
+                 (Plus
+                    (Ident (Identifier "out")) (Array [ Ident (Identifier "v") ]))
+             ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 20 , column 2 )
+    (For
+       (DestructuringBind
+          [ Simple (Just (Identifier "k"))
+          , Simple (Just (Identifier "v"))
+          ])
+       (Dict
+          [ ( Identifier "a" , Literal (Int 6) )
+          , ( Identifier "b" , Literal (Int 7) )
+          ])
+       (Block
+          (CodeBlock
+             [ Assign
+                 (Ident (Identifier "out"))
+                 (Plus
+                    (Ident (Identifier "out")) (Array [ Ident (Identifier "k") ]))
+             , Assign
+                 (Ident (Identifier "out"))
+                 (Plus
+                    (Ident (Identifier "out")) (Array [ Ident (Identifier "v") ]))
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 25 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "out"))
+       , NormalArg
+           (Array
+              [ Literal (Int 1)
+              , Literal (Int 2)
+              , Literal (Int 3)
+              , Array [ Literal (String "a") , Literal (Int 4) ]
+              , Array [ Literal (String "b") , Literal (Int 5) ]
+              , Literal (String "a")
+              , Literal (Int 6)
+              , Literal (String "b")
+              , Literal (Int 7)
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 28 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "first"))) (Literal (Boolean True)))
+, SoftBreak
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 29 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "joined")))
+       (For
+          (BasicBind (Just (Identifier "c")))
+          (Literal (String "abc\128105\8205\128105\8205\128102\8205\128102"))
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Not (Ident (Identifier "first"))
+                      , Block (CodeBlock [ Literal (String ", ") ])
+                      )
+                    ]
+                , Assign
+                    (Binding (BasicBind (Just (Identifier "first"))))
+                    (Literal (Boolean False))
+                , Ident (Identifier "c")
+                ]))))
+, ParBreak
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 35 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "joined"))
+       , NormalArg
+           (Literal
+              (String "a, b, c, \128105\8205\128105\8205\128102\8205\128102"))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 38 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (For
+              (BasicBind (Just (Identifier "v")))
+              (Literal (String ""))
+              (Block (Content [])))
+       , NormalArg (Literal None)
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/for-01.typ"
+    ( line 39 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg
+                  (For
+                     (BasicBind (Just (Identifier "v")))
+                     (Literal (String "1"))
+                     (Block (Content [])))
+              ])
+       , NormalArg (Literal (String "content"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak(), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [❌(]), 
+  text(body: ["a, b, c, 👩, ‍, 👩, ‍, 👦, ‍, 👦"]), 
+  text(body: [ /= ]), 
+  text(body: ["a, b, c, 👩‍👩‍👦‍👦"]), 
+  text(body: [)]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/for-02.out b/test/out/compiler/for-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/for-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/for-03.out b/test/out/compiler/for-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/for-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/for-04.out b/test/out/compiler/for-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/for-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/highlight-00.out b/test/out/compiler/highlight-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/highlight-00.out
@@ -0,0 +1,61 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/highlight-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/highlight-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/highlight-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/highlight-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, ParBreak
+, RawBlock
+    "typ"
+    "#set hello()\n#set hello()\n#set hello.world()\n#set hello.my.world()\n#let foo(x) = x * 2\n#show heading: func\n#show module.func: func\n#show module.func: it => {}\n#foo(ident: ident)\n#hello\n#hello()\n#box[]\n#hello.world\n#hello.world()\n#hello().world()\n#hello.my.world\n#hello.my.world()\n#hello.my().world\n#hello.my().world()\n#{ hello }\n#{ hello() }\n#{ hello.world() }\n$ hello $\n$ hello() $\n$ box[] $\n$ hello.world $\n$ hello.world() $\n$ hello.my.world() $\n$ f_zeta(x), f_zeta(x)/1 $\n$ emph(hello.my.world()) $\n$ emph(hello.my().world) $\n$ emph(hello.my().world()) $\n$ #hello $\n$ #hello() $\n$ #hello.world $\n$ #hello.world() $\n$ #box[] $\n#if foo []\n"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  raw(block: true, 
+      lang: "typ", 
+      text: "#set hello()\n#set hello()\n#set hello.world()\n#set hello.my.world()\n#let foo(x) = x * 2\n#show heading: func\n#show module.func: func\n#show module.func: it => {}\n#foo(ident: ident)\n#hello\n#hello()\n#box[]\n#hello.world\n#hello.world()\n#hello().world()\n#hello.my.world\n#hello.my.world()\n#hello.my().world\n#hello.my().world()\n#{ hello }\n#{ hello() }\n#{ hello.world() }\n$ hello $\n$ hello() $\n$ box[] $\n$ hello.world $\n$ hello.world() $\n$ hello.my.world() $\n$ f_zeta(x), f_zeta(x)/1 $\n$ emph(hello.my.world()) $\n$ emph(hello.my().world) $\n$ emph(hello.my().world()) $\n$ #hello $\n$ #hello() $\n$ #hello.world $\n$ #hello.world() $\n$ #box[] $\n#if foo []\n"), 
+  parbreak() }
diff --git a/test/out/compiler/hint-00.out b/test/out/compiler/hint-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/hint-00.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/hint-01.out b/test/out/compiler/hint-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/hint-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/hint-02.out b/test/out/compiler/hint-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/hint-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/if-00.out b/test/out/compiler/if-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/if-00.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/if-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/if-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/if-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/if-00.typ"
+    ( line 3 , column 2 )
+    (If
+       [ ( LessThan (Literal (Int 1)) (Literal (Int 2))
+         , Block (Content [ SoftBreak , Text "One" , Text "." , ParBreak ])
+         )
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/if-00.typ"
+    ( line 7 , column 2 )
+    (If
+       [ ( Equals (Literal (Boolean True)) (Literal (Boolean False))
+         , Block
+             (Content
+                [ SoftBreak
+                , Text "{Bad},"
+                , Space
+                , Text "but"
+                , Space
+                , Text "we"
+                , Space
+                , Text "{dont"
+                , Text "-"
+                , Text "care}!"
+                , ParBreak
+                ])
+         )
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+One.]), 
+  parbreak(), 
+  parbreak(), 
+  parbreak() }
diff --git a/test/out/compiler/if-01.out b/test/out/compiler/if-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/if-01.out
@@ -0,0 +1,163 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/if-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/if-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/if-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/if-01.typ"
+    ( line 3 , column 2 )
+    (If
+       [ ( Block (CodeBlock [ Literal (Boolean True) ])
+         , Block (Content [ SoftBreak , Text "One" , Text "." , ParBreak ])
+         )
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/if-01.typ"
+    ( line 8 , column 2 )
+    (If
+       [ ( Not (Equals (Block (Content [])) (Literal None))
+         , Block (Content [ SoftBreak , Text "Two" , Text "." , ParBreak ])
+         )
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/if-01.typ"
+    ( line 13 , column 2 )
+    (If
+       [ ( Equals
+             (Plus (Literal (Int 1)) (Literal (Int 1))) (Literal (Int 1))
+         , Block (Content [ SoftBreak , Text "Nope" , Text "." , ParBreak ])
+         )
+       , ( Literal (Boolean True)
+         , Block (CodeBlock [ Literal (String "Three.") ])
+         )
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/if-01.typ"
+    ( line 23 , column 2 )
+    (If
+       [ ( Literal (Boolean False)
+         , Block (Content [ SoftBreak , Text "Bad" , Text "." , ParBreak ])
+         )
+       , ( Literal (Boolean True)
+         , Block
+             (CodeBlock
+                [ Let
+                    (BasicBind (Just (Identifier "point"))) (Literal (String "."))
+                , Plus (Literal (String "Four")) (Ident (Identifier "point"))
+                ])
+         )
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/if-01.typ"
+    ( line 31 , column 2 )
+    (Block
+       (CodeBlock
+          [ If
+              [ ( Equals
+                    (Literal (String "content"))
+                    (FuncCall (Ident (Identifier "type")) [ BlockArg [ Text "b" ] ])
+                , Block (Content [ Text "Fi" ])
+                )
+              , ( Literal (Boolean True) , Block (Content [ Text "Nope" ]) )
+              ]
+          , If
+              [ ( Equals (Literal (String "content")) (Ident (Identifier "type"))
+                , Block (Content [ Text "Nope" ])
+                )
+              , ( Literal (Boolean True)
+                , Block (Content [ Text "ve" , Text "." ])
+                )
+              ]
+          ]))
+, ParBreak
+, Code
+    "test/typ/compiler/if-01.typ"
+    ( line 36 , column 2 )
+    (Let (BasicBind (Just (Identifier "i"))) (Literal (Int 3)))
+, SoftBreak
+, Code
+    "test/typ/compiler/if-01.typ"
+    ( line 37 , column 2 )
+    (If
+       [ ( LessThan (Ident (Identifier "i")) (Literal (Int 2))
+         , Block (Content [ SoftBreak , Text "Five" , Text "." , ParBreak ])
+         )
+       , ( LessThan (Ident (Identifier "i")) (Literal (Int 4))
+         , Block (Content [ SoftBreak , Text "Six" , Text "." , ParBreak ])
+         )
+       , ( Literal (Boolean True)
+         , Block
+             (Content [ SoftBreak , Text "Seven" , Text "." , ParBreak ])
+         )
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+One.]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [
+Two.]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [Three.]), 
+  parbreak(), 
+  text(body: [Four.]), 
+  parbreak(), 
+  text(body: [Fi]), 
+  text(body: [ve.]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+Six.]), 
+  parbreak(), 
+  parbreak() }
diff --git a/test/out/compiler/if-02.out b/test/out/compiler/if-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/if-02.out
@@ -0,0 +1,146 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/if-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/if-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/if-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/if-02.typ"
+    ( line 5 , column 2 )
+    (LetFunc
+       (Identifier "nth")
+       [ NormalParam (Identifier "n") ]
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "str")) [ NormalArg (Ident (Identifier "n")) ]
+             , If
+                 [ ( Equals (Ident (Identifier "n")) (Literal (Int 1))
+                   , Block (CodeBlock [ Literal (String "st") ])
+                   )
+                 , ( Equals (Ident (Identifier "n")) (Literal (Int 2))
+                   , Block (CodeBlock [ Literal (String "nd") ])
+                   )
+                 , ( Equals (Ident (Identifier "n")) (Literal (Int 3))
+                   , Block (CodeBlock [ Literal (String "rd") ])
+                   )
+                 , ( Literal (Boolean True)
+                   , Block (CodeBlock [ Literal (String "th") ])
+                   )
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/if-02.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "nth")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (String "1st"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/if-02.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "nth")) [ NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (String "2nd"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/if-02.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "nth")) [ NormalArg (Literal (Int 3)) ])
+       , NormalArg (Literal (String "3rd"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/if-02.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "nth")) [ NormalArg (Literal (Int 4)) ])
+       , NormalArg (Literal (String "4th"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/if-02.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "nth")) [ NormalArg (Literal (Int 5)) ])
+       , NormalArg (Literal (String "5th"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/if-03.out b/test/out/compiler/if-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/if-03.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/if-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/if-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/if-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/if-03.typ"
+    ( line 5 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let (BasicBind (Just (Identifier "x"))) (Literal (Int 1))
+          , Let (BasicBind (Just (Identifier "y"))) (Literal (Int 2))
+          , Let (BasicBind (Just (Identifier "z"))) (Literal None)
+          , Assign
+              (Binding (BasicBind (Just (Identifier "z"))))
+              (If
+                 [ ( LessThan (Ident (Identifier "x")) (Ident (Identifier "y"))
+                   , Block (CodeBlock [ Literal (String "ok") ])
+                   )
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "z"))
+              , NormalArg (Literal (String "ok"))
+              ]
+          , Assign
+              (Binding (BasicBind (Just (Identifier "z"))))
+              (If
+                 [ ( GreaterThan (Ident (Identifier "x")) (Ident (Identifier "y"))
+                   , Block (CodeBlock [ Literal (String "bad") ])
+                   )
+                 , ( Literal (Boolean True)
+                   , Block (CodeBlock [ Literal (String "ok") ])
+                   )
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "z"))
+              , NormalArg (Literal (String "ok"))
+              ]
+          , Assign
+              (Binding (BasicBind (Just (Identifier "z"))))
+              (If
+                 [ ( GreaterThan (Ident (Identifier "x")) (Ident (Identifier "y"))
+                   , Block (CodeBlock [ Literal (String "bad") ])
+                   )
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "z")) , NormalArg (Literal None) ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/if-04.out b/test/out/compiler/if-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/if-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/if-05.out b/test/out/compiler/if-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/if-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/if-06.out b/test/out/compiler/if-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/if-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-00.out b/test/out/compiler/import-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-00.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/import-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/import-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/import-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/import-00.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "value")))
+       (Block (Content [ Text "foo" ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/import-00.typ"
+    ( line 9 , column 2 )
+    (Import
+       (Literal (String "module.typ"))
+       (SomeIdentifiers [ Identifier "fn" , Identifier "value" ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/import-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "fn"))
+       [ BlockArg
+           [ Text "Like" , Space , Text "and" , Space , Text "Subscribe!" ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/import-00.typ"
+    ( line 11 , column 2 )
+    (Ident (Identifier "value"))
+, ParBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/import-00.typ"
+    ( line 15 , column 2 )
+    (Import
+       (Literal (String "module.typ"))
+       (SomeIdentifiers [ Identifier "a" , Identifier "c" ]))
+, Text "bye"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+]), 
+  rect(body: text(body: [Like and Subscribe!]), 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 5.0pt), 
+  text(body: [
+]), 
+  text(body: [hi]), 
+  parbreak(), 
+  text(body: [bye]), 
+  parbreak() }
diff --git a/test/out/compiler/import-01.out b/test/out/compiler/import-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-01.out
@@ -0,0 +1,115 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/import-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/import-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/import-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/import-01.typ"
+    ( line 3 , column 2 )
+    (Import
+       (Literal (String "module.typ"))
+       (SomeIdentifiers [ Identifier "item" ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/import-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "item"))
+              [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+, Comment
+, Text "{"
+, SoftBreak
+, Text "import"
+, Space
+, Quote '"'
+, Text "module"
+, Text "."
+, Text "typ"
+, Quote '"'
+, Text ":"
+, Space
+, Text "b"
+, SoftBreak
+, Text "test"
+, Text "("
+, Text "b,"
+, Space
+, Text "1)"
+, SoftBreak
+, Text "}"
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/import-01.typ"
+    ( line 13 , column 2 )
+    (Import (Literal (String "module.typ")) AllIdentifiers)
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/import-01.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "d"))
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [{
+import “module.typ”: b
+test(b, 1)
+}]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/import-02.out b/test/out/compiler/import-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-02.out
@@ -0,0 +1,108 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/import-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/import-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/import-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/import-02.typ"
+    ( line 5 , column 2 )
+    (Import
+       (Ident (Identifier "enum"))
+       (SomeIdentifiers [ Identifier "item" ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/import-02.typ"
+    ( line 6 , column 2 )
+    (Import
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "assert")))
+          [ NormalArg (Literal (Boolean True)) ])
+       AllIdentifiers)
+, ParBreak
+, Code
+    "test/typ/compiler/import-02.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "enum"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "item"))
+              [ NormalArg (Literal (Int 1)) , BlockArg [ Text "First" ] ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "item"))
+              [ NormalArg (Literal (Int 5)) , BlockArg [ Text "Fifth" ] ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/import-02.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "eq"))
+       [ NormalArg (Literal (Int 10)) , NormalArg (Literal (Int 10)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/import-02.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "ne"))
+       [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 6)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  enum(children: (enum.item(body: text(body: [First]), 
+                            number: 1), 
+                  enum.item(body: text(body: [Fifth]), 
+                            number: 5))), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/compiler/import-03.out b/test/out/compiler/import-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-03.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/import-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/import-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/import-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/import-03.typ"
+    ( line 3 , column 2 )
+    (Import (Literal (String "module.typ")) NoIdentifiers)
+, SoftBreak
+, Code
+    "test/typ/compiler/import-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "b")) (Ident (Identifier "module")))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/import-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "item")) (Ident (Identifier "module")))
+              [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/import-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "push")) (Ident (Identifier "module")))
+              [ NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/import-04.out b/test/out/compiler/import-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-05.out b/test/out/compiler/import-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-05.out
@@ -0,0 +1,61 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/import-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/import-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/import-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/import-05.typ"
+    ( line 3 , column 2 )
+    (Import (Literal (String "module.typ")) AllIdentifiers)
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/import-05.typ"
+    ( line 6 , column 2 )
+    (Import
+       (Literal (String "module.typ"))
+       (SomeIdentifiers [ Identifier "a" , Identifier "c" ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  parbreak() }
diff --git a/test/out/compiler/import-06.out b/test/out/compiler/import-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-06.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/import-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/import-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/import-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/import-06.typ"
+    ( line 3 , column 2 )
+    (Import (Ident (Identifier "enum")) NoIdentifiers)
+, SoftBreak
+, Code
+    "test/typ/compiler/import-06.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "d")))
+       (Dict [ ( Identifier "e" , Ident (Identifier "enum") ) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/import-06.typ"
+    ( line 5 , column 2 )
+    (Import
+       (FieldAccess (Ident (Identifier "e")) (Ident (Identifier "d")))
+       NoIdentifiers)
+, SoftBreak
+, Code
+    "test/typ/compiler/import-06.typ"
+    ( line 6 , column 2 )
+    (Import
+       (FieldAccess (Ident (Identifier "e")) (Ident (Identifier "d")))
+       (SomeIdentifiers [ Identifier "item" ]))
+, ParBreak
+, Code
+    "test/typ/compiler/import-06.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "item"))
+       [ NormalArg (Literal (Int 2)) , BlockArg [ Text "a" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  enum.item(body: text(body: [a]), 
+            number: 2), 
+  parbreak() }
diff --git a/test/out/compiler/import-07.out b/test/out/compiler/import-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-08.out b/test/out/compiler/import-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-09.out b/test/out/compiler/import-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-10.out b/test/out/compiler/import-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-11.out b/test/out/compiler/import-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-12.out b/test/out/compiler/import-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-13.out b/test/out/compiler/import-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-13.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-14.out b/test/out/compiler/import-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-14.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-15.out b/test/out/compiler/import-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-15.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-16.out b/test/out/compiler/import-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-16.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-17.out b/test/out/compiler/import-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-17.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-18.out b/test/out/compiler/import-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-18.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-19.out b/test/out/compiler/import-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-19.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-20.out b/test/out/compiler/import-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-20.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-21.out b/test/out/compiler/import-21.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-21.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-22.out b/test/out/compiler/import-22.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-22.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-23.out b/test/out/compiler/import-23.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-23.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-24.out b/test/out/compiler/import-24.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-24.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/import-25.out b/test/out/compiler/import-25.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/import-25.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/include-00.out b/test/out/compiler/include-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/include-00.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/include-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/include-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/include-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/include-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt)) ])
+, ParBreak
+, Heading 1 [ Text "Document" ]
+, Comment
+, Code
+    "test/typ/compiler/include-00.typ"
+    ( line 7 , column 2 )
+    (Include (Literal (String "modules/chap1.typ")))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/include-00.typ"
+    ( line 10 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "chap2")))
+       (Include
+          (Plus
+             (Plus (Literal (String "modu")) (Literal (String "les/chap")))
+             (Literal (String "2.typ")))))
+, ParBreak
+, EnDash
+, Space
+, Emph [ Text "Intermission" ]
+, Space
+, EnDash
+, SoftBreak
+, Code
+    "test/typ/compiler/include-00.typ"
+    ( line 13 , column 2 )
+    (Ident (Identifier "chap2"))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Document]), 
+          level: 1), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [– ]), 
+  emph(body: text(body: [Intermission])), 
+  text(body: [ –
+]), 
+  parbreak() }
diff --git a/test/out/compiler/include-01.out b/test/out/compiler/include-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/include-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/include-02.out b/test/out/compiler/include-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/include-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/include-03.out b/test/out/compiler/include-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/include-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/label-00.out b/test/out/compiler/label-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/label-00.out
@@ -0,0 +1,96 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/label-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/label-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/label-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/label-00.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Literal (Numeric 10.0 Pt)) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/label-00.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "heading")))
+             [ KeyValArg (Identifier "label") (Label "intro") ]))
+       (Ident (Identifier "underline")))
+, ParBreak
+, Heading 1 [ Text "Introduction" ]
+, Code
+    "test/typ/compiler/label-00.typ"
+    ( line 6 , column 16 )
+    (Label "intro")
+, SoftBreak
+, Text "The"
+, Space
+, Text "beginning"
+, Text "."
+, ParBreak
+, Heading 1 [ Text "Conclusion" ]
+, Text "The"
+, Space
+, Text "end"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Introduction]), 
+          level: 1), 
+  <intro>, 
+  text(body: [
+The beginning.]), 
+  parbreak(), 
+  heading(body: text(body: [Conclusion]), 
+          level: 1), 
+  text(body: [The end.]), 
+  parbreak() }
diff --git a/test/out/compiler/label-01.out b/test/out/compiler/label-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/label-01.out
@@ -0,0 +1,97 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/label-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/label-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/label-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/label-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "strong")))
+             [ KeyValArg (Identifier "label") (Label "v") ]))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "red")) ]))
+, ParBreak
+, Code
+    "test/typ/compiler/label-01.typ"
+    ( line 5 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "a")))
+       (Block (Content [ Strong [ Text "A" ] ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/label-01.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "b")))
+       (Block (Content [ Strong [ Text "B" ] ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/label-01.typ"
+    ( line 7 , column 2 )
+    (Ident (Identifier "a"))
+, Space
+, Code
+    "test/typ/compiler/label-01.typ" ( line 7 , column 4 ) (Label "v")
+, Space
+, Code
+    "test/typ/compiler/label-01.typ"
+    ( line 7 , column 9 )
+    (Ident (Identifier "b"))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  strong(body: text(body: [A])), 
+  text(body: [ ]), 
+  <v>, 
+  text(body: [ ]), 
+  strong(body: text(body: [B])), 
+  parbreak() }
diff --git a/test/out/compiler/label-02.out b/test/out/compiler/label-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/label-02.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/label-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/label-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/label-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/label-02.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Literal (String "t")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( And
+                          (FuncCall
+                             (FieldAccess (Ident (Identifier "has")) (Ident (Identifier "it")))
+                             [ NormalArg (Literal (String "label")) ])
+                          (Equals
+                             (FieldAccess
+                                (Ident (Identifier "label")) (Ident (Identifier "it")))
+                             (Label "last"))
+                      , Set
+                          (Ident (Identifier "text"))
+                          [ NormalArg (Ident (Identifier "blue")) ]
+                      )
+                    ]
+                , Ident (Identifier "it")
+                ]))))
+, ParBreak
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "a"
+, Space
+, Text "thing"
+, Space
+, Code
+    "test/typ/compiler/label-02.typ"
+    ( line 8 , column 18 )
+    (Block
+       (Content
+          [ Text "that"
+          , Space
+          , Code
+              "test/typ/compiler/label-02.typ"
+              ( line 8 , column 24 )
+              (Label "last")
+          ]))
+, Space
+, Text "happened"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [This is a thing ]), 
+  text(body: [that ]), 
+  <last>, 
+  text(body: [ happened.]), 
+  parbreak() }
diff --git a/test/out/compiler/label-03.out b/test/out/compiler/label-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/label-03.out
@@ -0,0 +1,100 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/label-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/label-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/label-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/label-03.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Label "red"))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "red")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/label-03.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Label "blue"))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "blue")) ]))
+, ParBreak
+, Strong [ Text "A" ]
+, Space
+, Strong [ Text "B" ]
+, Space
+, Code
+    "test/typ/compiler/label-03.typ"
+    ( line 6 , column 9 )
+    (Label "red")
+, Space
+, Strong [ Text "C" ]
+, Space
+, Code
+    "test/typ/compiler/label-03.typ"
+    ( line 6 , column 20 )
+    (FuncCall
+       (Ident (Identifier "label"))
+       [ NormalArg (Plus (Literal (String "bl")) (Literal (String "ue")))
+       ])
+, Space
+, Strong [ Text "D" ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  strong(body: text(body: [A])), 
+  text(body: [ ]), 
+  strong(body: text(body: [B])), 
+  text(body: [ ]), 
+  <red>, 
+  text(body: [ ]), 
+  strong(body: text(body: [C])), 
+  text(body: [ ]), 
+  <blue>, 
+  text(body: [ ]), 
+  strong(body: text(body: [D])), 
+  parbreak() }
diff --git a/test/out/compiler/label-04.out b/test/out/compiler/label-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/label-04.out
@@ -0,0 +1,80 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/label-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/label-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/label-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/label-04.typ"
+    ( line 3 , column 2 )
+    (Show (Just (Label "hide")) (Literal None))
+, ParBreak
+, Emph [ Text "Hidden" ]
+, SoftBreak
+, Code
+    "test/typ/compiler/label-04.typ"
+    ( line 6 , column 1 )
+    (Label "hide")
+, ParBreak
+, Emph [ Text "Hidden" ]
+, ParBreak
+, Code
+    "test/typ/compiler/label-04.typ"
+    ( line 10 , column 1 )
+    (Label "hide")
+, SoftBreak
+, Emph [ Text "Visible" ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  emph(body: text(body: [Hidden])), 
+  text(body: [
+]), 
+  <hide>, 
+  parbreak(), 
+  emph(body: text(body: [Hidden])), 
+  parbreak(), 
+  <hide>, 
+  text(body: [
+]), 
+  emph(body: text(body: [Visible])), 
+  parbreak() }
diff --git a/test/out/compiler/label-05.out b/test/out/compiler/label-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/label-05.out
@@ -0,0 +1,87 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/label-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/label-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/label-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/label-05.typ"
+    ( line 3 , column 2 )
+    (Show (Just (Label "strike")) (Ident (Identifier "strike")))
+, SoftBreak
+, Strong [ Text "This" , Space , Text "is" ]
+, Space
+, Code
+    "test/typ/compiler/label-05.typ"
+    ( line 4 , column 12 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/compiler/label-05.typ"
+              ( line 4 , column 13 )
+              (Label "strike")
+          ]))
+, Space
+, Strong [ Text "protected" , Text "." ]
+, SoftBreak
+, Strong
+    [ Text "This" , Space , Text "is" , Space , Text "not" , Text "." ]
+, Space
+, Code
+    "test/typ/compiler/label-05.typ"
+    ( line 5 , column 16 )
+    (Label "strike")
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  strong(body: text(body: [This is])), 
+  text(body: [ ]), 
+  <strike>, 
+  text(body: [ ]), 
+  strong(body: text(body: [protected.])), 
+  text(body: [
+]), 
+  strong(body: text(body: [This is not.])), 
+  text(body: [ ]), 
+  <strike>, 
+  parbreak() }
diff --git a/test/out/compiler/label-06.out b/test/out/compiler/label-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/label-06.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/label-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/label-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/label-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "1"
+, Space
+, Text "<"
+, Space
+, Text "2"
+, Space
+, Text "is"
+, Space
+, Code
+    "test/typ/compiler/label-06.typ"
+    ( line 3 , column 11 )
+    (If
+       [ ( LessThan (Literal (Int 1)) (Literal (Int 2))
+         , Block (Content [ Text "not" ])
+         )
+       ])
+, Space
+, Text "a"
+, Space
+, Text "label"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [1 < 2 is ]), 
+  text(body: [not]), 
+  text(body: [ a label.]), 
+  parbreak() }
diff --git a/test/out/compiler/let-00.out b/test/out/compiler/let-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-00.out
@@ -0,0 +1,117 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/let-00.typ"
+    ( line 3 , column 2 )
+    (Let (BasicBind (Just (Identifier "x"))) (Literal None))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x")) , NormalArg (Literal None) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/let-00.typ"
+    ( line 7 , column 2 )
+    (Let (BasicBind (Just (Identifier "z"))) (Literal (Int 1)))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "z"))
+       , NormalArg (Literal (Int 1))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/let-00.typ"
+    ( line 11 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "fill")))
+       (Ident (Identifier "green")))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-00.typ"
+    ( line 12 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "body") ]
+       (FuncCall
+          (Ident (Identifier "rect"))
+          [ KeyValArg (Identifier "width") (Literal (Numeric 2.0 Cm))
+          , KeyValArg (Identifier "fill") (Ident (Identifier "fill"))
+          , KeyValArg (Identifier "inset") (Literal (Numeric 5.0 Pt))
+          , NormalArg (Ident (Identifier "body"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-00.typ"
+    ( line 13 , column 2 )
+    (FuncCall (Ident (Identifier "f")) [ BlockArg [ Text "Hi!" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  rect(body: text(body: [Hi!]), 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 5.0pt, 
+       width: 2.0cm), 
+  parbreak() }
diff --git a/test/out/compiler/let-01.out b/test/out/compiler/let-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-01.out
@@ -0,0 +1,116 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/let-01.typ"
+    ( line 5 , column 2 )
+    (Let (BasicBind (Just (Identifier "v1"))) (Literal (Int 1)))
+, SoftBreak
+, Text "One"
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/let-01.typ"
+    ( line 9 , column 2 )
+    (Let (BasicBind (Just (Identifier "v2"))) (Literal (Int 2)))
+, Space
+, Text "Two"
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/let-01.typ"
+    ( line 12 , column 2 )
+    (Let (BasicBind (Just (Identifier "v3"))) (Literal (Int 3)))
+, SoftBreak
+, Text "Three"
+, ParBreak
+, Code
+    "test/typ/compiler/let-01.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "v1"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-01.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "v2"))
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-01.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "v3"))
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+One]), 
+  parbreak(), 
+  text(body: [ Two]), 
+  parbreak(), 
+  text(body: [
+Three]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-02.out b/test/out/compiler/let-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-02.out
@@ -0,0 +1,55 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-02.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "a")))
+       (Array [ Literal (Int 1) , Literal (Int 2) ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/compiler/let-03.out b/test/out/compiler/let-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-03.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-03.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Simple (Just (Identifier "a"))
+          , Simple (Just (Identifier "b"))
+          ])
+       (Array [ Literal (Int 1) , Literal (Int 2) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-04.out b/test/out/compiler/let-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-04.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/let-04.typ"
+    ( line 3 , column 2 )
+    (Let
+       (DestructuringBind [ Simple (Just (Identifier "a")) ])
+       (Array [ Literal (Int 1) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-05.out b/test/out/compiler/let-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-05.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-05.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Simple (Just (Identifier "a"))
+          , Simple Nothing
+          , Simple (Just (Identifier "c"))
+          , Simple Nothing
+          ])
+       (Array
+          [ Literal (Int 1)
+          , Literal (Int 2)
+          , Literal (Int 3)
+          , Literal (Int 4)
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-05.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-05.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "c"))
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-06.out b/test/out/compiler/let-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-06.out
@@ -0,0 +1,108 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-06.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Simple (Just (Identifier "a"))
+          , Simple (Just (Identifier "b"))
+          , Sink (Just (Identifier "c"))
+          ])
+       (Array
+          [ Literal (Int 1)
+          , Literal (Int 2)
+          , Literal (Int 3)
+          , Literal (Int 4)
+          , Literal (Int 5)
+          , Literal (Int 6)
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-06.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-06.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-06.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "c"))
+       , NormalArg
+           (Array
+              [ Literal (Int 3)
+              , Literal (Int 4)
+              , Literal (Int 5)
+              , Literal (Int 6)
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-07.out b/test/out/compiler/let-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-07.out
@@ -0,0 +1,108 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-07.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Simple (Just (Identifier "a"))
+          , Sink (Just (Identifier "b"))
+          , Simple (Just (Identifier "c"))
+          ])
+       (Array
+          [ Literal (Int 1)
+          , Literal (Int 2)
+          , Literal (Int 3)
+          , Literal (Int 4)
+          , Literal (Int 5)
+          , Literal (Int 6)
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-07.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-07.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg
+           (Array
+              [ Literal (Int 2)
+              , Literal (Int 3)
+              , Literal (Int 4)
+              , Literal (Int 5)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-07.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "c"))
+       , NormalArg (Literal (Int 6))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-08.out b/test/out/compiler/let-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-08.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-08.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Sink (Just (Identifier "a"))
+          , Simple (Just (Identifier "b"))
+          , Simple (Just (Identifier "c"))
+          ])
+       (Array [ Literal (Int 1) , Literal (Int 2) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-08.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a")) , NormalArg (Array []) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-08.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-08.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "c"))
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-09.out b/test/out/compiler/let-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-09.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-09.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Simple (Just (Identifier "a"))
+          , Sink (Just (Identifier "b"))
+          , Simple (Just (Identifier "c"))
+          ])
+       (Array [ Literal (Int 1) , Literal (Int 2) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-09.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-09.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b")) , NormalArg (Array []) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-09.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "c"))
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-10.out b/test/out/compiler/let-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-10.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-10.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-10.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-10.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-10.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Simple (Just (Identifier "a"))
+          , Simple (Just (Identifier "b"))
+          , Sink (Just (Identifier "c"))
+          ])
+       (Array [ Literal (Int 1) , Literal (Int 2) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-10.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-10.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-10.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "c")) , NormalArg (Array []) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-11.out b/test/out/compiler/let-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-11.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-11.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-11.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-11.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-11.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind [ Sink (Just (Identifier "a")) ]) (Array []))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-11.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a")) , NormalArg (Array []) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-12.out b/test/out/compiler/let-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-13.out b/test/out/compiler/let-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-13.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-14.out b/test/out/compiler/let-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-14.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-15.out b/test/out/compiler/let-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-15.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-16.out b/test/out/compiler/let-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-16.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-16.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-16.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-16.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-16.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ WithKey (Identifier "a") (Just (Identifier "a"))
+          , Simple (Just (Identifier "b"))
+          , WithKey (Identifier "x") (Just (Identifier "c"))
+          ])
+       (Dict
+          [ ( Identifier "a" , Literal (Int 1) )
+          , ( Identifier "b" , Literal (Int 2) )
+          , ( Identifier "x" , Literal (Int 3) )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-16.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-16.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/let-16.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "c"))
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-17.out b/test/out/compiler/let-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-17.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-17.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-17.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-17.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-17.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ WithKey (Identifier "a") Nothing
+          , Sink (Just (Identifier "b"))
+          ])
+       (Dict
+          [ ( Identifier "a" , Literal (Int 1) )
+          , ( Identifier "b" , Literal (Int 2) )
+          , ( Identifier "c" , Literal (Int 3) )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-17.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg
+           (Dict
+              [ ( Identifier "b" , Literal (Int 2) )
+              , ( Identifier "c" , Literal (Int 3) )
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-18.out b/test/out/compiler/let-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-18.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-18.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-18.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-18.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-18.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ WithKey (Identifier "a") Nothing
+          , Sink (Just (Identifier "b"))
+          , WithKey (Identifier "c") Nothing
+          ])
+       (Dict
+          [ ( Identifier "a" , Literal (Int 1) )
+          , ( Identifier "b" , Literal (Int 2) )
+          , ( Identifier "c" , Literal (Int 3) )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-18.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b"))
+       , NormalArg (Dict [ ( Identifier "b" , Literal (Int 2) ) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-19.out b/test/out/compiler/let-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-19.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-19.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-19.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-19.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-19.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ WithKey (Identifier "a") Nothing
+          , Sink (Just (Identifier "b"))
+          ])
+       (Dict [ ( Identifier "a" , Literal (Int 1) ) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-19.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "b")) , NormalArg (Dict []) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-20.out b/test/out/compiler/let-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-20.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-20.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-20.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-20.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-20.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind [ Sink (Just (Identifier "a")) ]) (Dict []))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-20.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a")) , NormalArg (Dict []) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-21.out b/test/out/compiler/let-21.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-21.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/let-21.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/let-21.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/let-21.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/let-21.typ"
+    ( line 4 , column 2 )
+    (Let
+       (DestructuringBind
+          [ Simple (Just (Identifier "a")) , Sink Nothing ])
+       (Dict
+          [ ( Identifier "a" , Literal (Int 1) )
+          , ( Identifier "b" , Literal (Int 2) )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/let-21.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "a"))
+       , NormalArg (Literal (Int 1))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/let-22.out b/test/out/compiler/let-22.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-22.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-23.out b/test/out/compiler/let-23.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-23.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-24.out b/test/out/compiler/let-24.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-24.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-25.out b/test/out/compiler/let-25.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-25.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-26.out b/test/out/compiler/let-26.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-26.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-27.out b/test/out/compiler/let-27.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-27.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-28.out b/test/out/compiler/let-28.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-28.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/let-29.out b/test/out/compiler/let-29.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/let-29.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/methods-00.out b/test/out/compiler/methods-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/methods-00.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/methods-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/methods-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/methods-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/methods-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "split")) (Literal (String "Hi there")))
+              [])
+       , NormalArg
+           (Array [ Literal (String "Hi") , Literal (String "there") ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/methods-01.out b/test/out/compiler/methods-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/methods-01.out
@@ -0,0 +1,85 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/methods-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/methods-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/methods-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/methods-01.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "matrix")))
+              (Array
+                 [ Array [ Array [ Literal (Int 1) ] , Array [ Literal (Int 2) ] ]
+                 , Array [ Array [ Literal (Int 3) ] , Array [ Literal (Int 4) ] ]
+                 ])
+          , FuncCall
+              (FieldAccess
+                 (Ident (Identifier "push"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "at"))
+                       (FuncCall
+                          (FieldAccess
+                             (Ident (Identifier "at")) (Ident (Identifier "matrix")))
+                          [ NormalArg (Literal (Int 1)) ]))
+                    [ NormalArg (Literal (Int 0)) ]))
+              [ NormalArg (Literal (Int 5)) ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "matrix"))
+              , NormalArg
+                  (Array
+                     [ Array [ Array [ Literal (Int 1) ] , Array [ Literal (Int 2) ] ]
+                     , Array
+                         [ Array [ Literal (Int 3) , Literal (Int 5) ]
+                         , Array [ Literal (Int 4) ]
+                         ]
+                     ])
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/methods-02.out b/test/out/compiler/methods-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/methods-02.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/methods-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/methods-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/methods-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/methods-02.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "rewritten")))
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "join"))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "map"))
+                          (FuncCall
+                             (FieldAccess
+                                (Ident (Identifier "filter"))
+                                (FuncCall
+                                   (FieldAccess
+                                      (Ident (Identifier "map"))
+                                      (FuncCall
+                                         (FieldAccess
+                                            (Ident (Identifier "split"))
+                                            (Literal
+                                               (String "Hello. This is a sentence. And one more.")))
+                                         [ NormalArg (Literal (String ".")) ]))
+                                   [ NormalArg
+                                       (FuncExpr
+                                          [ NormalParam (Identifier "s") ]
+                                          (FuncCall
+                                             (FieldAccess
+                                                (Ident (Identifier "trim"))
+                                                (Ident (Identifier "s")))
+                                             []))
+                                   ]))
+                             [ NormalArg
+                                 (FuncExpr
+                                    [ NormalParam (Identifier "s") ]
+                                    (Not (Equals (Ident (Identifier "s")) (Literal (String "")))))
+                             ]))
+                       [ NormalArg
+                           (FuncExpr
+                              [ NormalParam (Identifier "s") ]
+                              (Plus (Ident (Identifier "s")) (Literal (String "!"))))
+                       ]))
+                 [ NormalArg (Literal (String "\n ")) ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Ident (Identifier "rewritten"))
+              , NormalArg
+                  (Literal (String "Hello!\n This is a sentence!\n And one more!"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/methods-03.out b/test/out/compiler/methods-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/methods-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/methods-04.out b/test/out/compiler/methods-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/methods-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/methods-05.out b/test/out/compiler/methods-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/methods-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/methods-06.out b/test/out/compiler/methods-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/methods-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/module.out b/test/out/compiler/module.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/module.out
@@ -0,0 +1,131 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/module.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/module.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/module.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 5 , column 2 )
+    (Let (BasicBind (Just (Identifier "a"))) (Literal None))
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 6 , column 2 )
+    (Let (BasicBind (Just (Identifier "b"))) (Literal (Int 1)))
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 7 , column 2 )
+    (Let (BasicBind (Just (Identifier "c"))) (Literal (Int 2)))
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 8 , column 2 )
+    (Let (BasicBind (Just (Identifier "d"))) (Literal (Int 3)))
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 9 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "value")))
+       (Block (Content [ Text "hi" ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 10 , column 2 )
+    (LetFunc
+       (Identifier "item")
+       [ NormalParam (Identifier "a") , NormalParam (Identifier "b") ]
+       (Plus (Ident (Identifier "a")) (Ident (Identifier "b"))))
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 11 , column 2 )
+    (LetFunc
+       (Identifier "push")
+       [ NormalParam (Identifier "a") ]
+       (Plus (Ident (Identifier "a")) (Literal (Int 1))))
+, SoftBreak
+, Code
+    "test/typ/compiler/module.typ"
+    ( line 12 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "fn")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "rect")))
+          [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+          , KeyValArg (Identifier "inset") (Literal (Numeric 5.0 Pt))
+          ]))
+, ParBreak
+, Text "Some"
+, Space
+, Emph [ Text "includable" ]
+, Space
+, Text "text"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Some ]), 
+  emph(body: text(body: [includable])), 
+  text(body: [ text.]), 
+  parbreak() }
diff --git a/test/out/compiler/modules/chap1.out b/test/out/compiler/modules/chap1.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/modules/chap1.out
@@ -0,0 +1,173 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/modules/chap1.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/modules/chap1.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/modules/chap1.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/modules/chap1.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "name"))) (Literal (String "Klaus")))
+, ParBreak
+, Heading 2 [ Text "Chapter" , Space , Text "1" ]
+, Code
+    "test/typ/compiler/modules/chap1.typ"
+    ( line 7 , column 2 )
+    (Ident (Identifier "name"))
+, Space
+, Text "stood"
+, Space
+, Text "in"
+, Space
+, Text "a"
+, Space
+, Text "field"
+, Space
+, Text "of"
+, Space
+, Text "wheat"
+, Text "."
+, Space
+, Text "There"
+, Space
+, Text "was"
+, Space
+, Text "nothing"
+, Space
+, Text "of"
+, Space
+, Text "particular"
+, Space
+, Text "interest"
+, Space
+, Text "about"
+, SoftBreak
+, Text "the"
+, Space
+, Text "field"
+, Space
+, Code
+    "test/typ/compiler/modules/chap1.typ"
+    ( line 8 , column 12 )
+    (Ident (Identifier "name"))
+, Space
+, Text "just"
+, Space
+, Text "casually"
+, Space
+, Text "surveyed"
+, Space
+, Text "for"
+, Space
+, Text "any"
+, Space
+, Text "paths"
+, Space
+, Text "on"
+, Space
+, Text "which"
+, Space
+, Text "the"
+, Space
+, Text "corn"
+, Space
+, Text "would"
+, Space
+, Text "not"
+, SoftBreak
+, Text "totally"
+, Space
+, Text "ruin"
+, Space
+, Text "his"
+, Space
+, Text "semi"
+, Text "-"
+, Text "new"
+, Space
+, Text "outdorsy"
+, Space
+, Text "jacket"
+, Space
+, Text "but"
+, Space
+, Text "then"
+, Space
+, Text "again,"
+, Space
+, Text "most"
+, Space
+, Text "of"
+, Space
+, Text "us"
+, Space
+, Text "spend"
+, SoftBreak
+, Text "considerable"
+, Space
+, Text "time"
+, Space
+, Text "in"
+, Space
+, Text "non"
+, Text "-"
+, Text "descript"
+, Space
+, Text "environments"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Chapter 1]), 
+          level: 2), 
+  text(body: [Klaus]), 
+  text(body: [ stood in a field of wheat. There was nothing of particular interest about
+the field ]), 
+  text(body: [Klaus]), 
+  text(body: [ just casually surveyed for any paths on which the corn would not
+totally ruin his semi-new outdorsy jacket but then again, most of us spend
+considerable time in non-descript environments.]), 
+  parbreak() }
diff --git a/test/out/compiler/modules/chap2.out b/test/out/compiler/modules/chap2.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/modules/chap2.out
@@ -0,0 +1,238 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/modules/chap2.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/modules/chap2.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/modules/chap2.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/modules/chap2.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "name"))) (Literal (String "Klaus")))
+, ParBreak
+, Heading 2 [ Text "Chapter" , Space , Text "2" ]
+, Text "Their"
+, Space
+, Text "motivations,"
+, Space
+, Text "however,"
+, Space
+, Text "were"
+, Space
+, Text "pretty"
+, Space
+, Text "descript,"
+, Space
+, Text "so"
+, Space
+, Text "to"
+, Space
+, Text "speak"
+, Text "."
+, Space
+, Code
+    "test/typ/compiler/modules/chap2.typ"
+    ( line 7 , column 65 )
+    (Ident (Identifier "name"))
+, Space
+, Text "had"
+, Space
+, Text "not"
+, Space
+, Text "yet"
+, SoftBreak
+, Text "conceptualized"
+, Space
+, Text "their"
+, Space
+, Text "consequences,"
+, Space
+, Text "but"
+, Space
+, Text "that"
+, Space
+, Text "should"
+, Space
+, Text "change"
+, Space
+, Text "pretty"
+, Space
+, Text "quickly"
+, Text "."
+, Space
+, Code
+    "test/typ/compiler/modules/chap2.typ"
+    ( line 8 , column 76 )
+    (Ident (Identifier "name"))
+, SoftBreak
+, Text "approached"
+, Space
+, Text "the"
+, Space
+, Text "center"
+, Space
+, Text "of"
+, Space
+, Text "the"
+, Space
+, Text "field"
+, Space
+, Text "and"
+, Space
+, Text "picked"
+, Space
+, Text "up"
+, Space
+, Text "a"
+, Space
+, Text "4"
+, Text "-"
+, Text "foot"
+, Space
+, Text "long"
+, Space
+, Text "disk"
+, Space
+, Text "made"
+, Space
+, Text "from"
+, SoftBreak
+, Text "what"
+, Space
+, Text "could"
+, Space
+, Text "only"
+, Space
+, Text "be"
+, Space
+, Text "cow"
+, Space
+, Text "manure"
+, Text "."
+, Space
+, Text "The"
+, Space
+, Text "hair"
+, Space
+, Text "on"
+, Space
+, Text "the"
+, Space
+, Text "back"
+, Space
+, Text "of"
+, Space
+, Code
+    "test/typ/compiler/modules/chap2.typ"
+    ( line 10 , column 57 )
+    (Ident (Identifier "name"))
+, Quote '\''
+, Space
+, Text "neck"
+, Space
+, Text "bristled"
+, Space
+, Text "as"
+, SoftBreak
+, Text "he"
+, Space
+, Text "stared"
+, Space
+, Text "at"
+, Space
+, Text "the"
+, Space
+, Text "unusual"
+, Space
+, Text "sight"
+, Text "."
+, Space
+, Text "After"
+, Space
+, Text "studying"
+, Space
+, Text "the"
+, Space
+, Text "object"
+, Space
+, Text "for"
+, Space
+, Text "a"
+, Space
+, Text "while,"
+, Space
+, Text "he"
+, SoftBreak
+, Text "promptly"
+, Space
+, Text "popped"
+, Space
+, Text "the"
+, Space
+, Text "question,"
+, Space
+, Quote '"'
+, Text "How"
+, Space
+, Text "much?"
+, Quote '"'
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Chapter 2]), 
+          level: 2), 
+  text(body: [Their motivations, however, were pretty descript, so to speak. ]), 
+  text(body: [Klaus]), 
+  text(body: [ had not yet
+conceptualized their consequences, but that should change pretty quickly. ]), 
+  text(body: [Klaus]), 
+  text(body: [
+approached the center of the field and picked up a 4-foot long disk made from
+what could only be cow manure. The hair on the back of ]), 
+  text(body: [Klaus]), 
+  text(body: [” neck bristled as
+he stared at the unusual sight. After studying the object for a while, he
+promptly popped the question, “How much?”]), 
+  parbreak() }
diff --git a/test/out/compiler/modules/cycle1.out b/test/out/compiler/modules/cycle1.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/modules/cycle1.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/modules/cycle2.out b/test/out/compiler/modules/cycle2.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/modules/cycle2.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-00.out b/test/out/compiler/ops-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-00.out
@@ -0,0 +1,58 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/ops-00.typ"
+    ( line 4 , column 2 )
+    (Plus
+       (Block (Content [ Strong [ Text "Hello" ] , Space ]))
+       (Block (Content [ Text "world!" ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  strong(body: text(body: [Hello])), 
+  text(body: [ ]), 
+  text(body: [world!]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-01.out b/test/out/compiler/ops-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-01.out
@@ -0,0 +1,250 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 5 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "v")))
+       (Array
+          [ Literal (Int 1)
+          , Literal (Float 3.14)
+          , Literal (Numeric 12.0 Pt)
+          , Literal (Numeric 45.0 Deg)
+          , Literal (Numeric 90.0 Percent)
+          , Plus (Literal (Numeric 13.0 Percent)) (Literal (Numeric 10.0 Pt))
+          , Literal (Numeric 6.3 Fr)
+          ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg (Ident (Identifier "v"))
+                 , NormalArg (Ident (Identifier "v"))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg (Negated (Ident (Identifier "v")))
+                 , NormalArg
+                     (Times (Negated (Literal (Int 1))) (Ident (Identifier "v")))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg (Negated (Negated (Ident (Identifier "v"))))
+                 , NormalArg (Ident (Identifier "v"))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg (Negated (Negated (Negated (Ident (Identifier "v")))))
+                 , NormalArg (Negated (Ident (Identifier "v")))
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Negated (Plus (Literal (Int 4)) (Literal (Int 2))))
+       , NormalArg (Minus (Literal (Int 6)) (Literal (Int 12)))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 20 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Plus (Literal (Int 2)) (Literal (Int 4)))
+       , NormalArg (Literal (Int 6))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Plus (Literal (String "a")) (Literal (String "b")))
+       , NormalArg (Literal (String "ab"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (Literal (String "a"))
+              (If
+                 [ ( Literal (Boolean False)
+                   , Block (CodeBlock [ Literal (String "b") ])
+                   )
+                 ]))
+       , NormalArg (Literal (String "a"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 23 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (Literal (String "a"))
+              (If
+                 [ ( Literal (Boolean True)
+                   , Block (CodeBlock [ Literal (String "b") ])
+                   )
+                 ]))
+       , NormalArg (Literal (String "ab"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 24 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (Times (Literal (Int 13)) (Literal (String "a")))
+              (Literal (String "bbbbbb")))
+       , NormalArg (Literal (String "aaaaaaaaaaaaabbbbbb"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 25 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (Array [ Literal (Int 1) , Literal (Int 2) ])
+              (Array [ Literal (Int 3) , Literal (Int 4) ]))
+       , NormalArg
+           (Array
+              [ Literal (Int 1)
+              , Literal (Int 2)
+              , Literal (Int 3)
+              , Literal (Int 4)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-01.typ"
+    ( line 26 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (Dict [ ( Identifier "a" , Literal (Int 1) ) ])
+              (Dict
+                 [ ( Identifier "b" , Literal (Int 2) )
+                 , ( Identifier "c" , Literal (Int 3) )
+                 ]))
+       , NormalArg
+           (Dict
+              [ ( Identifier "a" , Literal (Int 1) )
+              , ( Identifier "b" , Literal (Int 2) )
+              , ( Identifier "c" , Literal (Int 3) )
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-02.out b/test/out/compiler/ops-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-03.out b/test/out/compiler/ops-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-03.out
@@ -0,0 +1,685 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Minus (Literal (Int 1)) (Literal (Int 4)))
+       , NormalArg (Times (Literal (Int 3)) (Negated (Literal (Int 1))))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Minus (Literal (Numeric 4.0 Cm)) (Literal (Numeric 2.0 Cm)))
+       , NormalArg (Literal (Numeric 2.0 Cm))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (ToPower
+              (Minus (Literal (Int 2)) (Literal (Float 1.0e-2)))
+              (Literal (Int 1)))
+       , NormalArg (Literal (Float 99.99))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Times (Literal (Int 2)) (Literal (Int 4)))
+       , NormalArg (Literal (Int 8))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Divided (Literal (Numeric 12.0 Pt)) (Literal (Float 0.4)))
+       , NormalArg (Literal (Numeric 30.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Divided (Literal (Int 7)) (Literal (Int 2)))
+       , NormalArg (Literal (Float 3.5))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (LessThan
+              (Minus
+                 (Literal (Int 3)) (Times (Literal (Int 4)) (Literal (Int 5))))
+              (Negated (Literal (Int 10))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Block
+              (CodeBlock
+                 [ Let (BasicBind (Just (Identifier "x"))) (Literal None)
+                 , Assign
+                     (Binding (BasicBind (Just (Identifier "x"))))
+                     (And
+                        (GreaterThanOrEqual
+                           (Plus
+                              (Literal (Int 1)) (Times (Literal (Int 4)) (Literal (Int 5))))
+                           (Literal (Int 21)))
+                        (Block
+                           (CodeBlock
+                              [ Assign
+                                  (Binding (BasicBind (Just (Identifier "x"))))
+                                  (Literal (String "a"))
+                              , Equals
+                                  (Plus (Ident (Identifier "x")) (Literal (String "b")))
+                                  (Literal (String "ab"))
+                              ])))
+                 , Ident (Identifier "x")
+                 ]))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (If
+                 [ ( Literal (Boolean True)
+                   , Block (CodeBlock [ Literal (Int 1) ])
+                   )
+                 ])
+              (Literal (Int 2)))
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 24 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "nums")))
+       (Array
+          [ Literal (Int 1)
+          , Literal (Float 3.14)
+          , Literal (Numeric 12.0 Pt)
+          , Literal (Numeric 3.0 Em)
+          , Plus (Literal (Numeric 12.0 Pt)) (Literal (Numeric 3.0 Em))
+          , Literal (Numeric 45.0 Deg)
+          , Literal (Numeric 90.0 Percent)
+          , Plus (Literal (Numeric 13.0 Percent)) (Literal (Numeric 10.0 Pt))
+          , Plus
+              (Plus (Literal (Numeric 5.0 Percent)) (Literal (Numeric 1.0 Em)))
+              (Literal (Numeric 3.0 Pt))
+          , Literal (Numeric 2.3 Fr)
+          ]))
+, ParBreak
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 33 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "v")))
+       (Ident (Identifier "nums"))
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg
+                     (Minus
+                        (Plus (Ident (Identifier "v")) (Ident (Identifier "v")))
+                        (Ident (Identifier "v")))
+                 , NormalArg (Ident (Identifier "v"))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg
+                     (Minus
+                        (Minus (Ident (Identifier "v")) (Ident (Identifier "v")))
+                        (Ident (Identifier "v")))
+                 , NormalArg (Negated (Ident (Identifier "v")))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg
+                     (Minus (Ident (Identifier "v")) (Ident (Identifier "v")))
+                 , NormalArg (Times (Literal (Int 0)) (Ident (Identifier "v")))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "test"))
+                 [ NormalArg
+                     (Plus (Ident (Identifier "v")) (Ident (Identifier "v")))
+                 , NormalArg (Times (Literal (Int 2)) (Ident (Identifier "v")))
+                 ]
+             , If
+                 [ ( Not
+                       (Equals
+                          (FuncCall
+                             (Ident (Identifier "type")) [ NormalArg (Ident (Identifier "v")) ])
+                          (Literal (String "integer")))
+                   , Block
+                       (CodeBlock
+                          [ FuncCall
+                              (Ident (Identifier "test"))
+                              [ NormalArg
+                                  (Plus (Ident (Identifier "v")) (Ident (Identifier "v")))
+                              , NormalArg (Times (Literal (Float 2.0)) (Ident (Identifier "v")))
+                              ]
+                          ])
+                   )
+                 ]
+             , If
+                 [ ( And
+                       (Not
+                          (InCollection
+                             (Literal (String "relative"))
+                             (FuncCall
+                                (Ident (Identifier "type"))
+                                [ NormalArg (Ident (Identifier "v")) ])))
+                       (Or
+                          (Not
+                             (InCollection
+                                (Literal (String "pt"))
+                                (FuncCall
+                                   (Ident (Identifier "repr"))
+                                   [ NormalArg (Ident (Identifier "v")) ])))
+                          (Not
+                             (InCollection
+                                (Literal (String "em"))
+                                (FuncCall
+                                   (Ident (Identifier "repr"))
+                                   [ NormalArg (Ident (Identifier "v")) ]))))
+                   , Block
+                       (CodeBlock
+                          [ FuncCall
+                              (Ident (Identifier "test"))
+                              [ NormalArg
+                                  (Divided (Ident (Identifier "v")) (Ident (Identifier "v")))
+                              , NormalArg (Literal (Float 1.0))
+                              ]
+                          ])
+                   )
+                 ]
+             ])))
+, ParBreak
+, Comment
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 56 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "dims")))
+       (Array
+          [ Literal (Numeric 10.0 Pt)
+          , Literal (Numeric 1.0 Em)
+          , Plus (Literal (Numeric 10.0 Pt)) (Literal (Numeric 1.0 Em))
+          , Literal (Numeric 30.0 Percent)
+          , Plus (Literal (Numeric 50.0 Percent)) (Literal (Numeric 3.0 Cm))
+          , Plus
+              (Plus (Literal (Numeric 40.0 Percent)) (Literal (Numeric 2.0 Em)))
+              (Literal (Numeric 1.0 Cm))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 57 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "a")))
+       (Ident (Identifier "dims"))
+       (Block
+          (CodeBlock
+             [ For
+                 (BasicBind (Just (Identifier "b")))
+                 (Ident (Identifier "dims"))
+                 (Block
+                    (CodeBlock
+                       [ FuncCall
+                           (Ident (Identifier "test"))
+                           [ NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg
+                                      (Plus (Ident (Identifier "a")) (Ident (Identifier "b")))
+                                  ])
+                           , NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg
+                                      (Minus (Ident (Identifier "a")) (Ident (Identifier "b")))
+                                  ])
+                           ]
+                       ]))
+             , For
+                 (BasicBind (Just (Identifier "b")))
+                 (Array [ Literal (Int 7) , Literal (Float 3.14) ])
+                 (Block
+                    (CodeBlock
+                       [ FuncCall
+                           (Ident (Identifier "test"))
+                           [ NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg
+                                      (Times (Ident (Identifier "a")) (Ident (Identifier "b")))
+                                  ])
+                           , NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg (Ident (Identifier "a")) ])
+                           ]
+                       , FuncCall
+                           (Ident (Identifier "test"))
+                           [ NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg
+                                      (Times (Ident (Identifier "b")) (Ident (Identifier "a")))
+                                  ])
+                           , NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg (Ident (Identifier "a")) ])
+                           ]
+                       , FuncCall
+                           (Ident (Identifier "test"))
+                           [ NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg
+                                      (Divided (Ident (Identifier "a")) (Ident (Identifier "b")))
+                                  ])
+                           , NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "type"))
+                                  [ NormalArg (Ident (Identifier "a")) ])
+                           ]
+                       ]))
+             ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-03.typ"
+    ( line 70 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "a")))
+       (Array
+          [ Literal (Numeric 0.0 Pt)
+          , Literal (Numeric 0.0 Em)
+          , Literal (Numeric 0.0 Percent)
+          ])
+       (Block
+          (CodeBlock
+             [ For
+                 (BasicBind (Just (Identifier "b")))
+                 (Array
+                    [ Literal (Numeric 10.0 Pt)
+                    , Literal (Numeric 10.0 Em)
+                    , Literal (Numeric 10.0 Percent)
+                    ])
+                 (Block
+                    (CodeBlock
+                       [ FuncCall
+                           (Ident (Identifier "test"))
+                           [ NormalArg
+                               (Divided
+                                  (Times (Literal (Int 2)) (Ident (Identifier "b")))
+                                  (Ident (Identifier "b")))
+                           , NormalArg (Literal (Int 2))
+                           ]
+                       , FuncCall
+                           (Ident (Identifier "test"))
+                           [ NormalArg
+                               (Divided
+                                  (Plus
+                                     (Ident (Identifier "a"))
+                                     (Times (Ident (Identifier "b")) (Literal (Int 2))))
+                                  (Ident (Identifier "b")))
+                           , NormalArg (Literal (Int 2))
+                           ]
+                       , FuncCall
+                           (Ident (Identifier "test"))
+                           [ NormalArg
+                               (Divided
+                                  (Ident (Identifier "b"))
+                                  (Plus
+                                     (Times (Ident (Identifier "b")) (Literal (Int 2)))
+                                     (Ident (Identifier "a"))))
+                           , NormalArg (Literal (Float 0.5))
+                           ]
+                       ]))
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [1.0]), 
+  text(body: [ /= ]), 
+  text(body: [99.99]), 
+  text(body: [)]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [❌(]), 
+  text(body: [((12.0pt + 3.0em) + (12.0pt + 3.0em)) + (-12.0pt + -3.0em)]), 
+  text(body: [ /= ]), 
+  text(body: [12.0pt + 3.0em]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [((12.0pt + 3.0em) + (-12.0pt + -3.0em)) + (-12.0pt + -3.0em)]), 
+  text(body: [ /= ]), 
+  text(body: [-12.0pt + -3.0em]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [(12.0pt + 3.0em) + (-12.0pt + -3.0em)]), 
+  text(body: [ /= ]), 
+  text(body: [0.0pt + 0.0em]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [(12.0pt + 3.0em) + (12.0pt + 3.0em)]), 
+  text(body: [ /= ]), 
+  text(body: [24.0pt + 6.0em]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [(12.0pt + 3.0em) + (12.0pt + 3.0em)]), 
+  text(body: [ /= ]), 
+  text(body: [24.0pt + 6.0em]), 
+  text(body: [)]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [❌(]), 
+  text(body: [((10.0pt + 13%) + (10.0pt + 13%)) + (-10.0pt + -13%)]), 
+  text(body: [ /= ]), 
+  text(body: [10.0pt + 13%]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [((10.0pt + 13%) + (-10.0pt + -13%)) + (-10.0pt + -13%)]), 
+  text(body: [ /= ]), 
+  text(body: [-10.0pt + -13%]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [(10.0pt + 13%) + (-10.0pt + -13%)]), 
+  text(body: [ /= ]), 
+  text(body: [0.0pt + 0%]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [(10.0pt + 13%) + (10.0pt + 13%)]), 
+  text(body: [ /= ]), 
+  text(body: [20.0pt + 26%]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [(10.0pt + 13%) + (10.0pt + 13%)]), 
+  text(body: [ /= ]), 
+  text(body: [20.0pt + 26%]), 
+  text(body: [)]), 
+  text(body: [✅]), 
+  text(body: [❌(]), 
+  text(body: [(((1.0em + 5%) + 3.0pt) + ((1.0em + 5%) + 3.0pt)) + ((-1.0em + -5%) + -3.0pt)]), 
+  text(body: [ /= ]), 
+  text(body: [(1.0em + 5%) + 3.0pt]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [(((1.0em + 5%) + 3.0pt) + ((-1.0em + -5%) + -3.0pt)) + ((-1.0em + -5%) + -3.0pt)]), 
+  text(body: [ /= ]), 
+  text(body: [(-1.0em + -5%) + -3.0pt]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [((1.0em + 5%) + 3.0pt) + ((-1.0em + -5%) + -3.0pt)]), 
+  text(body: [ /= ]), 
+  text(body: [(0.0em + 0%) + 0.0pt]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [((1.0em + 5%) + 3.0pt) + ((1.0em + 5%) + 3.0pt)]), 
+  text(body: [ /= ]), 
+  text(body: [(2.0em + 10%) + 6.0pt]), 
+  text(body: [)]), 
+  text(body: [❌(]), 
+  text(body: [((1.0em + 5%) + 3.0pt) + ((1.0em + 5%) + 3.0pt)]), 
+  text(body: [ /= ]), 
+  text(body: [(2.0em + 10%) + 6.0pt]), 
+  text(body: [)]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [❌(]), 
+  text(body: [1.0fr]), 
+  text(body: [ /= ]), 
+  text(body: [1.0]), 
+  text(body: [)]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [❌(]), 
+  text(body: [200%]), 
+  text(body: [ /= ]), 
+  text(body: [2]), 
+  text(body: [)]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [❌(]), 
+  text(body: [200%]), 
+  text(body: [ /= ]), 
+  text(body: [2]), 
+  text(body: [)]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-04.out b/test/out/compiler/ops-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-04.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-04.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Literal (Int 16)) , NormalArg (Literal (Int 16)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Literal (Int 13)) , NormalArg (Literal (Int 13)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Plus (Literal (Int 10)) (Literal (Int 10)))
+       , NormalArg (Literal (Int 20))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-05.out b/test/out/compiler/ops-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-06.out b/test/out/compiler/ops-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-07.out b/test/out/compiler/ops-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-07.out
@@ -0,0 +1,199 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Not (Literal (Boolean True)))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Not (Literal (Boolean False)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (And (Literal (Boolean False)) (Literal (Boolean False)))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (And (Literal (Boolean False)) (Literal (Boolean True)))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (And (Literal (Boolean True)) (Literal (Boolean False)))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (And (Literal (Boolean True)) (Literal (Boolean True)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Or (Literal (Boolean False)) (Literal (Boolean False)))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Or (Literal (Boolean False)) (Literal (Boolean True)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Or (Literal (Boolean True)) (Literal (Boolean False)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Or (Literal (Boolean True)) (Literal (Boolean True)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (And (Literal (Boolean False)) (Ident (Identifier "dont-care")))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-07.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Or (Literal (Boolean True)) (Ident (Identifier "dont-care")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-08.out b/test/out/compiler/ops-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-08.out
@@ -0,0 +1,320 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Equals (Literal (Int 1)) (Literal (String "hi")))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Equals (Literal (Int 1)) (Literal (Float 1.0)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Literal (Numeric 30.0 Percent))
+              (Plus (Literal (Numeric 30.0 Percent)) (Literal (Numeric 0.0 Cm))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Literal (Numeric 1.0 In))
+              (Plus (Literal (Numeric 0.0 Percent)) (Literal (Numeric 72.0 Pt))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Literal (Numeric 30.0 Percent))
+              (Plus (Literal (Numeric 30.0 Percent)) (Literal (Numeric 1.0 Cm))))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Literal (String "ab"))
+              (Plus (Literal (String "a")) (Literal (String "b"))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Equals (Array []) (Array [ Literal (Int 1) ]))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+              (Plus
+                 (Array [ Literal (Int 1) , Literal (Float 2.0) ])
+                 (Array [ Literal (Int 3) ])))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals (Dict []) (Dict [ ( Identifier "a" , Literal (Int 1) ) ]))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Dict
+                 [ ( Identifier "a"
+                   , Minus (Literal (Int 2)) (Literal (Float 1.0))
+                   )
+                 , ( Identifier "b" , Literal (Int 2) )
+                 ])
+              (Dict
+                 [ ( Identifier "b" , Literal (Int 2) )
+                 , ( Identifier "a" , Literal (Int 1) )
+                 ]))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Not (Equals (Literal (String "a")) (Literal (String "a"))))
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals (Ident (Identifier "test")) (Ident (Identifier "test")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (FuncExpr [] (Block (CodeBlock [])))
+              (FuncExpr [] (Block (CodeBlock []))))
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 22 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "t"))) (Block (Content [ Text "a" ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 23 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals (Ident (Identifier "t")) (Ident (Identifier "t")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 24 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Equals (Block (Content [])) (Block (Content [])))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 25 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Block (Content [ Text "a" ])) (Block (Content [ Text "a" ])))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 26 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (FuncCall (Ident (Identifier "grid")) [ BlockArg [ Text "a" ] ])
+              (FuncCall (Ident (Identifier "grid")) [ BlockArg [ Text "a" ] ]))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-08.typ"
+    ( line 27 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (FuncCall (Ident (Identifier "grid")) [ BlockArg [ Text "a" ] ])
+              (FuncCall (Ident (Identifier "grid")) [ BlockArg [ Text "b" ] ]))
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [❌(]), 
+  text(body: [false]), 
+  text(body: [ /= ]), 
+  text(body: [true]), 
+  text(body: [)]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-09.out b/test/out/compiler/ops-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-09.out
@@ -0,0 +1,181 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (LessThan
+              (Times (Literal (Int 13)) (Literal (Int 3)))
+              (Times (Literal (Int 14)) (Literal (Int 4))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (LessThan (Literal (Int 5)) (Literal (Int 10)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (GreaterThan (Literal (Int 5)) (Literal (Int 5)))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (LessThanOrEqual (Literal (Int 5)) (Literal (Int 5)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (LessThanOrEqual (Literal (Int 5)) (Literal (Int 4)))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (LessThan (Literal (Numeric 45.0 Deg)) (Literal (Numeric 1.0 Rad)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (LessThan
+              (Literal (Numeric 10.0 Percent)) (Literal (Numeric 20.0 Percent)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (LessThan
+              (Literal (Numeric 50.0 Percent))
+              (Plus (Literal (Numeric 40.0 Percent)) (Literal (Numeric 0.0 Pt))))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (LessThan
+              (Plus (Literal (Numeric 40.0 Percent)) (Literal (Numeric 0.0 Pt)))
+              (Plus (Literal (Numeric 50.0 Percent)) (Literal (Numeric 0.0 Pt))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-09.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (LessThan (Literal (Numeric 1.0 Em)) (Literal (Numeric 2.0 Em)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-10.out b/test/out/compiler/ops-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-10.out
@@ -0,0 +1,194 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-10.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-10.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 4 , column 2 )
+    (Let (BasicBind (Just (Identifier "x"))) (Literal (Int 0)))
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 5 , column 2 )
+    (Assign
+       (Binding (BasicBind (Just (Identifier "x")))) (Literal (Int 10)))
+, Space
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 5 , column 18 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Int 10))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 6 , column 2 )
+    (Assign
+       (Ident (Identifier "x"))
+       (Minus (Ident (Identifier "x")) (Literal (Int 5))))
+, Space
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 6 , column 18 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Int 5))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 7 , column 2 )
+    (Assign
+       (Ident (Identifier "x"))
+       (Plus (Ident (Identifier "x")) (Literal (Int 1))))
+, Space
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 7 , column 18 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Int 6))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 8 , column 2 )
+    (Assign
+       (Ident (Identifier "x"))
+       (Times (Ident (Identifier "x")) (Ident (Identifier "x"))))
+, Space
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 8 , column 18 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Int 36))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 9 , column 2 )
+    (Assign
+       (Ident (Identifier "x"))
+       (Divided (Ident (Identifier "x")) (Literal (Float 2.0))))
+, Space
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 9 , column 18 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Float 18.0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 10 , column 2 )
+    (Assign
+       (Binding (BasicBind (Just (Identifier "x"))))
+       (Literal (String "some")))
+, Space
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 10 , column 18 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (String "some"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 11 , column 2 )
+    (Assign
+       (Ident (Identifier "x"))
+       (Plus (Ident (Identifier "x")) (Literal (String "thing"))))
+, Space
+, Code
+    "test/typ/compiler/ops-10.typ"
+    ( line 11 , column 18 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (String "something"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-11.out b/test/out/compiler/ops-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-11.out
@@ -0,0 +1,3 @@
+"test/typ/compiler/ops-11.typ" (line 25, column 5):
+unexpected ":"
+expecting "//", "/*", operator or ")"
diff --git a/test/out/compiler/ops-12.out b/test/out/compiler/ops-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-13.out b/test/out/compiler/ops-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-13.out
@@ -0,0 +1,208 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-13.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-13.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection (Literal (String "hi")) (Literal (String "worship")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (String "hi"))
+              (Array
+                 [ Literal (String "we")
+                 , Literal (String "hi")
+                 , Literal (String "bye")
+                 ]))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (String "Hey")) (Literal (String "abHeyCd")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (String "Hey")) (Literal (String "abheyCd")))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (Int 5))
+              (FuncCall
+                 (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ]))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (Int 12))
+              (FuncCall
+                 (Ident (Identifier "range")) [ NormalArg (Literal (Int 10)) ]))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (InCollection (Literal (String "")) (Array []))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (String "key"))
+              (Dict [ ( Identifier "key" , Literal (String "value") ) ]))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (String "value"))
+              (Dict [ ( Identifier "key" , Literal (String "value") ) ]))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Not
+              (InCollection
+                 (Literal (String "Hey")) (Literal (String "abheyCd"))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-13.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Not
+              (InCollection (Literal (String "a")) (Literal (String "abc"))))
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-14.out b/test/out/compiler/ops-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-14.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-15.out b/test/out/compiler/ops-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-15.out
@@ -0,0 +1,207 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-15.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-15.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 5 , column 2 )
+    (LetFunc
+       (Identifier "add")
+       [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+       (Plus (Ident (Identifier "x")) (Ident (Identifier "y"))))
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "with")) (Ident (Identifier "add")))
+                 [ NormalArg (Literal (Int 2)) ])
+              [ NormalArg (Literal (Int 3)) ])
+       , NormalArg (Literal (Int 5))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "with"))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "with")) (Ident (Identifier "add")))
+                       [ NormalArg (Literal (Int 2)) ]))
+                 [ NormalArg (Literal (Int 3)) ])
+              [])
+       , NormalArg (Literal (Int 5))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "with")) (Ident (Identifier "add")))
+                 [ NormalArg (Literal (Int 2)) ])
+              [ NormalArg (Literal (Int 4)) ])
+       , NormalArg (Literal (Int 6))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "with"))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "with")) (Ident (Identifier "add")))
+                       [ NormalArg (Literal (Int 2)) ]))
+                 [ NormalArg (Literal (Int 3)) ])
+              [])
+       , NormalArg (Literal (Int 5))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 12 , column 2 )
+    (LetFunc
+       (Identifier "inc")
+       [ NormalParam (Identifier "x")
+       , DefaultParam (Identifier "y") (Literal (Int 1))
+       ]
+       (Plus (Ident (Identifier "x")) (Ident (Identifier "y"))))
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "inc")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 15 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "inc2")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "inc")))
+          [ KeyValArg (Identifier "y") (Literal (Int 2)) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "inc2")) [ NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (Int 4))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-15.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "inc2"))
+              [ NormalArg (Literal (Int 2))
+              , KeyValArg (Identifier "y") (Literal (Int 4))
+              ])
+       , NormalArg (Literal (Int 6))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-assoc-00.out b/test/out/compiler/ops-assoc-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-assoc-00.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-assoc-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-assoc-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-assoc-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-assoc-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Divided
+                 (Divided (Literal (Int 10)) (Literal (Int 2))) (Literal (Int 2)))
+              (Divided
+                 (Divided (Literal (Int 10)) (Literal (Int 2))) (Literal (Int 2))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-assoc-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Divided
+                 (Divided (Literal (Int 10)) (Literal (Int 2))) (Literal (Int 2)))
+              (Divided
+                 (Literal (Int 10)) (Divided (Literal (Int 2)) (Literal (Int 2)))))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-assoc-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Times
+              (Divided (Literal (Int 1)) (Literal (Int 2))) (Literal (Int 3)))
+       , NormalArg (Literal (Float 1.5))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-assoc-01.out b/test/out/compiler/ops-assoc-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-assoc-01.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-assoc-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-assoc-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-assoc-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "{"
+, SoftBreak
+, Text "let"
+, Space
+, Text "x"
+, Space
+, Text "="
+, Space
+, Text "1"
+, SoftBreak
+, Text "let"
+, Space
+, Text "y"
+, Space
+, Text "="
+, Space
+, Text "2"
+, SoftBreak
+, Text "x"
+, Space
+, Text "="
+, Space
+, Text "y"
+, Space
+, Text "="
+, Space
+, Quote '"'
+, Text "ok"
+, Quote '"'
+, SoftBreak
+, Text "test"
+, Text "("
+, Text "x,"
+, Space
+, Text "none)"
+, SoftBreak
+, Text "test"
+, Text "("
+, Text "y,"
+, Space
+, Quote '"'
+, Text "ok"
+, Quote '"'
+, Text ")"
+, SoftBreak
+, Text "}"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [{
+let x = 1
+let y = 2
+x = y = “ok”
+test(x, none)
+test(y, “ok”)
+}]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-invalid-00.out b/test/out/compiler/ops-invalid-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-00.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-01.out b/test/out/compiler/ops-invalid-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-02.out b/test/out/compiler/ops-invalid-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-03.out b/test/out/compiler/ops-invalid-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-04.out b/test/out/compiler/ops-invalid-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-05.out b/test/out/compiler/ops-invalid-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-06.out b/test/out/compiler/ops-invalid-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-07.out b/test/out/compiler/ops-invalid-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-08.out b/test/out/compiler/ops-invalid-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-09.out b/test/out/compiler/ops-invalid-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-10.out b/test/out/compiler/ops-invalid-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-11.out b/test/out/compiler/ops-invalid-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-12.out b/test/out/compiler/ops-invalid-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-13.out b/test/out/compiler/ops-invalid-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-13.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-14.out b/test/out/compiler/ops-invalid-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-14.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-15.out b/test/out/compiler/ops-invalid-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-15.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-16.out b/test/out/compiler/ops-invalid-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-16.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-17.out b/test/out/compiler/ops-invalid-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-17.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-18.out b/test/out/compiler/ops-invalid-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-18.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-19.out b/test/out/compiler/ops-invalid-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-19.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-20.out b/test/out/compiler/ops-invalid-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-20.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-21.out b/test/out/compiler/ops-invalid-21.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-21.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-22.out b/test/out/compiler/ops-invalid-22.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-22.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-23.out b/test/out/compiler/ops-invalid-23.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-23.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-24.out b/test/out/compiler/ops-invalid-24.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-24.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-25.out b/test/out/compiler/ops-invalid-25.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-25.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-26.out b/test/out/compiler/ops-invalid-26.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-26.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-27.out b/test/out/compiler/ops-invalid-27.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-27.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-28.out b/test/out/compiler/ops-invalid-28.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-28.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-invalid-29.out b/test/out/compiler/ops-invalid-29.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-invalid-29.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-invalid-29.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-invalid-29.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-invalid-29.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/ops-invalid-29.typ"
+    ( line 4 , column 2 )
+    (Let (BasicBind (Just (Identifier "rect"))) (Literal (String "")))
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-invalid-29.typ"
+    ( line 5 , column 2 )
+    (Assign
+       (Binding (BasicBind (Just (Identifier "rect"))))
+       (Literal (String "hi")))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-prec-00.out b/test/out/compiler/ops-prec-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-prec-00.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-prec-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-prec-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-prec-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-prec-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Plus
+              (Literal (Int 1))
+              (Times (Literal (Int 2)) (Negated (Literal (Int 3)))))
+       , NormalArg (Negated (Literal (Int 5)))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-prec-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Literal (Int 3)) (Minus (Literal (Int 5)) (Literal (Int 2))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-prec-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (And
+              (Equals (Literal (String "a")) (Literal (String "a")))
+              (LessThan (Literal (Int 2)) (Literal (Int 3))))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/ops-prec-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Not (Equals (Literal (String "b")) (Literal (String "b"))))
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-prec-01.out b/test/out/compiler/ops-prec-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-prec-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-prec-02.out b/test/out/compiler/ops-prec-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-prec-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/ops-prec-03.out b/test/out/compiler/ops-prec-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-prec-03.out
@@ -0,0 +1,61 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/ops-prec-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/ops-prec-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/ops-prec-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/ops-prec-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Not
+              (InCollection
+                 (Negated (Literal (Int 1)))
+                 (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/ops-prec-04.out b/test/out/compiler/ops-prec-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/ops-prec-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/recursion-00.out b/test/out/compiler/recursion-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/recursion-00.out
@@ -0,0 +1,87 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/recursion-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/recursion-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/recursion-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/recursion-00.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "fib")
+       [ NormalParam (Identifier "n") ]
+       (Block
+          (CodeBlock
+             [ If
+                 [ ( LessThanOrEqual (Ident (Identifier "n")) (Literal (Int 2))
+                   , Block (CodeBlock [ Literal (Int 1) ])
+                   )
+                 , ( Literal (Boolean True)
+                   , Block
+                       (CodeBlock
+                          [ Plus
+                              (FuncCall
+                                 (Ident (Identifier "fib"))
+                                 [ NormalArg (Minus (Ident (Identifier "n")) (Literal (Int 1))) ])
+                              (FuncCall
+                                 (Ident (Identifier "fib"))
+                                 [ NormalArg (Minus (Ident (Identifier "n")) (Literal (Int 2))) ])
+                          ])
+                   )
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/recursion-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "fib")) [ NormalArg (Literal (Int 10)) ])
+       , NormalArg (Literal (Int 55))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/recursion-01.out b/test/out/compiler/recursion-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/recursion-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/recursion-02.out b/test/out/compiler/recursion-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/recursion-02.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/recursion-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/recursion-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/recursion-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/recursion-02.typ"
+    ( line 3 , column 2 )
+    (Let (BasicBind (Just (Identifier "f"))) (Literal (Int 10)))
+, SoftBreak
+, Code
+    "test/typ/compiler/recursion-02.typ"
+    ( line 4 , column 2 )
+    (LetFunc (Identifier "f") [] (Ident (Identifier "f")))
+, SoftBreak
+, Code
+    "test/typ/compiler/recursion-02.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (FuncCall (Ident (Identifier "f")) []) ])
+       , NormalArg (Literal (String "function"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/recursion-03.out b/test/out/compiler/recursion-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/recursion-03.out
@@ -0,0 +1,76 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/recursion-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/recursion-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/recursion-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/recursion-03.typ"
+    ( line 3 , column 2 )
+    (Let (BasicBind (Just (Identifier "f"))) (Literal (Int 10)))
+, SoftBreak
+, Code
+    "test/typ/compiler/recursion-03.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "f")))
+       (FuncExpr [] (Ident (Identifier "f"))))
+, SoftBreak
+, Code
+    "test/typ/compiler/recursion-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (FuncCall (Ident (Identifier "f")) []) ])
+       , NormalArg (Literal (String "integer"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/recursion-04.out b/test/out/compiler/recursion-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/recursion-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/recursion-05.out b/test/out/compiler/recursion-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/recursion-05.out
@@ -0,0 +1,86 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/recursion-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/recursion-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/recursion-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/recursion-05.typ"
+    ( line 2 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "x") ]
+       (Literal (String "hello")))
+, SoftBreak
+, Code
+    "test/typ/compiler/recursion-05.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "x") ]
+       (If
+          [ ( Not (Equals (Ident (Identifier "x")) (Literal None))
+            , Block
+                (CodeBlock
+                   [ FuncCall (Ident (Identifier "f")) [ NormalArg (Literal None) ] ])
+            )
+          , ( Literal (Boolean True)
+            , Block (CodeBlock [ Literal (String "world") ])
+            )
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/recursion-05.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall (Ident (Identifier "f")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (String "world"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/repr-00.out b/test/out/compiler/repr-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/repr-00.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/repr-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/repr-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/repr-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/repr-00.typ"
+    ( line 3 , column 2 )
+    (Literal Auto)
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-00.typ"
+    ( line 4 , column 2 )
+    (Literal None)
+, Space
+, Text "("
+, Text "empty)"
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-00.typ"
+    ( line 5 , column 2 )
+    (Literal (Boolean True))
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-00.typ"
+    ( line 6 , column 2 )
+    (Literal (Boolean False))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [auto]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [ (empty) ]), 
+  linebreak(), 
+  text(body: [true]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [false]), 
+  parbreak() }
diff --git a/test/out/compiler/repr-01.out b/test/out/compiler/repr-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/repr-01.out
@@ -0,0 +1,156 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/repr-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/repr-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 3 , column 2 )
+    (Literal (Int 1))
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 4 , column 2 )
+    (Literal (Float 1.0e-4))
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 5 , column 2 )
+    (Literal (Float 3.15))
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 6 , column 2 )
+    (Literal (Float 1.0e-10))
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 7 , column 2 )
+    (Literal (Numeric 50.368 Percent))
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 8 , column 2 )
+    (Literal (Numeric 1.2345e-6 Pt))
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 9 , column 2 )
+    (Literal (Numeric 4.5 Cm))
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 10 , column 2 )
+    (Literal (Numeric 120.0 Pt))
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 11 , column 2 )
+    (Literal (Numeric 2.5 Rad))
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 12 , column 2 )
+    (Literal (Numeric 45.0 Deg))
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 13 , column 2 )
+    (Literal (Numeric 1.7 Em))
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 14 , column 2 )
+    (Plus (Literal (Numeric 1.0 Cm)) (Literal (Numeric 0.0 Em)))
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 15 , column 2 )
+    (Plus (Literal (Numeric 2.0 Em)) (Literal (Numeric 10.0 Pt)))
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-01.typ"
+    ( line 16 , column 2 )
+    (Literal (Numeric 2.3 Fr))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [1]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [1.0e-4]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [3.15]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [1.0e-10]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [50%]), 
+  linebreak(), 
+  text(body: [1.2345e-6pt]), 
+  linebreak(), 
+  text(body: [4.5cm]), 
+  linebreak(), 
+  text(body: [120.0pt]), 
+  linebreak(), 
+  text(body: [143.2394487827058deg]), 
+  linebreak(), 
+  text(body: [45.0deg]), 
+  linebreak(), 
+  text(body: [1.7em]), 
+  linebreak(), 
+  text(body: [1.0cm]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [2.0em + 10.0pt]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [2.3fr]), 
+  parbreak() }
diff --git a/test/out/compiler/repr-02.out b/test/out/compiler/repr-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/repr-02.out
@@ -0,0 +1,157 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/repr-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/repr-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 0.8 Em)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rgb"))
+       [ NormalArg (Literal (String "f7a205")) ])
+, Space
+, HardBreak
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 5 , column 2 )
+    (Plus
+       (Literal (Numeric 2.0 Pt))
+       (FuncCall
+          (Ident (Identifier "rgb"))
+          [ NormalArg (Literal (String "f7a205")) ]))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "raw"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "repr")) [ NormalArg (Literal (String "hi")) ])
+       , KeyValArg (Identifier "lang") (Literal (String "typc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "repr"))
+       [ NormalArg (Literal (String "a\n[]\"\128640string")) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "raw"))
+       [ KeyValArg (Identifier "lang") (Literal (String "typc"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "repr")) [ BlockArg [ Strong [ Text "Hey" ] ] ])
+       ])
+, ParBreak
+, Comment
+, Text "Nothing"
+, SoftBreak
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 16 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "x") ]
+       (Ident (Identifier "x")))
+, SoftBreak
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 17 , column 2 )
+    (Ident (Identifier "f"))
+, SoftBreak
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 18 , column 2 )
+    (Ident (Identifier "rect"))
+, SoftBreak
+, Code
+    "test/typ/compiler/repr-02.typ"
+    ( line 19 , column 2 )
+    (FuncExpr [] (Literal None))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], size: 0.8em), 
+  text(body: [rgb(96%,63%,1%,100%)], 
+       size: 0.8em), 
+  text(body: [ ], size: 0.8em), 
+  linebreak(), 
+  text(body: [(thickness: 2.0pt,
+ color: rgb(96%,63%,1%,100%))], 
+       size: 0.8em), 
+  parbreak(), 
+  raw(lang: "typc", 
+      text: "\"hi\""), 
+  text(body: [
+], size: 0.8em), 
+  text(body: ["a\n[]\"🚀string"], 
+       size: 0.8em), 
+  parbreak(), 
+  raw(lang: "typc", 
+      text: "strong(body: text(body: [Hey], \n                  size: 0.8em))"), 
+  parbreak(), 
+  text(body: [Nothing
+], 
+       size: 0.8em), 
+  text(body: [
+], size: 0.8em), 
+  text(body: [
+], size: 0.8em), 
+  text(body: [
+], size: 0.8em), 
+  parbreak() }
diff --git a/test/out/compiler/return-00.out b/test/out/compiler/return-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/return-00.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/return-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/return-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/return-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/return-00.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "x") ]
+       (Block
+          (CodeBlock
+             [ Return (Just (Plus (Ident (Identifier "x")) (Literal (Int 1))))
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/return-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall (Ident (Identifier "f")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/return-01.out b/test/out/compiler/return-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/return-01.out
@@ -0,0 +1,112 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/return-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/return-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/return-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/return-01.typ"
+    ( line 4 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "x") ]
+       (Block
+          (CodeBlock
+             [ Literal (String "a")
+             , If
+                 [ ( Equals (Ident (Identifier "x")) (Literal (Int 0))
+                   , Block (CodeBlock [ Return (Just (Literal (String "b"))) ])
+                   )
+                 , ( Equals (Ident (Identifier "x")) (Literal (Int 1))
+                   , Block (CodeBlock [ Literal (String "c") ])
+                   )
+                 , ( Literal (Boolean True)
+                   , Block
+                       (CodeBlock
+                          [ Literal (String "d") , Return Nothing , Literal (String "e") ])
+                   )
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/return-01.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall (Ident (Identifier "f")) [ NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (String "b"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/return-01.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall (Ident (Identifier "f")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (String "ac"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/return-01.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall (Ident (Identifier "f")) [ NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (String "ad"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/return-02.out b/test/out/compiler/return-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/return-02.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/return-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/return-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/return-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/return-02.typ"
+    ( line 5 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ NormalParam (Identifier "text")
+       , DefaultParam (Identifier "caption") (Literal None)
+       ]
+       (Block
+          (CodeBlock
+             [ Ident (Identifier "text")
+             , If
+                 [ ( Equals (Ident (Identifier "caption")) (Literal None)
+                   , Block
+                       (Content
+                          [ Text "."
+                          , Code
+                              "test/typ/compiler/return-02.typ"
+                              ( line 7 , column 26 )
+                              (Return Nothing)
+                          ])
+                   )
+                 ]
+             , Block (Content [ Text "," , Space ])
+             , FuncCall
+                 (Ident (Identifier "emph"))
+                 [ NormalArg (Ident (Identifier "caption")) ]
+             , Block (Content [ Text "." ])
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/return-02.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "f"))
+       [ KeyValArg
+           (Identifier "caption")
+           (Block (Content [ Text "with" , Space , Text "caption" ]))
+       , BlockArg [ Text "My" , Space , Text "figure" ]
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/return-02.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "f"))
+       [ BlockArg
+           [ Text "My" , Space , Text "other" , Space , Text "figure" ]
+       ])
+, ParBreak
+]
+"test/typ/compiler/return-02.typ" (line 13, column 2):
+unexpected end of input
+text is not an element function
diff --git a/test/out/compiler/return-03.out b/test/out/compiler/return-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/return-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/return-04.out b/test/out/compiler/return-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/return-04.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/return-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/return-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/return-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/return-04.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "sum")
+       [ SinkParam (Just (Identifier "args")) ]
+       (Block
+          (CodeBlock
+             [ Let (BasicBind (Just (Identifier "s"))) (Literal (Int 0))
+             , For
+                 (BasicBind (Just (Identifier "v")))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "pos")) (Ident (Identifier "args")))
+                    [])
+                 (Block
+                    (CodeBlock
+                       [ Assign
+                           (Ident (Identifier "s"))
+                           (Plus (Ident (Identifier "s")) (Ident (Identifier "v")))
+                       ]))
+             , Ident (Identifier "s")
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/return-04.typ"
+    ( line 11 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       []
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "sum"))
+                 [ SpreadArg (Return Nothing)
+                 , NormalArg (Literal (Int 1))
+                 , NormalArg (Literal (Int 2))
+                 , NormalArg (Literal (Int 3))
+                 ]
+             , Literal (String "nope")
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/return-04.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (FuncCall (Ident (Identifier "f")) [])
+       , NormalArg (Literal (Int 6))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/return-05.out b/test/out/compiler/return-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/return-05.out
@@ -0,0 +1,97 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/return-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/return-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/return-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/return-05.typ"
+    ( line 3 , column 2 )
+    (Let (BasicBind (Just (Identifier "x"))) (Literal (Int 3)))
+, SoftBreak
+, Code
+    "test/typ/compiler/return-05.typ"
+    ( line 4 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       []
+       (Block
+          (Content
+             [ SoftBreak
+             , Text "Hello"
+             , Space
+             , Text "\128512"
+             , SoftBreak
+             , Code
+                 "test/typ/compiler/return-05.typ"
+                 ( line 6 , column 4 )
+                 (Return (Just (Literal (String "nope"))))
+             , SoftBreak
+             , Text "World"
+             , ParBreak
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/return-05.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (FuncCall (Ident (Identifier "f")) [])
+       , NormalArg (Literal (String "nope"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [❌(]), 
+  text(body: [{ text(body: [
+Hello 😀
+]), 
+  text(body: [nope]), 
+  text(body: [
+World]), 
+  parbreak() }]), 
+  text(body: [ /= ]), 
+  text(body: ["nope"]), 
+  text(body: [)]), 
+  parbreak() }
diff --git a/test/out/compiler/set-00.out b/test/out/compiler/set-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-00.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/set-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/set-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/set-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/set-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "x")))
+       (Block (Content [ Text "World" ])))
+, SoftBreak
+, Text "Hello"
+, Space
+, Strong
+    [ Code
+        "test/typ/compiler/set-00.typ"
+        ( line 4 , column 9 )
+        (Ident (Identifier "x"))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Hello ]), 
+  strong(body: text(body: [World])), 
+  parbreak() }
diff --git a/test/out/compiler/set-01.out b/test/out/compiler/set-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-01.out
@@ -0,0 +1,113 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/set-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/set-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/set-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/set-01.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "fruit")))
+       (Block
+          (Content
+             [ SoftBreak
+             , BulletListItem [ Text "Apple" ]
+             , SoftBreak
+             , BulletListItem [ Text "Orange" ]
+             , SoftBreak
+             , Code
+                 "test/typ/compiler/set-01.typ"
+                 ( line 6 , column 4 )
+                 (FuncCall
+                    (Ident (Identifier "list"))
+                    [ KeyValArg (Identifier "body-indent") (Literal (Numeric 20.0 Pt))
+                    , BlockArg [ Text "Pear" ]
+                    ])
+             , ParBreak
+             ])))
+, ParBreak
+, BulletListItem [ Text "Fruit" ]
+, SoftBreak
+, Code
+    "test/typ/compiler/set-01.typ"
+    ( line 10 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/compiler/set-01.typ"
+              ( line 10 , column 4 )
+              (Set
+                 (Ident (Identifier "list"))
+                 [ KeyValArg (Identifier "indent") (Literal (Numeric 10.0 Pt)) ])
+          , SoftBreak
+          , Code
+              "test/typ/compiler/set-01.typ"
+              ( line 11 , column 3 )
+              (Ident (Identifier "fruit"))
+          ]))
+, SoftBreak
+, BulletListItem
+    [ Text "No"
+    , Space
+    , Text "more"
+    , Space
+    , Text "fruit"
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  list(children: (text(body: [Fruit]))), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  list(children: (text(body: [Apple]), 
+                  text(body: [Orange]))), 
+  list(body-indent: 20.0pt, 
+       children: (text(body: [Pear]))), 
+  parbreak(), 
+  text(body: [
+]), 
+  list(children: ({ text(body: [No more fruit]), 
+                    parbreak() }), 
+       indent: 10.0pt) }
diff --git a/test/out/compiler/set-02.out b/test/out/compiler/set-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-02.out
@@ -0,0 +1,115 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/set-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/set-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/set-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/set-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 4.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/set-02.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "style") (Literal (String "italic"))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/set-02.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "x")))
+       (Block
+          (Content
+             [ Text "And"
+             , Space
+             , Text "the"
+             , Space
+             , Text "red"
+             , Space
+             , Code
+                 "test/typ/compiler/set-02.typ"
+                 ( line 6 , column 24 )
+                 (FuncCall (Ident (Identifier "parbreak")) [])
+             , Space
+             , Text "lay"
+             , Space
+             , Text "silent!"
+             ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/set-02.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , NormalArg (Ident (Identifier "x"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       fill: rgb(13%,61%,67%,100%), 
+       style: "italic"), 
+  text(body: [
+], 
+       fill: rgb(13%,61%,67%,100%), 
+       style: "italic"), 
+  text(body: { text(body: [And the red ], 
+                    fill: rgb(13%,61%,67%,100%), 
+                    style: "italic"), 
+               parbreak(), 
+               text(body: [ lay silent!], 
+                    fill: rgb(13%,61%,67%,100%), 
+                    style: "italic") }, 
+       fill: rgb(100%,25%,21%,100%), 
+       style: "italic"), 
+  parbreak() }
diff --git a/test/out/compiler/set-03.out b/test/out/compiler/set-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-03.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/set-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/set-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/set-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/set-03.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ If
+              [ ( Literal (Boolean True)
+                , Block
+                    (CodeBlock
+                       [ Set
+                           (Ident (Identifier "text"))
+                           [ NormalArg (Ident (Identifier "blue")) ]
+                       , Block (Content [ Text "Blue" , Space ])
+                       ])
+                )
+              ]
+          , Block (Content [ Text "Not" , Space , Text "blue" ])
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Blue ], 
+       color: rgb(0%,45%,85%,100%)), 
+  text(body: [Not blue]), 
+  parbreak() }
diff --git a/test/out/compiler/set-04.out b/test/out/compiler/set-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-04.out
@@ -0,0 +1,103 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/set-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/set-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/set-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/set-04.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "choice")))
+       (Array
+          [ Literal (String "monkey.svg")
+          , Literal (String "rhino.png")
+          , Literal (String "tiger.jpg")
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/set-04.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "enum"))
+       [ KeyValArg
+           (Identifier "numbering")
+           (FuncExpr
+              [ NormalParam (Identifier "n") ]
+              (Block
+                 (CodeBlock
+                    [ Let
+                        (BasicBind (Just (Identifier "path")))
+                        (Plus
+                           (Literal (String "/"))
+                           (FuncCall
+                              (FieldAccess
+                                 (Ident (Identifier "at")) (Ident (Identifier "choice")))
+                              [ NormalArg (Minus (Ident (Identifier "n")) (Literal (Int 1))) ]))
+                    , FuncCall
+                        (Ident (Identifier "move"))
+                        [ KeyValArg (Identifier "dy") (Negated (Literal (Numeric 0.15 Em)))
+                        , NormalArg
+                            (FuncCall
+                               (Ident (Identifier "image"))
+                               [ NormalArg (Ident (Identifier "path"))
+                               , KeyValArg (Identifier "width") (Literal (Numeric 1.0 Em))
+                               , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+                               ])
+                        ]
+                    ])))
+       ])
+, ParBreak
+, EnumListItem Nothing [ Text "Monkey" ]
+, SoftBreak
+, EnumListItem Nothing [ Text "Rhino" ]
+, SoftBreak
+, EnumListItem Nothing [ Text "Tiger" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  enum(children: (text(body: [Monkey]), 
+                  text(body: [Rhino]), 
+                  { text(body: [Tiger]), 
+                    parbreak() }), 
+       numbering: ) }
diff --git a/test/out/compiler/set-05.out b/test/out/compiler/set-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-05.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/set-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/set-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/set-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/set-05.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "ref")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals
+                          (FieldAccess
+                             (Ident (Identifier "target")) (Ident (Identifier "it")))
+                          (Label "unknown")
+                      , Set
+                          (Ident (Identifier "text"))
+                          [ NormalArg (Ident (Identifier "red")) ]
+                      )
+                    ]
+                , Plus
+                    (Literal (String "@"))
+                    (FuncCall
+                       (Ident (Identifier "str"))
+                       [ NormalArg
+                           (FieldAccess
+                              (Ident (Identifier "target")) (Ident (Identifier "it")))
+                       ])
+                ]))))
+, ParBreak
+, Ref "hello" (Literal Auto)
+, Space
+, Text "from"
+, Space
+, Text "the"
+, Space
+, Ref "unknown" (Literal Auto)
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [@]), 
+  text(body: [ from the ]), 
+  text(body: [@]), 
+  parbreak() }
diff --git a/test/out/compiler/set-06.out b/test/out/compiler/set-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/set-07.out b/test/out/compiler/set-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/set-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/shorthand-00.out b/test/out/compiler/shorthand-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/shorthand-00.out
@@ -0,0 +1,59 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/shorthand-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/shorthand-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/shorthand-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Text "The"
+, Space
+, Text "non"
+, Text "-"
+, Text "breaking"
+, Nbsp
+, Text "space"
+, Space
+, Text "does"
+, Space
+, Text "work"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+The non-breaking space does work.]), 
+  parbreak() }
diff --git a/test/out/compiler/shorthand-01.out b/test/out/compiler/shorthand-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/shorthand-01.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/shorthand-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/shorthand-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/shorthand-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/compiler/shorthand-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "New Computer Modern"))
+       ])
+, SoftBreak
+, Text "a"
+, Space
+, Text "b"
+, Space
+, HardBreak
+, Text "a"
+, Nbsp
+, Text "b"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+a b ], 
+       font: "New Computer Modern"), 
+  linebreak(), 
+  text(body: [a b], 
+       font: "New Computer Modern"), 
+  parbreak() }
diff --git a/test/out/compiler/shorthand-02.out b/test/out/compiler/shorthand-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/shorthand-02.out
@@ -0,0 +1,60 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/shorthand-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/shorthand-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/shorthand-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, BulletListItem
+    [ Text "En" , Space , Text "dash" , Text ":" , Space , EnDash ]
+, SoftBreak
+, BulletListItem
+    [ Text "Em"
+    , Space
+    , Text "dash"
+    , Text ":"
+    , Space
+    , EmDash
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  list(children: (text(body: [En dash: –]), 
+                  { text(body: [Em dash: —]), 
+                    parbreak() })) }
diff --git a/test/out/compiler/shorthand-03.out b/test/out/compiler/shorthand-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/shorthand-03.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/shorthand-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/shorthand-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/shorthand-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/shorthand-03.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "Roboto")) ])
+, SoftBreak
+, Text "A"
+, Ellipsis
+, Space
+, Text "vs"
+, Space
+, Code
+    "test/typ/compiler/shorthand-03.typ"
+    ( line 3 , column 10 )
+    (Literal (String "A..."))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+A… vs ], 
+       font: "Roboto"), 
+  text(body: [A...], 
+       font: "Roboto"), 
+  parbreak() }
diff --git a/test/out/compiler/show-bare-00.out b/test/out/compiler/show-bare-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-bare-00.out
@@ -0,0 +1,193 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-bare-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-bare-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-bare-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-bare-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 130.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/show-bare-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 0.7 Em)) ])
+, ParBreak
+, Code
+    "test/typ/compiler/show-bare-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/compiler/show-bare-00.typ"
+               ( line 6 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "text"))
+                  [ NormalArg (Literal (Numeric 1.3 Em))
+                  , BlockArg
+                      [ Strong
+                          [ Text "Essay" , Space , Text "on" , Space , Text "typography" ]
+                      ]
+                  ])
+           , Space
+           , HardBreak
+           , Text "T"
+           , Text "."
+           , Space
+           , Text "Ypst"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/show-bare-00.typ"
+    ( line 10 , column 2 )
+    (Show
+       Nothing
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "columns")))
+          [ NormalArg (Literal (Int 2)) ]))
+, SoftBreak
+, Text "Great"
+, Space
+, Text "typography"
+, Space
+, Text "is"
+, Space
+, Text "at"
+, Space
+, Text "the"
+, Space
+, Text "essence"
+, Space
+, Text "of"
+, Space
+, Text "great"
+, Space
+, Text "storytelling"
+, Text "."
+, Space
+, Text "It"
+, Space
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "medium"
+, Space
+, Text "that"
+, SoftBreak
+, Text "transports"
+, Space
+, Text "meaning"
+, Space
+, Text "from"
+, Space
+, Text "parchment"
+, Space
+, Text "to"
+, Space
+, Text "reader,"
+, Space
+, Text "the"
+, Space
+, Text "wave"
+, Space
+, Text "that"
+, Space
+, Text "sparks"
+, Space
+, Text "a"
+, Space
+, Text "flame"
+, SoftBreak
+, Text "in"
+, Space
+, Text "booklovers"
+, Space
+, Text "and"
+, Space
+, Text "the"
+, Space
+, Text "great"
+, Space
+, Text "fulfiller"
+, Space
+, Text "of"
+, Space
+, Text "human"
+, Space
+, Text "need"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  align(alignment: center, 
+        body: { text(body: [
+], 
+                     size: 0.7em), 
+                text(body: strong(body: text(body: [Essay on typography], 
+                                             size: 0.7em)), 
+                     size: 1.3em), 
+                text(body: [ ], size: 0.7em), 
+                linebreak(), 
+                text(body: [T. Ypst], 
+                     size: 0.7em), 
+                parbreak() }), 
+  parbreak(), 
+  columns(body: { text(body: [
+Great typography is at the essence of great storytelling. It is the medium that
+transports meaning from parchment to reader, the wave that sparks a flame
+in booklovers and the great fulfiller of human need.], 
+                       size: 0.7em), 
+                  parbreak() }, 
+          count: 2) }
diff --git a/test/out/compiler/show-bare-01.out b/test/out/compiler/show-bare-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-bare-01.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-bare-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-bare-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-bare-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Space
+, Code
+    "test/typ/compiler/show-bare-01.typ"
+    ( line 3 , column 4 )
+    (Block
+       (Content
+          [ Emph
+              [ Text "B"
+              , Space
+              , Code
+                  "test/typ/compiler/show-bare-01.typ"
+                  ( line 3 , column 9 )
+                  (Show
+                     Nothing
+                     (FuncExpr
+                        [ NormalParam (Identifier "c") ]
+                        (Block
+                           (Content
+                              [ Strong
+                                  [ Code
+                                      "test/typ/compiler/show-bare-01.typ"
+                                      ( line 3 , column 23 )
+                                      (Ident (Identifier "c"))
+                                  ]
+                              ]))))
+              , Space
+              , Text "C"
+              ]
+          ]))
+, Space
+, Text "D"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A ]), 
+  emph(body: { text(body: [B ]), 
+               strong(body: text(body: [ C])) }), 
+  text(body: [ D]), 
+  parbreak() }
diff --git a/test/out/compiler/show-bare-02.out b/test/out/compiler/show-bare-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-bare-02.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-bare-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-bare-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-bare-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-bare-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       , KeyValArg (Identifier "size") (Literal (Numeric 1.5 Em))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/show-bare-02.typ"
+    ( line 4 , column 2 )
+    (Show
+       Nothing
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "text")))
+          [ KeyValArg (Identifier "fill") (Ident (Identifier "red")) ]))
+, SoftBreak
+, Text "Forest"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       fill: rgb(13%,61%,67%,100%), 
+       size: 1.5em), 
+  text(body: { text(body: [
+Forest], 
+                    fill: rgb(13%,61%,67%,100%), 
+                    size: 1.5em), 
+               parbreak() }, 
+       fill: rgb(100%,25%,21%,100%)) }
diff --git a/test/out/compiler/show-bare-03.out b/test/out/compiler/show-bare-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-bare-03.out
@@ -0,0 +1,53 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-bare-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-bare-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-bare-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-bare-03.typ"
+    ( line 2 , column 2 )
+    (Show Nothing (Block (Content [ Text "Shown" ])))
+, SoftBreak
+, Text "Ignored"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Shown]) }
diff --git a/test/out/compiler/show-bare-04.out b/test/out/compiler/show-bare-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-bare-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-bare-05.out b/test/out/compiler/show-bare-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-bare-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-bare-06.out b/test/out/compiler/show-bare-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-bare-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-node-00.out b/test/out/compiler/show-node-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-00.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-node-00.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Plus
+             (Plus
+                (Literal (String "("))
+                (FuncCall
+                   (FieldAccess
+                      (Ident (Identifier "join"))
+                      (FuncCall
+                         (FieldAccess
+                            (Ident (Identifier "map"))
+                            (FieldAccess
+                               (Ident (Identifier "children")) (Ident (Identifier "it"))))
+                         [ NormalArg
+                             (FuncExpr
+                                [ NormalParam (Identifier "v") ]
+                                (FieldAccess (Ident (Identifier "body")) (Ident (Identifier "v"))))
+                         ]))
+                   [ NormalArg (Literal (String ", ")) ]))
+             (Literal (String ")")))))
+, ParBreak
+, BulletListItem
+    [ Text "A"
+    , SoftBreak
+    , BulletListItem [ Text "B" ]
+    , SoftBreak
+    , BulletListItem [ Text "C" ]
+    ]
+, SoftBreak
+, BulletListItem [ Text "D" ]
+, SoftBreak
+, BulletListItem [ Text "E" , ParBreak ]
+]
+"test/typ/compiler/show-node-00.typ" (line 3, column 2):
+unexpected end of input
+Content does not have a method "body" or FieldAccess requires a dictionary
diff --git a/test/out/compiler/show-node-01.out b/test/out/compiler/show-node-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-01.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-node-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (Block (Content [ Text "B" ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-node-01.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (Set
+          (Ident (Identifier "text"))
+          [ KeyValArg (Identifier "size") (Literal (Numeric 10.0 Pt))
+          , KeyValArg (Identifier "weight") (Literal (Int 400))
+          ]))
+, SoftBreak
+, Text "A"
+, Space
+, Code
+    "test/typ/compiler/show-node-01.typ"
+    ( line 5 , column 4 )
+    (Block (Content [ Heading 1 [ Text "Heading" ] ]))
+, Space
+, Text "C"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+A ]), 
+  heading(body: text(body: [Heading]), 
+          level: 1), 
+  text(body: [ C]), 
+  parbreak() }
diff --git a/test/out/compiler/show-node-02.out b/test/out/compiler/show-node-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-02.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-node-02.typ"
+    ( line 3 , column 2 )
+    (Show (Just (Ident (Identifier "heading"))) (Literal None))
+, ParBreak
+, Text "Where"
+, Space
+, Text "is"
+, SoftBreak
+, Heading
+    1
+    [ Text "There"
+    , Space
+    , Text "are"
+    , Space
+    , Text "no"
+    , Space
+    , Text "headings"
+    , Space
+    , Text "around"
+    , Space
+    , Text "here!"
+    ]
+, Text "my"
+, Space
+, Text "heading?"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Where is
+]), 
+  text(body: [my heading?]), 
+  parbreak() }
diff --git a/test/out/compiler/show-node-03.out b/test/out/compiler/show-node-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-03.out
@@ -0,0 +1,159 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-node-03.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (FuncCall
+             (Ident (Identifier "block"))
+             [ NormalArg
+                 (Block
+                    (CodeBlock
+                       [ Set
+                           (Ident (Identifier "text"))
+                           [ NormalArg (Literal (Numeric 10.0 Pt)) ]
+                       , FuncCall
+                           (Ident (Identifier "box"))
+                           [ NormalArg
+                               (FuncCall
+                                  (Ident (Identifier "move"))
+                                  [ KeyValArg (Identifier "dy") (Negated (Literal (Numeric 1.0 Pt)))
+                                  , BlockArg [ Text "\128214" ]
+                                  ])
+                           ]
+                       , FuncCall
+                           (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 5.0 Pt)) ]
+                       , If
+                           [ ( Equals
+                                 (FieldAccess
+                                    (Ident (Identifier "level")) (Ident (Identifier "it")))
+                                 (Literal (Int 1))
+                             , Block
+                                 (CodeBlock
+                                    [ FuncCall
+                                        (Ident (Identifier "underline"))
+                                        [ NormalArg
+                                            (FuncCall
+                                               (Ident (Identifier "text"))
+                                               [ NormalArg (Literal (Numeric 1.25 Em))
+                                               , NormalArg (Ident (Identifier "blue"))
+                                               , NormalArg
+                                                   (FieldAccess
+                                                      (Ident (Identifier "body"))
+                                                      (Ident (Identifier "it")))
+                                               ])
+                                        ]
+                                    ])
+                             )
+                           , ( Literal (Boolean True)
+                             , Block
+                                 (CodeBlock
+                                    [ FuncCall
+                                        (Ident (Identifier "text"))
+                                        [ NormalArg (Ident (Identifier "red"))
+                                        , NormalArg
+                                            (FieldAccess
+                                               (Ident (Identifier "body"))
+                                               (Ident (Identifier "it")))
+                                        ]
+                                    ])
+                             )
+                           ]
+                       ]))
+             ])))
+, ParBreak
+, Heading 1 [ Text "Task" , Space , Text "1" ]
+, Text "Some"
+, Space
+, Text "text"
+, Text "."
+, ParBreak
+, Heading 2 [ Text "Subtask" ]
+, Text "Some"
+, Space
+, Text "more"
+, Space
+, Text "text"
+, Text "."
+, ParBreak
+, Heading 1 [ Text "Task" , Space , Text "2" ]
+, Text "Another"
+, Space
+, Text "text"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  block(body: { box(body: move(body: text(body: [📖], 
+                                          size: 10.0pt), 
+                               dy: -1.0pt)), 
+                h(amount: 5.0pt), 
+                underline(body: text(body: text(body: [Task 1]), 
+                                     color: rgb(0%,45%,85%,100%), 
+                                     size: 1.25em)) }), 
+  text(body: [Some text.]), 
+  parbreak(), 
+  block(body: { box(body: move(body: text(body: [📖], 
+                                          size: 10.0pt), 
+                               dy: -1.0pt)), 
+                h(amount: 5.0pt), 
+                text(body: text(body: [Subtask]), 
+                     color: rgb(100%,25%,21%,100%), 
+                     size: 10.0pt) }), 
+  text(body: [Some more text.]), 
+  parbreak(), 
+  block(body: { box(body: move(body: text(body: [📖], 
+                                          size: 10.0pt), 
+                               dy: -1.0pt)), 
+                h(amount: 5.0pt), 
+                underline(body: text(body: text(body: [Task 2]), 
+                                     color: rgb(0%,45%,85%,100%), 
+                                     size: 1.25em)) }), 
+  text(body: [Another text.]), 
+  parbreak() }
diff --git a/test/out/compiler/show-node-04.out b/test/out/compiler/show-node-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-04.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-node-04.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ Set
+                    (Ident (Identifier "text"))
+                    [ NormalArg (Ident (Identifier "red")) ]
+                , Show
+                    (Just (Literal (String "ding")))
+                    (Block (Content [ Text "\128718" ]))
+                , FieldAccess (Ident (Identifier "body")) (Ident (Identifier "it"))
+                ]))))
+, ParBreak
+, Heading 1 [ Text "Heading" ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Heading]) }
diff --git a/test/out/compiler/show-node-05.out b/test/out/compiler/show-node-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-05.out
@@ -0,0 +1,85 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-node-05.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "world")))
+              (Block (Content [ Space , Text "World" , Space ]))
+          , Show (Just (Literal (String "W"))) (Ident (Identifier "strong"))
+          , Ident (Identifier "world")
+          , Block
+              (CodeBlock
+                 [ Set
+                     (Ident (Identifier "text"))
+                     [ NormalArg (Ident (Identifier "blue")) ]
+                 , Show
+                     Nothing
+                     (FuncExpr
+                        [ NormalParam (Identifier "it") ]
+                        (Block
+                           (CodeBlock
+                              [ Show (Just (Literal (String "o"))) (Literal (String "\216"))
+                              , Ident (Identifier "it")
+                              ])))
+                 , Ident (Identifier "world")
+                 ])
+          , Ident (Identifier "world")
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: { [ ], 
+               strong(body: [W]), 
+               [orld ] }), 
+  parbreak(), 
+  text(body: { [ ], 
+               strong(body: [W]), 
+               [orld ] }), 
+  text(body: { [ ], 
+               strong(body: [W]), 
+               [orld ] }) }
diff --git a/test/out/compiler/show-node-06.out b/test/out/compiler/show-node-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-06.out
@@ -0,0 +1,56 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-node-06.typ"
+    ( line 2 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (Block (Content [ Text "1234" ])))
+, SoftBreak
+, Heading 1 [ Text "Heading" ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [1234]) }
diff --git a/test/out/compiler/show-node-07.out b/test/out/compiler/show-node-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-node-08.out b/test/out/compiler/show-node-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-08.out
@@ -0,0 +1,55 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-node-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-node-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-node-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-node-08.typ"
+    ( line 2 , column 2 )
+    (Show (Just (Ident (Identifier "text"))) (Literal None))
+, SoftBreak
+, Text "Hey"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Hey]), 
+  parbreak() }
diff --git a/test/out/compiler/show-node-09.out b/test/out/compiler/show-node-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-node-10.out b/test/out/compiler/show-node-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-node-11.out b/test/out/compiler/show-node-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-node-12.out b/test/out/compiler/show-node-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-node-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-recursive-00.out b/test/out/compiler/show-recursive-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-recursive-00.out
@@ -0,0 +1,59 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-recursive-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-recursive-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-recursive-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-recursive-00.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ] (Ident (Identifier "it"))))
+, SoftBreak
+, Heading 1 [ Text "Heading" ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  heading(body: text(body: [Heading]), 
+          level: 1) }
diff --git a/test/out/compiler/show-recursive-01.out b/test/out/compiler/show-recursive-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-recursive-01.out
@@ -0,0 +1,86 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-recursive-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-recursive-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-recursive-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-recursive-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "scale")))
+          [ KeyValArg (Identifier "origin") (Ident (Identifier "left"))
+          , KeyValArg (Identifier "x") (Literal (Numeric 80.0 Percent))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-recursive-01.typ"
+    ( line 4 , column 2 )
+    (Show (Just (Ident (Identifier "heading"))) (Block (Content [])))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-recursive-01.typ"
+    ( line 5 , column 2 )
+    (Show (Just (Ident (Identifier "enum"))) (Block (Content [])))
+, SoftBreak
+, BulletListItem [ Text "Actual" ]
+, SoftBreak
+, BulletListItem [ Text "Tight" ]
+, SoftBreak
+, BulletListItem [ Text "List" ]
+, SoftBreak
+, Heading 1 [ Text "Nope" ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  scale(body: list(children: (text(body: [Actual]), 
+                              text(body: [Tight]), 
+                              text(body: [List]))), 
+        origin: left, 
+        x: 80%) }
diff --git a/test/out/compiler/show-recursive-02.out b/test/out/compiler/show-recursive-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-recursive-02.out
@@ -0,0 +1,123 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-recursive-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-recursive-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-recursive-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-recursive-02.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "starwars")
+       [ NormalParam (Identifier "body") ]
+       (Block
+          (CodeBlock
+             [ Show
+                 (Just (Ident (Identifier "list")))
+                 (FuncExpr
+                    [ NormalParam (Identifier "it") ]
+                    (FuncCall
+                       (Ident (Identifier "block"))
+                       [ NormalArg
+                           (Block
+                              (CodeBlock
+                                 [ FuncCall
+                                     (Ident (Identifier "stack"))
+                                     [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+                                     , NormalArg
+                                         (FuncCall
+                                            (Ident (Identifier "text"))
+                                            [ NormalArg (Ident (Identifier "red"))
+                                            , NormalArg (Ident (Identifier "it"))
+                                            ])
+                                     , NormalArg (Literal (Numeric 1.0 Fr))
+                                     , NormalArg
+                                         (FuncCall
+                                            (Ident (Identifier "scale"))
+                                            [ KeyValArg
+                                                (Identifier "x")
+                                                (Negated (Literal (Numeric 100.0 Percent)))
+                                            , NormalArg
+                                                (FuncCall
+                                                   (Ident (Identifier "text"))
+                                                   [ NormalArg (Ident (Identifier "blue"))
+                                                   , NormalArg (Ident (Identifier "it"))
+                                                   ])
+                                            ])
+                                     ]
+                                 ]))
+                       ]))
+             , Ident (Identifier "body")
+             ])))
+, ParBreak
+, BulletListItem
+    [ Text "Normal" , Space , Text "list" , SoftBreak ]
+, SoftBreak
+, Code
+    "test/typ/compiler/show-recursive-02.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "starwars"))
+       [ BlockArg
+           [ SoftBreak
+           , BulletListItem [ Text "Star" ]
+           , SoftBreak
+           , BulletListItem [ Text "Wars" ]
+           , SoftBreak
+           , BulletListItem [ Text "List" , ParBreak ]
+           ]
+       ])
+, ParBreak
+, BulletListItem [ Text "Normal" , Space , Text "list" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  list(children: (text(body: [Normal list
+]))), 
+  text(body: [
+]), 
+  list(children: (text(body: [Star]), 
+                  text(body: [Wars]), 
+                  { text(body: [List]), 
+                    parbreak() })), 
+  parbreak(), 
+  list(children: ({ text(body: [Normal list]), 
+                    parbreak() })) }
diff --git a/test/out/compiler/show-recursive-03.out b/test/out/compiler/show-recursive-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-recursive-03.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-recursive-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-recursive-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-recursive-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-recursive-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/show-recursive-03.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "rect")))
+          [ KeyValArg (Identifier "stroke") (Ident (Identifier "blue")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-recursive-03.typ"
+    ( line 5 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "rect")))
+          [ KeyValArg (Identifier "stroke") (Ident (Identifier "red")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-recursive-03.typ"
+    ( line 6 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list"))) (Ident (Identifier "block")))
+, ParBreak
+, BulletListItem
+    [ Text "List"
+    , SoftBreak
+    , BulletListItem [ Text "Nested" ]
+    , SoftBreak
+    , BulletListItem [ Text "List" ]
+    ]
+, SoftBreak
+, BulletListItem [ Text "Recursive!" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  block(body: list(children: ({ text(body: [List
+]), 
+                                block(body: block(body: list(children: (text(body: [Nested]), 
+                                                                        text(body: [List]))))) }, 
+                              { text(body: [Recursive!]), 
+                                parbreak() }))) }
diff --git a/test/out/compiler/show-selector-00.out b/test/out/compiler/show-selector-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-selector-00.out
@@ -0,0 +1,209 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-selector-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-selector-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-selector-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-selector-00.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "raw")))
+             [ KeyValArg (Identifier "block") (Literal (Boolean False)) ]))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "box")))
+          [ KeyValArg (Identifier "radius") (Literal (Numeric 2.0 Pt))
+          , KeyValArg
+              (Identifier "outset")
+              (Dict [ ( Identifier "y" , Literal (Numeric 2.5 Pt) ) ])
+          , KeyValArg
+              (Identifier "inset")
+              (Dict
+                 [ ( Identifier "x" , Literal (Numeric 3.0 Pt) )
+                 , ( Identifier "y" , Literal (Numeric 0.0 Pt) )
+                 ])
+          , KeyValArg
+              (Identifier "fill")
+              (FuncCall
+                 (Ident (Identifier "luma")) [ NormalArg (Literal (Int 230)) ])
+          ]))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/show-selector-00.typ"
+    ( line 11 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "raw")))
+             [ KeyValArg (Identifier "block") (Literal (Boolean True)) ]))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "block")))
+          [ KeyValArg
+              (Identifier "outset") (Negated (Literal (Numeric 3.0 Pt)))
+          , KeyValArg (Identifier "inset") (Literal (Numeric 11.0 Pt))
+          , KeyValArg
+              (Identifier "fill")
+              (FuncCall
+                 (Ident (Identifier "luma")) [ NormalArg (Literal (Int 230)) ])
+          , KeyValArg
+              (Identifier "stroke")
+              (Dict
+                 [ ( Identifier "left"
+                   , Plus
+                       (Literal (Numeric 1.5 Pt))
+                       (FuncCall
+                          (Ident (Identifier "luma")) [ NormalArg (Literal (Int 180)) ])
+                   )
+                 ])
+          ]))
+, ParBreak
+, Code
+    "test/typ/compiler/show-selector-00.typ"
+    ( line 18 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg
+           (Identifier "margin")
+           (Dict [ ( Identifier "top" , Literal (Numeric 12.0 Pt) ) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/show-selector-00.typ"
+    ( line 19 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, ParBreak
+, Text "This"
+, Space
+, Text "code"
+, Space
+, Text "tests"
+, Space
+, RawInline "code"
+, SoftBreak
+, Text "with"
+, Space
+, Text "selectors"
+, Space
+, Text "and"
+, Space
+, Text "justification"
+, Text "."
+, ParBreak
+, RawBlock "rs" "code!(\"it\");\n"
+, ParBreak
+, Text "You"
+, Space
+, Text "can"
+, Space
+, Text "use"
+, Space
+, Text "the"
+, Space
+, RawBlock "rs" "*const T"
+, Space
+, Text "pointer"
+, Space
+, Text "or"
+, SoftBreak
+, Text "the"
+, Space
+, RawBlock "rs" "&mut T"
+, Space
+, Text "reference"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [This code tests ]), 
+  box(body: raw(block: false, 
+                lang: none, 
+                text: "code"), 
+      fill: luma(23000%), 
+      inset: (x: 3.0pt, y: 0.0pt), 
+      outset: (y: 2.5pt), 
+      radius: 2.0pt), 
+  text(body: [
+with selectors and justification.]), 
+  parbreak(), 
+  block(body: raw(block: true, 
+                  lang: "rs", 
+                  text: "code!(\"it\");\n"), 
+        fill: luma(23000%), 
+        inset: 11.0pt, 
+        outset: -3.0pt, 
+        stroke: (left: (thickness: 1.5pt,
+                        color: luma(18000%)))), 
+  parbreak(), 
+  text(body: [You can use the ]), 
+  block(body: raw(block: true, 
+                  lang: "rs", 
+                  text: "*const T"), 
+        fill: luma(23000%), 
+        inset: 11.0pt, 
+        outset: -3.0pt, 
+        stroke: (left: (thickness: 1.5pt,
+                        color: luma(18000%)))), 
+  text(body: [ pointer or
+the ]), 
+  block(body: raw(block: true, 
+                  lang: "rs", 
+                  text: "&mut T"), 
+        fill: luma(23000%), 
+        inset: 11.0pt, 
+        outset: -3.0pt, 
+        stroke: (left: (thickness: 1.5pt,
+                        color: luma(18000%)))), 
+  text(body: [ reference.]), 
+  parbreak() }
diff --git a/test/out/compiler/show-selector-01.out b/test/out/compiler/show-selector-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-selector-01.out
@@ -0,0 +1,95 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-selector-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-selector-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-selector-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-selector-01.typ"
+    ( line 2 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "heading")))
+             [ KeyValArg (Identifier "level") (Literal (Int 1)) ]))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "red")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-selector-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "heading")))
+             [ KeyValArg (Identifier "level") (Literal (Int 2)) ]))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "blue")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-selector-01.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "green")) ]))
+, SoftBreak
+, Heading 1 [ Text "Red" ]
+, Heading 2 [ Text "Blue" ]
+, Heading 3 [ Text "Green" ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  heading(body: text(body: [Red]), 
+          level: 1), 
+  heading(body: text(body: [Blue]), 
+          level: 2), 
+  heading(body: text(body: [Green]), 
+          level: 3) }
diff --git a/test/out/compiler/show-selector-02.out b/test/out/compiler/show-selector-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-selector-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/show-text-00.out b/test/out/compiler/show-text-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-00.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "Roboto")) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/show-text-00.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Literal (String "Der Spiegel")))
+       (Ident (Identifier "smallcaps")))
+, SoftBreak
+, Text "Die"
+, Space
+, Text "Zeitung"
+, Space
+, Text "Der"
+, Space
+, Text "Spiegel"
+, Space
+, Text "existiert"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       font: "Roboto"), 
+  text(body: [
+Die Zeitung ], 
+       font: "Roboto"), 
+  smallcaps(body: [Der Spiegel]), 
+  text(body: [ existiert.], 
+       font: "Roboto"), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-01.out b/test/out/compiler/show-text-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-01.out
@@ -0,0 +1,156 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Literal (String "TeX")))
+       (Block
+          (Content
+             [ Text "T"
+             , Code
+                 "test/typ/compiler/show-text-01.typ"
+                 ( line 3 , column 17 )
+                 (FuncCall
+                    (Ident (Identifier "h"))
+                    [ NormalArg (Negated (Literal (Numeric 0.145 Em))) ])
+             , Code
+                 "test/typ/compiler/show-text-01.typ"
+                 ( line 3 , column 29 )
+                 (FuncCall
+                    (Ident (Identifier "box"))
+                    [ NormalArg
+                        (FuncCall
+                           (Ident (Identifier "move"))
+                           [ KeyValArg (Identifier "dy") (Literal (Numeric 0.233 Em))
+                           , BlockArg [ Text "E" ]
+                           ])
+                    ])
+             , Code
+                 "test/typ/compiler/show-text-01.typ"
+                 ( line 3 , column 55 )
+                 (FuncCall
+                    (Ident (Identifier "h"))
+                    [ NormalArg (Negated (Literal (Numeric 0.135 Em))) ])
+             , Text "X"
+             ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-text-01.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (Ident (Identifier "regex"))
+             [ NormalArg (Literal (String "(Lua)?(La)?TeX")) ]))
+       (FuncExpr
+          [ NormalParam (Identifier "name") ]
+          (FuncCall
+             (Ident (Identifier "box"))
+             [ NormalArg
+                 (FuncCall
+                    (Ident (Identifier "text"))
+                    [ KeyValArg
+                        (Identifier "font") (Literal (String "New Computer Modern"))
+                    , BlockArg
+                        [ Code
+                            "test/typ/compiler/show-text-01.typ"
+                            ( line 4 , column 79 )
+                            (Ident (Identifier "name"))
+                        ]
+                    ])
+             ])))
+, ParBreak
+, Text "TeX,"
+, Space
+, Text "LaTeX,"
+, Space
+, Text "LuaTeX"
+, Space
+, Text "and"
+, Space
+, Text "LuaLaTeX!"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  box(body: text(body: { text(body: [T]), 
+                         h(amount: -0.145em), 
+                         box(body: move(body: text(body: [E]), 
+                                        dy: 0.233em)), 
+                         h(amount: -0.135em), 
+                         text(body: [X]) }, 
+                 font: "New Computer Modern")), 
+  text(body: [, ]), 
+  box(body: text(body: { text(body: [La]), 
+                         text(body: [T]), 
+                         h(amount: -0.145em), 
+                         box(body: move(body: text(body: [E]), 
+                                        dy: 0.233em)), 
+                         h(amount: -0.135em), 
+                         text(body: [X]) }, 
+                 font: "New Computer Modern")), 
+  text(body: [, ]), 
+  box(body: text(body: { text(body: [Lua]), 
+                         text(body: [T]), 
+                         h(amount: -0.145em), 
+                         box(body: move(body: text(body: [E]), 
+                                        dy: 0.233em)), 
+                         h(amount: -0.135em), 
+                         text(body: [X]) }, 
+                 font: "New Computer Modern")), 
+  text(body: [ and ]), 
+  box(body: text(body: { text(body: [LuaLa]), 
+                         text(body: [T]), 
+                         h(amount: -0.145em), 
+                         box(body: move(body: text(body: [E]), 
+                                        dy: 0.233em)), 
+                         h(amount: -0.135em), 
+                         text(body: [X]) }, 
+                 font: "New Computer Modern")), 
+  text(body: [!]), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-02.out b/test/out/compiler/show-text-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-02.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-02.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Literal (String "A"))) (Block (Content [ Text "BB" ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-text-02.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Literal (String "B"))) (Block (Content [ Text "CC" ])))
+, SoftBreak
+, Text "AA"
+, Space
+, Text "("
+, Text "8)"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [BB]), 
+  text(body: [BB]), 
+  text(body: [ (8)]), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-03.out b/test/out/compiler/show-text-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-03.out
@@ -0,0 +1,80 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-03.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (Ident (Identifier "regex"))
+             [ NormalArg (Literal (String "(?i)\\bworld\\b")) ]))
+       (Block (Content [ Text "\127757" ])))
+, ParBreak
+, Text "Treeworld,"
+, Space
+, Text "the"
+, Space
+, Text "World"
+, Space
+, Text "of"
+, Space
+, Text "worlds,"
+, Space
+, Text "is"
+, Space
+, Text "a"
+, Space
+, Text "world"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Treeworld, the ]), 
+  text(body: [🌍]), 
+  text(body: [ of worlds, is a ]), 
+  text(body: [🌍]), 
+  text(body: [.]), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-04.out b/test/out/compiler/show-text-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-04.out
@@ -0,0 +1,157 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/show-text-04.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (Ident (Identifier "regex"))
+             [ NormalArg (Literal (String "\\S")) ]))
+       (FuncExpr
+          [ NormalParam (Identifier "letter") ]
+          (FuncCall
+             (Ident (Identifier "box"))
+             [ KeyValArg (Identifier "stroke") (Literal (Numeric 1.0 Pt))
+             , KeyValArg (Identifier "inset") (Literal (Numeric 2.0 Pt))
+             , NormalArg
+                 (FuncCall
+                    (Ident (Identifier "upper"))
+                    [ NormalArg (Ident (Identifier "letter")) ])
+             ])))
+, SoftBreak
+, Code
+    "test/typ/compiler/show-text-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 5)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  box(body: upper(text: [L]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [o]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [r]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [e]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [m]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  text(body: [ ]), 
+  box(body: upper(text: [i]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [p]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [s]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [u]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [m]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  text(body: [ ]), 
+  box(body: upper(text: [d]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [o]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [l]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [o]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [r]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  text(body: [ ]), 
+  box(body: upper(text: [s]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [i]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [t]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  text(body: [ ]), 
+  box(body: upper(text: [a]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [m]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [e]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [t]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  box(body: upper(text: [,]), 
+      inset: 2.0pt, 
+      stroke: 1.0pt), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-05.out b/test/out/compiler/show-text-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-05.out
@@ -0,0 +1,104 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-05.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (Ident (Identifier "regex"))
+             [ NormalArg (Literal (String "(?i)rust")) ]))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (Content
+                [ Code
+                    "test/typ/compiler/show-text-05.typ"
+                    ( line 3 , column 34 )
+                    (Ident (Identifier "it"))
+                , Space
+                , Text "("
+                , Text "\128640)"
+                ]))))
+, SoftBreak
+, Text "Rust"
+, Space
+, Text "is"
+, Space
+, Text "memory"
+, Text "-"
+, Text "safe"
+, Space
+, Text "and"
+, Space
+, Text "blazingly"
+, Space
+, Text "fast"
+, Text "."
+, Space
+, Text "Let"
+, Quote '\''
+, Text "s"
+, Space
+, Text "rewrite"
+, Space
+, Text "everything"
+, Space
+, Text "in"
+, Space
+, Text "rust"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Rust]), 
+  text(body: [ (🚀)]), 
+  text(body: [ is memory-safe and blazingly fast. Let’s rewrite everything in ]), 
+  text(body: [rust]), 
+  text(body: [ (🚀)]), 
+  text(body: [.]), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-06.out b/test/out/compiler/show-text-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-06.out
@@ -0,0 +1,79 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-06.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Literal (String "hello")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "join"))
+                (FuncCall
+                   (FieldAccess
+                      (Ident (Identifier "map"))
+                      (FuncCall
+                         (FieldAccess
+                            (Ident (Identifier "split"))
+                            (FieldAccess
+                               (Ident (Identifier "text")) (Ident (Identifier "it"))))
+                         [ NormalArg (Literal (String "")) ]))
+                   [ NormalArg (Ident (Identifier "upper")) ]))
+             [ NormalArg (Literal (String "|")) ])))
+, SoftBreak
+, Text "Oh,"
+, Space
+, Text "hello"
+, Space
+, Text "there!"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Oh, ]), 
+  text(body: [|H|E|L|L|O|]), 
+  text(body: [ there!]), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-07.out b/test/out/compiler/show-text-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-07.out
@@ -0,0 +1,85 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/show-text-07.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (Content
+                [ SoftBreak
+                , Code
+                    "test/typ/compiler/show-text-07.typ"
+                    ( line 4 , column 4 )
+                    (Show
+                       (Just (Literal (String "World")))
+                       (Block (Content [ Text "\127758" ])))
+                , SoftBreak
+                , Code
+                    "test/typ/compiler/show-text-07.typ"
+                    ( line 5 , column 4 )
+                    (Ident (Identifier "it"))
+                , ParBreak
+                ]))))
+, ParBreak
+, Text "World"
+, SoftBreak
+, BulletListItem [ Text "World" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [World
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  list(children: ({ text(body: { [], 
+                                 text(body: [🌎]), 
+                                 [] }), 
+                    parbreak() })), 
+  parbreak() }
diff --git a/test/out/compiler/show-text-08.out b/test/out/compiler/show-text-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/show-text-08.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/show-text-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/show-text-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/show-text-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/show-text-08.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Literal (String "GRAPH")))
+       (FuncCall
+          (Ident (Identifier "image"))
+          [ NormalArg (Literal (String "test/assets/files/graph.png")) ]))
+, ParBreak
+, Text "The"
+, Space
+, Text "GRAPH"
+, Space
+, Text "has"
+, Space
+, Text "nodes"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [The ]), 
+  image(path: "test/assets/files/graph.png"), 
+  text(body: [ has nodes.]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-00.out b/test/out/compiler/spread-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-00.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-00.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ LetFunc
+              (Identifier "f")
+              [ DefaultParam (Identifier "style") (Literal (String "normal"))
+              , DefaultParam (Identifier "weight") (Literal (String "regular"))
+              ]
+              (Block
+                 (CodeBlock
+                    [ Plus
+                        (Plus
+                           (Plus
+                              (Plus (Literal (String "(style: ")) (Ident (Identifier "style")))
+                              (Literal (String ", weight: ")))
+                           (Ident (Identifier "weight")))
+                        (Literal (String ")"))
+                    ]))
+          , LetFunc
+              (Identifier "myf")
+              [ SinkParam (Just (Identifier "args")) ]
+              (FuncCall
+                 (Ident (Identifier "f"))
+                 [ KeyValArg (Identifier "weight") (Literal (String "bold"))
+                 , SpreadArg (Ident (Identifier "args"))
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (FuncCall (Ident (Identifier "myf")) [])
+              , NormalArg (Literal (String "(style: normal, weight: bold)"))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "myf"))
+                     [ KeyValArg (Identifier "weight") (Literal (String "black")) ])
+              , NormalArg (Literal (String "(style: normal, weight: black)"))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "myf"))
+                     [ KeyValArg (Identifier "style") (Literal (String "italic")) ])
+              , NormalArg (Literal (String "(style: italic, weight: bold)"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-01.out b/test/out/compiler/spread-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-01.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-01.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ LetFunc
+              (Identifier "f")
+              [ NormalParam (Identifier "b")
+              , DefaultParam (Identifier "c") (Literal (String "!"))
+              ]
+              (Plus (Ident (Identifier "b")) (Ident (Identifier "c")))
+          , LetFunc
+              (Identifier "g")
+              [ NormalParam (Identifier "a")
+              , SinkParam (Just (Identifier "sink"))
+              ]
+              (Plus
+                 (Ident (Identifier "a"))
+                 (FuncCall
+                    (Ident (Identifier "f"))
+                    [ SpreadArg (Ident (Identifier "sink")) ]))
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "g"))
+                     [ NormalArg (Literal (String "a"))
+                     , NormalArg (Literal (String "b"))
+                     , KeyValArg (Identifier "c") (Literal (String "c"))
+                     ])
+              , NormalArg (Literal (String "abc"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-02.out b/test/out/compiler/spread-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-02.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-02.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ LetFunc
+              (Identifier "save")
+              [ SinkParam (Just (Identifier "args")) ]
+              (Block
+                 (CodeBlock
+                    [ FuncCall
+                        (Ident (Identifier "test"))
+                        [ NormalArg
+                            (FuncCall
+                               (Ident (Identifier "type"))
+                               [ NormalArg (Ident (Identifier "args")) ])
+                        , NormalArg (Literal (String "arguments"))
+                        ]
+                    , FuncCall
+                        (Ident (Identifier "test"))
+                        [ NormalArg
+                            (FuncCall
+                               (Ident (Identifier "repr"))
+                               [ NormalArg (Ident (Identifier "args")) ])
+                        , NormalArg (Literal (String "(three: true, 1, 2)"))
+                        ]
+                    ]))
+          , FuncCall
+              (Ident (Identifier "save"))
+              [ NormalArg (Literal (Int 1))
+              , NormalArg (Literal (Int 2))
+              , KeyValArg (Identifier "three") (Literal (Boolean True))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-03.out b/test/out/compiler/spread-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-03.out
@@ -0,0 +1,131 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-03.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "more")))
+              (Array
+                 [ Literal (Int 3)
+                 , Negated (Literal (Int 3))
+                 , Literal (Int 6)
+                 , Literal (Int 10)
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "min")) (Ident (Identifier "calc")))
+                     [ NormalArg (Literal (Int 1))
+                     , NormalArg (Literal (Int 2))
+                     , SpreadArg (Ident (Identifier "more"))
+                     ])
+              , NormalArg (Negated (Literal (Int 3)))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "max")) (Ident (Identifier "calc")))
+                     [ SpreadArg (Ident (Identifier "more"))
+                     , NormalArg (Literal (Int 9))
+                     ])
+              , NormalArg (Literal (Int 10))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "max")) (Ident (Identifier "calc")))
+                     [ SpreadArg (Ident (Identifier "more"))
+                     , NormalArg (Literal (Int 11))
+                     ])
+              , NormalArg (Literal (Int 11))
+              ]
+          ]))
+, ParBreak
+, Code
+    "test/typ/compiler/spread-03.typ"
+    ( line 10 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "more")))
+              (Dict
+                 [ ( Identifier "c" , Literal (Int 3) )
+                 , ( Identifier "d" , Literal (Int 4) )
+                 ])
+          , LetFunc
+              (Identifier "tostr")
+              [ SinkParam (Just (Identifier "args")) ]
+              (FuncCall
+                 (Ident (Identifier "repr"))
+                 [ NormalArg (Ident (Identifier "args")) ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "tostr"))
+                     [ KeyValArg (Identifier "a") (Literal (Int 1))
+                     , SpreadArg (Ident (Identifier "more"))
+                     , KeyValArg (Identifier "b") (Literal (Int 2))
+                     ])
+              , NormalArg (Literal (String "(a: 1, c: 3, d: 4, b: 2)"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-04.out b/test/out/compiler/spread-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-04.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-04.typ"
+    ( line 3 , column 2 )
+    (LetFunc (Identifier "f") [] (Literal None))
+, SoftBreak
+, Code
+    "test/typ/compiler/spread-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall (Ident (Identifier "f")) [ SpreadArg (Literal None) ])
+, SoftBreak
+, Code
+    "test/typ/compiler/spread-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "f"))
+       [ SpreadArg
+           (If [ ( Literal (Boolean False) , Block (CodeBlock []) ) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/spread-04.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "f"))
+       [ SpreadArg
+           (For
+              (BasicBind (Just (Identifier "x")))
+              (Array [])
+              (Block (Content [])))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-05.out b/test/out/compiler/spread-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-05.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-05.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "f")
+       [ SinkParam Nothing , NormalParam (Identifier "a") ]
+       (Ident (Identifier "a")))
+, SoftBreak
+, Code
+    "test/typ/compiler/spread-05.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "f"))
+              [ NormalArg (Literal (Int 1))
+              , NormalArg (Literal (Int 2))
+              , NormalArg (Literal (Int 3))
+              ])
+       , NormalArg (Literal (Int 3))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-06.out b/test/out/compiler/spread-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/spread-07.out b/test/out/compiler/spread-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/spread-08.out b/test/out/compiler/spread-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/spread-09.out b/test/out/compiler/spread-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-09.out
@@ -0,0 +1,3 @@
+"test/typ/compiler/spread-09.typ" (line 6, column 10):
+unexpected "."
+expecting digit
diff --git a/test/out/compiler/spread-10.out b/test/out/compiler/spread-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/spread-11.out b/test/out/compiler/spread-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/spread-12.out b/test/out/compiler/spread-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-12.out
@@ -0,0 +1,105 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-12.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-12.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-12.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-12.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ LetFunc
+              (Identifier "f")
+              [ SinkParam (Just (Identifier "a"))
+              , NormalParam (Identifier "b")
+              ]
+              (Array [ Ident (Identifier "a") , Ident (Identifier "b") ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "repr"))
+                     [ NormalArg
+                         (FuncCall (Ident (Identifier "f")) [ NormalArg (Literal (Int 1)) ])
+                     ])
+              , NormalArg (Literal (String "((), 1)"))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "repr"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "f"))
+                            [ NormalArg (Literal (Int 1))
+                            , NormalArg (Literal (Int 2))
+                            , NormalArg (Literal (Int 3))
+                            ])
+                     ])
+              , NormalArg (Literal (String "((1, 2), 3)"))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "repr"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "f"))
+                            [ NormalArg (Literal (Int 1))
+                            , NormalArg (Literal (Int 2))
+                            , NormalArg (Literal (Int 3))
+                            , NormalArg (Literal (Int 4))
+                            , NormalArg (Literal (Int 5))
+                            ])
+                     ])
+              , NormalArg (Literal (String "((1, 2, 3, 4), 5)"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-13.out b/test/out/compiler/spread-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-13.out
@@ -0,0 +1,96 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-13.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-13.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-13.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-13.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ LetFunc
+              (Identifier "f")
+              [ NormalParam (Identifier "a")
+              , SinkParam (Just (Identifier "b"))
+              , NormalParam (Identifier "c")
+              ]
+              (Array
+                 [ Ident (Identifier "a")
+                 , Ident (Identifier "b")
+                 , Ident (Identifier "c")
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "repr"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "f"))
+                            [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 2)) ])
+                     ])
+              , NormalArg (Literal (String "(1, (), 2)"))
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "repr"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "f"))
+                            [ NormalArg (Literal (Int 1))
+                            , NormalArg (Literal (Int 2))
+                            , NormalArg (Literal (Int 3))
+                            , NormalArg (Literal (Int 4))
+                            , NormalArg (Literal (Int 5))
+                            ])
+                     ])
+              , NormalArg (Literal (String "(1, (2, 3, 4), 5)"))
+              ]
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/spread-14.out b/test/out/compiler/spread-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/spread-14.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-00.out b/test/out/compiler/string-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-00.out
@@ -0,0 +1,61 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "len")) (Literal (String "Hello World!")))
+              [])
+       , NormalArg (Literal (Int 12))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-01.out b/test/out/compiler/string-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-01.out
@@ -0,0 +1,123 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "first")) (Literal (String "Hello")))
+              [])
+       , NormalArg (Literal (String "H"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "last")) (Literal (String "Hello")))
+              [])
+       , NormalArg (Literal (String "o"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "first"))
+                 (Literal
+                    (String
+                       "\127987\65039\8205\127752A\127987\65039\8205\9895\65039")))
+              [])
+       , NormalArg (Literal (String "\127987\65039\8205\127752"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "last"))
+                 (Literal
+                    (String
+                       "\127987\65039\8205\127752A\127987\65039\8205\9895\65039")))
+              [])
+       , NormalArg (Literal (String "\127987\65039\8205\9895\65039"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: ["🏳"]), 
+  text(body: [ /= ]), 
+  text(body: ["🏳️‍🌈"]), 
+  text(body: [)]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: ["️"]), 
+  text(body: [ /= ]), 
+  text(body: ["🏳️‍⚧️"]), 
+  text(body: [)]), 
+  parbreak() }
diff --git a/test/out/compiler/string-02.out b/test/out/compiler/string-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-03.out b/test/out/compiler/string-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-04.out b/test/out/compiler/string-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-04.out
@@ -0,0 +1,126 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-04.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "at")) (Literal (String "Hello")))
+              [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (String "e"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "at")) (Literal (String "Hello")))
+              [ NormalArg (Literal (Int 4)) ])
+       , NormalArg (Literal (String "o"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "at")) (Literal (String "Hello")))
+              [ NormalArg (Negated (Literal (Int 1))) ])
+       , NormalArg (Literal (String "o"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-04.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "at")) (Literal (String "Hello")))
+              [ NormalArg (Negated (Literal (Int 2))) ])
+       , NormalArg (Literal (String "l"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-04.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "at"))
+                 (Literal (String "Hey: \127987\65039\8205\127752 there!")))
+              [ NormalArg (Literal (Int 5)) ])
+       , NormalArg (Literal (String "\127987\65039\8205\127752"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: ["🏳"]), 
+  text(body: [ /= ]), 
+  text(body: ["🏳️‍🌈"]), 
+  text(body: [)]), 
+  parbreak() }
diff --git a/test/out/compiler/string-05.out b/test/out/compiler/string-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-06.out b/test/out/compiler/string-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-07.out b/test/out/compiler/string-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-07.out
@@ -0,0 +1,116 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-07.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "slice")) (Literal (String "abc")))
+              [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (String "b"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-07.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice")) (Literal (String "abc\127969def")))
+              [ NormalArg (Literal (Int 2)) , NormalArg (Literal (Int 7)) ])
+       , NormalArg (Literal (String "c\127969"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-07.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice")) (Literal (String "abc\127969def")))
+              [ NormalArg (Literal (Int 2))
+              , NormalArg (Negated (Literal (Int 2)))
+              ])
+       , NormalArg (Literal (String "c\127969d"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-07.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "slice")) (Literal (String "abc\127969def")))
+              [ NormalArg (Negated (Literal (Int 3)))
+              , NormalArg (Negated (Literal (Int 1)))
+              ])
+       , NormalArg (Literal (String "de"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: ["c🏡def"]), 
+  text(body: [ /= ]), 
+  text(body: ["c🏡"]), 
+  text(body: [)]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-08.out b/test/out/compiler/string-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-09.out b/test/out/compiler/string-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-09.out
@@ -0,0 +1,136 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-09.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "clusters")) (Literal (String "abc")))
+              [])
+       , NormalArg
+           (Array
+              [ Literal (String "a")
+              , Literal (String "b")
+              , Literal (String "c")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-09.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "clusters")) (Literal (String "abc")))
+              [])
+       , NormalArg
+           (Array
+              [ Literal (String "a")
+              , Literal (String "b")
+              , Literal (String "c")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-09.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "clusters"))
+                 (Literal (String "\127987\65039\8205\127752!")))
+              [])
+       , NormalArg
+           (Array
+              [ Literal (String "\127987\65039\8205\127752")
+              , Literal (String "!")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-09.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "codepoints"))
+                 (Literal (String "\127987\65039\8205\127752!")))
+              [])
+       , NormalArg
+           (Array
+              [ Literal (String "\127987")
+              , Literal (String "\65039")
+              , Literal (String "\8205")
+              , Literal (String "\127752")
+              , Literal (String "!")
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [("🏳", "️", "‍", "🌈", "!")]), 
+  text(body: [ /= ]), 
+  text(body: [("🏳️‍🌈", "!")]), 
+  text(body: [)]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-10.out b/test/out/compiler/string-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-10.out
@@ -0,0 +1,181 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-10.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-10.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-10.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "contains")) (Literal (String "abc")))
+              [ NormalArg (Literal (String "b")) ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection (Literal (String "b")) (Literal (String "abc")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "contains")) (Literal (String "1234f")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (FuncCall
+                 (Ident (Identifier "regex"))
+                 [ NormalArg (Literal (String "\\d")) ])
+              (Literal (String "1234f")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "contains")) (Literal (String "abc")))
+              [ NormalArg (Literal (String "d")) ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (InCollection
+              (Literal (String "1234g")) (Literal (String "1234f")))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "contains")) (Literal (String "abc")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "^[abc]$")) ])
+              ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-10.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "contains")) (Literal (String "abc")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "^[abc]+$")) ])
+              ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-11.out b/test/out/compiler/string-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-11.out
@@ -0,0 +1,173 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-11.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-11.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-11.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-11.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "starts-with")) (Literal (String "Typst")))
+              [ NormalArg (Literal (String "Ty")) ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-11.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "starts-with")) (Literal (String "Typst")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "[Tt]ys")) ])
+              ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-11.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "starts-with")) (Literal (String "Typst")))
+              [ NormalArg (Literal (String "st")) ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-11.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "ends-with")) (Literal (String "Typst")))
+              [ NormalArg (Literal (String "st")) ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-11.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "ends-with")) (Literal (String "Typst")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d*")) ])
+              ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-11.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "ends-with")) (Literal (String "Typst")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d+")) ])
+              ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-11.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "ends-with")) (Literal (String "Typ12")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d+")) ])
+              ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-12.out b/test/out/compiler/string-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-12.out
@@ -0,0 +1,121 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-12.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-12.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-12.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-12.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "date")))
+       (FuncCall
+          (Ident (Identifier "regex"))
+          [ NormalArg (Literal (String "\\d{2}:\\d{2}")) ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/string-12.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "find")) (Literal (String "Hello World")))
+              [ NormalArg (Literal (String "World")) ])
+       , NormalArg (Literal (String "World"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-12.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "position")) (Literal (String "Hello World")))
+              [ NormalArg (Literal (String "World")) ])
+       , NormalArg (Literal (Int 6))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-12.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "find")) (Literal (String "It's 12:13 now")))
+              [ NormalArg (Ident (Identifier "date")) ])
+       , NormalArg (Literal (String "12:13"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-12.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "position"))
+                 (Literal (String "It's 12:13 now")))
+              [ NormalArg (Ident (Identifier "date")) ])
+       , NormalArg (Literal (Int 5))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-13.out b/test/out/compiler/string-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-13.out
@@ -0,0 +1,253 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-13.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-13.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-13.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "match")) (Literal (String "Is there a")))
+              [ NormalArg (Literal (String "for this?")) ])
+       , NormalArg (Literal None)
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "match"))
+                 (Literal (String "The time of my life.")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "[mit]+e")) ])
+              ])
+       , NormalArg
+           (Dict
+              [ ( Identifier "start" , Literal (Int 4) )
+              , ( Identifier "end" , Literal (Int 8) )
+              , ( Identifier "text" , Literal (String "time") )
+              , ( Identifier "captures" , Array [] )
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "matches")) (Literal (String "Hello there")))
+              [ NormalArg (Literal (String "\\d")) ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "matches")) (Literal (String "Day by Day.")))
+              [ NormalArg (Literal (String "Day")) ])
+       , NormalArg
+           (Array
+              [ Dict
+                  [ ( Identifier "start" , Literal (Int 0) )
+                  , ( Identifier "end" , Literal (Int 3) )
+                  , ( Identifier "text" , Literal (String "Day") )
+                  , ( Identifier "captures" , Array [] )
+                  ]
+              , Dict
+                  [ ( Identifier "start" , Literal (Int 7) )
+                  , ( Identifier "end" , Literal (Int 10) )
+                  , ( Identifier "text" , Literal (String "Day") )
+                  , ( Identifier "captures" , Array [] )
+                  ]
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 17 , column 2 )
+    (LetFunc
+       (Identifier "timesum")
+       [ NormalParam (Identifier "text") ]
+       (Block
+          (CodeBlock
+             [ Let (BasicBind (Just (Identifier "time"))) (Literal (Int 0))
+             , For
+                 (BasicBind (Just (Identifier "match")))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "matches")) (Ident (Identifier "text")))
+                    [ NormalArg
+                        (FuncCall
+                           (Ident (Identifier "regex"))
+                           [ NormalArg (Literal (String "(\\d+):(\\d+)")) ])
+                    ])
+                 (Block
+                    (CodeBlock
+                       [ Let
+                           (BasicBind (Just (Identifier "caps")))
+                           (FieldAccess
+                              (Ident (Identifier "captures")) (Ident (Identifier "match")))
+                       , Assign
+                           (Ident (Identifier "time"))
+                           (Plus
+                              (Ident (Identifier "time"))
+                              (Plus
+                                 (Times
+                                    (Literal (Int 60))
+                                    (FuncCall
+                                       (Ident (Identifier "int"))
+                                       [ NormalArg
+                                           (FuncCall
+                                              (FieldAccess
+                                                 (Ident (Identifier "at"))
+                                                 (Ident (Identifier "caps")))
+                                              [ NormalArg (Literal (Int 0)) ])
+                                       ]))
+                                 (FuncCall
+                                    (Ident (Identifier "int"))
+                                    [ NormalArg
+                                        (FuncCall
+                                           (FieldAccess
+                                              (Ident (Identifier "at")) (Ident (Identifier "caps")))
+                                           [ NormalArg (Literal (Int 1)) ])
+                                    ])))
+                       ]))
+             , Plus
+                 (Plus
+                    (FuncCall
+                       (Ident (Identifier "str"))
+                       [ NormalArg
+                           (FuncCall
+                              (Ident (Identifier "int"))
+                              [ NormalArg
+                                  (Divided (Ident (Identifier "time")) (Literal (Int 60)))
+                              ])
+                       ])
+                    (Literal (String ":")))
+                 (FuncCall
+                    (Ident (Identifier "str"))
+                    [ NormalArg
+                        (FuncCall
+                           (FieldAccess
+                              (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+                           [ NormalArg (Ident (Identifier "time"))
+                           , NormalArg (Literal (Int 60))
+                           ])
+                    ])
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 26 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "timesum")) [ NormalArg (Literal (String "")) ])
+       , NormalArg (Literal (String "0:0"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 27 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "timesum"))
+              [ NormalArg (Literal (String "2:70")) ])
+       , NormalArg (Literal (String "3:10"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-13.typ"
+    ( line 28 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "timesum"))
+              [ NormalArg (Literal (String "1:20, 2:10, 0:40")) ])
+       , NormalArg (Literal (String "4:10"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-14.out b/test/out/compiler/string-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-14.out
@@ -0,0 +1,198 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-14.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-14.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-14.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-14.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "ABC")))
+              [ NormalArg (Literal (String ""))
+              , NormalArg (Literal (String "-"))
+              ])
+       , NormalArg (Literal (String "-A-B-C-"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-14.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "Ok")))
+              [ NormalArg (Literal (String "Ok"))
+              , NormalArg (Literal (String "Nope"))
+              , KeyValArg (Identifier "count") (Literal (Int 0))
+              ])
+       , NormalArg (Literal (String "Ok"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-14.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "to add?")))
+              [ NormalArg (Literal (String ""))
+              , NormalArg (Literal (String "How "))
+              , KeyValArg (Identifier "count") (Literal (Int 1))
+              ])
+       , NormalArg (Literal (String "How to add?"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-14.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "AB C DEF GH J")))
+              [ NormalArg (Literal (String " "))
+              , NormalArg (Literal (String ","))
+              , KeyValArg (Identifier "count") (Literal (Int 2))
+              ])
+       , NormalArg (Literal (String "AB,C,DEF GH J"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-14.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "replace"))
+                       (FuncCall
+                          (FieldAccess
+                             (Ident (Identifier "replace"))
+                             (FuncCall
+                                (FieldAccess
+                                   (Ident (Identifier "replace")) (Literal (String "Walcemo")))
+                                [ NormalArg (Literal (String "o"))
+                                , NormalArg (Literal (String "k"))
+                                ]))
+                          [ NormalArg (Literal (String "e"))
+                          , NormalArg (Literal (String "o"))
+                          ]))
+                    [ NormalArg (Literal (String "k"))
+                    , NormalArg (Literal (String "e"))
+                    ]))
+              [ NormalArg (Literal (String "a"))
+              , NormalArg (Literal (String "e"))
+              ])
+       , NormalArg (Literal (String "Welcome"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-14.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "123")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d$")) ])
+              , NormalArg (Literal (String "_"))
+              ])
+       , NormalArg (Literal (String "12_"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-14.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "123")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d{1,2}$")) ])
+              , NormalArg (Literal (String "__"))
+              ])
+       , NormalArg (Literal (String "1__"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-15.out b/test/out/compiler/string-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-15.out
@@ -0,0 +1,476 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-15.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-15.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-15.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "abc")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "[a-z]")) ])
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (Block
+                        (CodeBlock
+                           [ Plus
+                               (Plus
+                                  (FuncCall
+                                     (Ident (Identifier "str"))
+                                     [ NormalArg
+                                         (FieldAccess
+                                            (Ident (Identifier "start")) (Ident (Identifier "m")))
+                                     ])
+                                  (FieldAccess
+                                     (Ident (Identifier "text")) (Ident (Identifier "m"))))
+                               (FuncCall
+                                  (Ident (Identifier "str"))
+                                  [ NormalArg
+                                      (FieldAccess
+                                         (Ident (Identifier "end")) (Ident (Identifier "m")))
+                                  ])
+                           ])))
+              ])
+       , NormalArg (Literal (String "0a11b22c3"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "abcd, efgh")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\w+")) ])
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (Block
+                        (CodeBlock
+                           [ FuncCall
+                               (Ident (Identifier "upper"))
+                               [ NormalArg
+                                   (FieldAccess
+                                      (Ident (Identifier "text")) (Ident (Identifier "m")))
+                               ]
+                           ])))
+              ])
+       , NormalArg (Literal (String "ABCD, EFGH"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "hello : world")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "^(.+)\\s*(:)\\s*(.+)$")) ])
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (Block
+                        (CodeBlock
+                           [ Plus
+                               (Plus
+                                  (Plus
+                                     (FuncCall
+                                        (Ident (Identifier "upper"))
+                                        [ NormalArg
+                                            (FuncCall
+                                               (FieldAccess
+                                                  (Ident (Identifier "at"))
+                                                  (FieldAccess
+                                                     (Ident (Identifier "captures"))
+                                                     (Ident (Identifier "m"))))
+                                               [ NormalArg (Literal (Int 0)) ])
+                                        ])
+                                     (FuncCall
+                                        (FieldAccess
+                                           (Ident (Identifier "at"))
+                                           (FieldAccess
+                                              (Ident (Identifier "captures"))
+                                              (Ident (Identifier "m"))))
+                                        [ NormalArg (Literal (Int 1)) ]))
+                                  (Literal (String " ")))
+                               (FuncCall
+                                  (Ident (Identifier "upper"))
+                                  [ NormalArg
+                                      (FuncCall
+                                         (FieldAccess
+                                            (Ident (Identifier "at"))
+                                            (FieldAccess
+                                               (Ident (Identifier "captures"))
+                                               (Ident (Identifier "m"))))
+                                         [ NormalArg (Literal (Int 2)) ])
+                                  ])
+                           ])))
+              ])
+       , NormalArg (Literal (String "HELLO : WORLD"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace"))
+                 (Literal (String "hello world, lorem ipsum")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "(\\w+) (\\w+)")) ])
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (Block
+                        (CodeBlock
+                           [ Plus
+                               (Plus
+                                  (FuncCall
+                                     (FieldAccess
+                                        (Ident (Identifier "at"))
+                                        (FieldAccess
+                                           (Ident (Identifier "captures"))
+                                           (Ident (Identifier "m"))))
+                                     [ NormalArg (Literal (Int 1)) ])
+                                  (Literal (String " ")))
+                               (FuncCall
+                                  (FieldAccess
+                                     (Ident (Identifier "at"))
+                                     (FieldAccess
+                                        (Ident (Identifier "captures")) (Ident (Identifier "m"))))
+                                  [ NormalArg (Literal (Int 0)) ])
+                           ])))
+              ])
+       , NormalArg (Literal (String "world hello, ipsum lorem"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace"))
+                 (Literal (String "hello world, lorem ipsum")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "(\\w+) (\\w+)")) ])
+              , KeyValArg (Identifier "count") (Literal (Int 1))
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (Block
+                        (CodeBlock
+                           [ Plus
+                               (Plus
+                                  (FuncCall
+                                     (FieldAccess
+                                        (Ident (Identifier "at"))
+                                        (FieldAccess
+                                           (Ident (Identifier "captures"))
+                                           (Ident (Identifier "m"))))
+                                     [ NormalArg (Literal (Int 1)) ])
+                                  (Literal (String " ")))
+                               (FuncCall
+                                  (FieldAccess
+                                     (Ident (Identifier "at"))
+                                     (FieldAccess
+                                        (Ident (Identifier "captures")) (Ident (Identifier "m"))))
+                                  [ NormalArg (Literal (Int 0)) ])
+                           ])))
+              ])
+       , NormalArg (Literal (String "world hello, lorem ipsum"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "123 456")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "[a-z]+")) ])
+              , NormalArg (Literal (String "a"))
+              ])
+       , NormalArg (Literal (String "123 456"))
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "abc")))
+              [ NormalArg (Literal (String ""))
+              , NormalArg
+                  (FuncExpr [ NormalParam (Identifier "m") ] (Literal (String "-")))
+              ])
+       , NormalArg (Literal (String "-a-b-c-"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "abc")))
+              [ NormalArg (Literal (String ""))
+              , NormalArg
+                  (FuncExpr [ NormalParam (Identifier "m") ] (Literal (String "-")))
+              , KeyValArg (Identifier "count") (Literal (Int 1))
+              ])
+       , NormalArg (Literal (String "-abc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 23 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "123")))
+              [ NormalArg (Literal (String "abc"))
+              , NormalArg
+                  (FuncExpr [ NormalParam (Identifier "m") ] (Literal (String "")))
+              ])
+       , NormalArg (Literal (String "123"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 24 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "123")))
+              [ NormalArg (Literal (String "abc"))
+              , NormalArg
+                  (FuncExpr [ NormalParam (Identifier "m") ] (Literal (String "")))
+              , KeyValArg (Identifier "count") (Literal (Int 2))
+              ])
+       , NormalArg (Literal (String "123"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 25 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "a123b123c")))
+              [ NormalArg (Literal (String "123"))
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (Block
+                        (CodeBlock
+                           [ Plus
+                               (Plus
+                                  (FuncCall
+                                     (Ident (Identifier "str"))
+                                     [ NormalArg
+                                         (FieldAccess
+                                            (Ident (Identifier "start")) (Ident (Identifier "m")))
+                                     ])
+                                  (Literal (String "-")))
+                               (FuncCall
+                                  (Ident (Identifier "str"))
+                                  [ NormalArg
+                                      (FieldAccess
+                                         (Ident (Identifier "end")) (Ident (Identifier "m")))
+                                  ])
+                           ])))
+              ])
+       , NormalArg (Literal (String "a1-4b5-8c"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 28 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "halla warld")))
+              [ NormalArg (Literal (String "a"))
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (Block
+                        (CodeBlock
+                           [ If
+                               [ ( Equals
+                                     (FieldAccess
+                                        (Ident (Identifier "start")) (Ident (Identifier "m")))
+                                     (Literal (Int 1))
+                                 , Block (CodeBlock [ Literal (String "e") ])
+                                 )
+                               , ( Or
+                                     (Equals
+                                        (FieldAccess
+                                           (Ident (Identifier "start")) (Ident (Identifier "m")))
+                                        (Literal (Int 4)))
+                                     (Equals
+                                        (FieldAccess
+                                           (Ident (Identifier "start")) (Ident (Identifier "m")))
+                                        (Literal (Int 7)))
+                                 , Block (CodeBlock [ Literal (String "o") ])
+                                 )
+                               ]
+                           ])))
+              ])
+       , NormalArg (Literal (String "hello world"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-15.typ"
+    ( line 32 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "replace")) (Literal (String "aaa")))
+              [ NormalArg (Literal (String "a"))
+              , NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "m") ]
+                     (FuncCall
+                        (Ident (Identifier "str"))
+                        [ NormalArg
+                            (FuncCall
+                               (FieldAccess
+                                  (Ident (Identifier "len"))
+                                  (FieldAccess
+                                     (Ident (Identifier "captures")) (Ident (Identifier "m"))))
+                               [])
+                        ]))
+              ])
+       , NormalArg (Literal (String "000"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-16.out b/test/out/compiler/string-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-16.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-17.out b/test/out/compiler/string-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-17.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-18.out b/test/out/compiler/string-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-18.out
@@ -0,0 +1,420 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-18.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-18.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-18.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "str")))
+       (Literal (String "Typst, LaTeX, Word, InDesign")))
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "array")))
+       (Array
+          [ Literal (String "Typst")
+          , Literal (String "LaTeX")
+          , Literal (String "Word")
+          , Literal (String "InDesign")
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "map"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "split")) (Ident (Identifier "str")))
+                    [ NormalArg (Literal (String ",")) ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "s") ]
+                     (FuncCall
+                        (FieldAccess (Ident (Identifier "trim")) (Ident (Identifier "s")))
+                        []))
+              ])
+       , NormalArg (Ident (Identifier "array"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "trim")) (Literal (String ""))) [])
+       , NormalArg (Literal (String ""))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String " abc ")))
+              [ KeyValArg (Identifier "at") (Ident (Identifier "start")) ])
+       , NormalArg (Literal (String "abc "))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String " abc ")))
+              [ KeyValArg (Identifier "at") (Ident (Identifier "end"))
+              , KeyValArg (Identifier "repeat") (Literal (Boolean True))
+              ])
+       , NormalArg (Literal (String " abc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "  abc")))
+              [ KeyValArg (Identifier "at") (Ident (Identifier "start"))
+              , KeyValArg (Identifier "repeat") (Literal (Boolean False))
+              ])
+       , NormalArg (Literal (String "abc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "aabcaa")))
+              [ NormalArg (Literal (String "a"))
+              , KeyValArg (Identifier "repeat") (Literal (Boolean False))
+              ])
+       , NormalArg (Literal (String "abca"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "aabca")))
+              [ NormalArg (Literal (String "a"))
+              , KeyValArg (Identifier "at") (Ident (Identifier "start"))
+              ])
+       , NormalArg (Literal (String "bca"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "aabcaa")))
+              [ NormalArg (Literal (String "a"))
+              , KeyValArg (Identifier "at") (Ident (Identifier "end"))
+              , KeyValArg (Identifier "repeat") (Literal (Boolean False))
+              ])
+       , NormalArg (Literal (String "aabca"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "trim")) (Literal (String "")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex")) [ NormalArg (Literal (String ".")) ])
+              ])
+       , NormalArg (Literal (String ""))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123abc456")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              ])
+       , NormalArg (Literal (String "abc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123abc456")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              , KeyValArg (Identifier "repeat") (Literal (Boolean False))
+              ])
+       , NormalArg (Literal (String "23abc45"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123a4b5c678")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              , KeyValArg (Identifier "repeat") (Literal (Boolean True))
+              ])
+       , NormalArg (Literal (String "a4b5c"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123a4b5c678")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              , KeyValArg (Identifier "repeat") (Literal (Boolean False))
+              ])
+       , NormalArg (Literal (String "23a4b5c67"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123abc456")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              , KeyValArg (Identifier "at") (Ident (Identifier "start"))
+              ])
+       , NormalArg (Literal (String "abc456"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123abc456")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              , KeyValArg (Identifier "at") (Ident (Identifier "end"))
+              ])
+       , NormalArg (Literal (String "123abc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 20 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123abc456")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d+")) ])
+              , KeyValArg (Identifier "at") (Ident (Identifier "end"))
+              , KeyValArg (Identifier "repeat") (Literal (Boolean False))
+              ])
+       , NormalArg (Literal (String "123abc"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "123abc456")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d{1,2}$")) ])
+              , KeyValArg (Identifier "repeat") (Literal (Boolean False))
+              ])
+       , NormalArg (Literal (String "123abc4"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-18.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "trim")) (Literal (String "hello world")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex")) [ NormalArg (Literal (String ".")) ])
+              ])
+       , NormalArg (Literal (String ""))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-19.out b/test/out/compiler/string-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-19.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/string-20.out b/test/out/compiler/string-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-20.out
@@ -0,0 +1,128 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/string-20.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/string-20.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/string-20.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/string-20.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "split")) (Literal (String "abc")))
+              [ NormalArg (Literal (String "")) ])
+       , NormalArg
+           (Array
+              [ Literal (String "")
+              , Literal (String "a")
+              , Literal (String "b")
+              , Literal (String "c")
+              , Literal (String "")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-20.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "split")) (Literal (String "abc")))
+              [ NormalArg (Literal (String "b")) ])
+       , NormalArg (Array [ Literal (String "a") , Literal (String "c") ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-20.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "split")) (Literal (String "a123c")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d")) ])
+              ])
+       , NormalArg
+           (Array
+              [ Literal (String "a")
+              , Literal (String "")
+              , Literal (String "")
+              , Literal (String "c")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compiler/string-20.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "split")) (Literal (String "a123c")))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "regex"))
+                     [ NormalArg (Literal (String "\\d+")) ])
+              ])
+       , NormalArg (Array [ Literal (String "a") , Literal (String "c") ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/string-21.out b/test/out/compiler/string-21.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/string-21.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/while-00.out b/test/out/compiler/while-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/while-00.out
@@ -0,0 +1,138 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/while-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/while-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/while-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/while-00.typ"
+    ( line 3 , column 2 )
+    (Let (BasicBind (Just (Identifier "i"))) (Literal (Int 0)))
+, SoftBreak
+, Code
+    "test/typ/compiler/while-00.typ"
+    ( line 4 , column 2 )
+    (While
+       (LessThan (Ident (Identifier "i")) (Literal (Int 10)))
+       (Block
+          (Content
+             [ SoftBreak
+             , Code
+                 "test/typ/compiler/while-00.typ"
+                 ( line 5 , column 4 )
+                 (Assign
+                    (Ident (Identifier "i"))
+                    (Plus (Ident (Identifier "i")) (Literal (Int 2))))
+             , SoftBreak
+             , Code
+                 "test/typ/compiler/while-00.typ"
+                 ( line 6 , column 4 )
+                 (Ident (Identifier "i"))
+             , ParBreak
+             ])))
+, ParBreak
+, Comment
+, Code
+    "test/typ/compiler/while-00.typ"
+    ( line 10 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "iter"))) (Literal (Boolean True)))
+, SoftBreak
+, Code
+    "test/typ/compiler/while-00.typ"
+    ( line 11 , column 2 )
+    (While
+       (Ident (Identifier "iter"))
+       (Block
+          (CodeBlock
+             [ Assign
+                 (Binding (BasicBind (Just (Identifier "iter"))))
+                 (Literal (Boolean False))
+             , Literal (String "Hi.")
+             ])))
+, ParBreak
+, Code
+    "test/typ/compiler/while-00.typ"
+    ( line 16 , column 2 )
+    (While
+       (Literal (Boolean False))
+       (Block (CodeBlock [ Ident (Identifier "dont-care") ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [2]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [4]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [6]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [8]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [10]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [Hi.]), 
+  parbreak(), 
+  parbreak() }
diff --git a/test/out/compiler/while-01.out b/test/out/compiler/while-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/while-01.out
@@ -0,0 +1,95 @@
+--- parse tree ---
+[ Code
+    "test/typ/compiler/while-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/while-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/while-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, SoftBreak
+, Code
+    "test/typ/compiler/while-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (While (Literal (Boolean False)) (Block (CodeBlock [])))
+       , NormalArg (Literal None)
+       ])
+, ParBreak
+, Code
+    "test/typ/compiler/while-01.typ"
+    ( line 7 , column 2 )
+    (Let (BasicBind (Just (Identifier "i"))) (Literal (Int 0)))
+, SoftBreak
+, Code
+    "test/typ/compiler/while-01.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg
+                  (While
+                     (LessThan (Ident (Identifier "i")) (Literal (Int 1)))
+                     (Block
+                        (Content
+                           [ Code
+                               "test/typ/compiler/while-01.typ"
+                               ( line 8 , column 26 )
+                               (Assign
+                                  (Ident (Identifier "i"))
+                                  (Plus (Ident (Identifier "i")) (Literal (Int 1))))
+                           ])))
+              ])
+       , NormalArg (Literal (String "content"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compiler/while-02.out b/test/out/compiler/while-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/while-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/while-03.out b/test/out/compiler/while-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/while-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/while-04.out b/test/out/compiler/while-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/while-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compiler/while-05.out b/test/out/compiler/while-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compiler/while-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-00.out b/test/out/compute/calc-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-00.out
@@ -0,0 +1,181 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int")) [ NormalArg (Literal (Boolean False)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int")) [ NormalArg (Literal (Boolean True)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int")) [ NormalArg (Literal (Int 10)) ])
+       , NormalArg (Literal (Int 10))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int")) [ NormalArg (Literal (String "150")) ])
+       , NormalArg (Literal (Int 150))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Divided (Literal (Int 10)) (Literal (Int 3))) ])
+       , NormalArg (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "float")) [ NormalArg (Literal (Int 10)) ])
+       , NormalArg (Literal (Float 10.0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "float"))
+              [ NormalArg
+                  (Times
+                     (Literal (Numeric 50.0 Percent)) (Literal (Numeric 30.0 Percent)))
+              ])
+       , NormalArg (Literal (Float 0.15))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "float"))
+              [ NormalArg (Literal (String "31.4e-1")) ])
+       , NormalArg (Literal (Float 3.14))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "float")) [ NormalArg (Literal (Int 10)) ])
+              ])
+       , NormalArg (Literal (String "float"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-01.out b/test/out/compute/calc-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-01.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compute/calc-01.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "round")) (Ident (Identifier "calc")))
+              [ NormalArg
+                  (FieldAccess (Ident (Identifier "e")) (Ident (Identifier "calc")))
+              , KeyValArg (Identifier "digits") (Literal (Int 2))
+              ])
+       , NormalArg (Literal (Float 2.72))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "round")) (Ident (Identifier "calc")))
+              [ NormalArg
+                  (FieldAccess (Ident (Identifier "pi")) (Ident (Identifier "calc")))
+              , KeyValArg (Identifier "digits") (Literal (Int 2))
+              ])
+       , NormalArg (Literal (Float 3.14))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-02.out b/test/out/compute/calc-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-03.out b/test/out/compute/calc-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-04.out b/test/out/compute/calc-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-05.out b/test/out/compute/calc-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-06.out b/test/out/compute/calc-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-06.out
@@ -0,0 +1,157 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-06.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "abs")) (Ident (Identifier "calc")))
+              [ NormalArg (Negated (Literal (Int 3))) ])
+       , NormalArg (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-06.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "abs")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 3)) ])
+       , NormalArg (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-06.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "abs")) (Ident (Identifier "calc")))
+              [ NormalArg (Negated (Literal (Float 0.0))) ])
+       , NormalArg (Literal (Float 0.0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-06.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "abs")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Float 0.0)) ])
+       , NormalArg (Negated (Literal (Float 0.0)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-06.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "abs")) (Ident (Identifier "calc")))
+              [ NormalArg (Negated (Literal (Float 3.14))) ])
+       , NormalArg (Literal (Float 3.14))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-06.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "abs")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Numeric 50.0 Percent)) ])
+       , NormalArg (Literal (Numeric 50.0 Percent))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-06.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "abs")) (Ident (Identifier "calc")))
+              [ NormalArg (Negated (Literal (Numeric 25.0 Percent))) ])
+       , NormalArg (Literal (Numeric 25.0 Percent))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-07.out b/test/out/compute/calc-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-08.out b/test/out/compute/calc-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-08.out
@@ -0,0 +1,109 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-08.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "even")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-08.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "odd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-08.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "odd")) (Ident (Identifier "calc")))
+              [ NormalArg (Negated (Literal (Int 1))) ])
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-08.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "even")) (Ident (Identifier "calc")))
+              [ NormalArg (Negated (Literal (Int 11))) ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-09.out b/test/out/compute/calc-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-09.out
@@ -0,0 +1,133 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-09.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-09.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 3)) ])
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-09.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5))
+              , NormalArg (Negated (Literal (Int 3)))
+              ])
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-09.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Float 22.5))
+              , NormalArg (Literal (Int 10))
+              ])
+       , NormalArg (Literal (Float 2.5))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-09.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 9)) , NormalArg (Literal (Float 4.5)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [1]), 
+  text(body: [ /= ]), 
+  text(body: [0]), 
+  text(body: [)]), 
+  parbreak() }
diff --git a/test/out/compute/calc-10.out b/test/out/compute/calc-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-11.out b/test/out/compute/calc-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-12.out b/test/out/compute/calc-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-12.out
@@ -0,0 +1,129 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-12.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-12.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-12.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-12.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "quo")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-12.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "quo")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 3)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-12.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "quo")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5))
+              , NormalArg (Negated (Literal (Int 3)))
+              ])
+       , NormalArg (Negated (Literal (Int 1)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-12.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "quo")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Float 22.5))
+              , NormalArg (Literal (Int 10))
+              ])
+       , NormalArg (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-12.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "quo")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 9)) , NormalArg (Literal (Float 4.5)) ])
+       , NormalArg (Literal (Int 2))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-13.out b/test/out/compute/calc-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-13.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-14.out b/test/out/compute/calc-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-14.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-15.out b/test/out/compute/calc-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-15.out
@@ -0,0 +1,117 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-15.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-15.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-15.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-15.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "min")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 2))
+              , NormalArg (Negated (Literal (Int 4)))
+              ])
+       , NormalArg (Negated (Literal (Int 4)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-15.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "min")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Float 3.5))
+              , NormalArg (Literal (Float 100.0))
+              , NormalArg (Negated (Literal (Float 0.1)))
+              , NormalArg (Literal (Int 3))
+              ])
+       , NormalArg (Negated (Literal (Float 0.1)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-15.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "max")) (Ident (Identifier "calc")))
+              [ NormalArg (Negated (Literal (Int 3)))
+              , NormalArg (Literal (Int 11))
+              ])
+       , NormalArg (Literal (Int 11))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-15.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "min")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (String "hi")) ])
+       , NormalArg (Literal (String "hi"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-16.out b/test/out/compute/calc-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-16.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-16.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-16.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-16.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-16.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "pow")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 10)) , NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-16.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "pow")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 2)) , NormalArg (Literal (Int 4)) ])
+       , NormalArg (Literal (Int 16))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-17.out b/test/out/compute/calc-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-17.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-18.out b/test/out/compute/calc-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-18.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-19.out b/test/out/compute/calc-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-19.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-20.out b/test/out/compute/calc-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-20.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-21.out b/test/out/compute/calc-21.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-21.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-22.out b/test/out/compute/calc-22.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-22.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-23.out b/test/out/compute/calc-23.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-23.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-24.out b/test/out/compute/calc-24.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-24.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-25.out b/test/out/compute/calc-25.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-25.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-26.out b/test/out/compute/calc-26.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-26.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-26.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-26.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-26.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-26.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "fact")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-26.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "fact")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) ])
+       , NormalArg (Literal (Int 120))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-27.out b/test/out/compute/calc-27.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-27.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-28.out b/test/out/compute/calc-28.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-28.out
@@ -0,0 +1,109 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-28.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-28.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-28.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-28.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "perm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-28.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "perm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 3)) ])
+       , NormalArg (Literal (Int 60))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-28.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "perm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 5)) ])
+       , NormalArg (Literal (Int 120))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-28.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "perm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 6)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-29.out b/test/out/compute/calc-29.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-29.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-30.out b/test/out/compute/calc-30.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-30.out
@@ -0,0 +1,125 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-30.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-30.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-30.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-30.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "binom")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-30.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "binom")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 3)) ])
+       , NormalArg (Literal (Int 10))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-30.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "binom")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 5)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-30.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "binom")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 5)) , NormalArg (Literal (Int 6)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-30.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "binom")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 6)) , NormalArg (Literal (Int 2)) ])
+       , NormalArg (Literal (Int 15))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-31.out b/test/out/compute/calc-31.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-31.out
@@ -0,0 +1,161 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-31.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-31.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-31.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-31.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "gcd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 112)) , NormalArg (Literal (Int 77)) ])
+       , NormalArg (Literal (Int 7))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-31.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "gcd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 12)) , NormalArg (Literal (Int 96)) ])
+       , NormalArg (Literal (Int 12))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-31.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "gcd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 13)) , NormalArg (Literal (Int 9)) ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-31.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "gcd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 13))
+              , NormalArg (Negated (Literal (Int 9)))
+              ])
+       , NormalArg (Literal (Int 1))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-31.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "gcd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 272557))
+              , NormalArg (Literal (Int 272557))
+              ])
+       , NormalArg (Literal (Int 272557))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-31.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "gcd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-31.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "gcd")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 7)) , NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 7))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-32.out b/test/out/compute/calc-32.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-32.out
@@ -0,0 +1,161 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-32.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-32.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-32.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-32.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lcm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 112)) , NormalArg (Literal (Int 77)) ])
+       , NormalArg (Literal (Int 1232))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-32.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lcm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 12)) , NormalArg (Literal (Int 96)) ])
+       , NormalArg (Literal (Int 96))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-32.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lcm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 13)) , NormalArg (Literal (Int 9)) ])
+       , NormalArg (Literal (Int 117))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-32.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lcm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 13))
+              , NormalArg (Negated (Literal (Int 9)))
+              ])
+       , NormalArg (Literal (Int 117))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-32.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lcm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 272557))
+              , NormalArg (Literal (Int 272557))
+              ])
+       , NormalArg (Literal (Int 272557))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-32.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lcm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-32.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lcm")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 8)) , NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Int 0))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-33.out b/test/out/compute/calc-33.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-33.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-34.out b/test/out/compute/calc-34.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-34.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-35.out b/test/out/compute/calc-35.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-35.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-36.out b/test/out/compute/calc-36.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-36.out
@@ -0,0 +1,230 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/calc-36.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/calc-36.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/calc-36.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range")) [ NormalArg (Literal (Int 4)) ])
+       , NormalArg
+           (Array
+              [ Literal (Int 0)
+              , Literal (Int 1)
+              , Literal (Int 2)
+              , Literal (Int 3)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 4)) ])
+       , NormalArg
+           (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Negated (Literal (Int 4)))
+              , NormalArg (Literal (Int 2))
+              ])
+       , NormalArg
+           (Array
+              [ Negated (Literal (Int 4))
+              , Negated (Literal (Int 3))
+              , Negated (Literal (Int 2))
+              , Negated (Literal (Int 1))
+              , Literal (Int 0)
+              , Literal (Int 1)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 10)) , NormalArg (Literal (Int 5)) ])
+       , NormalArg (Array [])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 10))
+              , KeyValArg (Identifier "step") (Literal (Int 3))
+              ])
+       , NormalArg
+           (Array
+              [ Literal (Int 0)
+              , Literal (Int 3)
+              , Literal (Int 6)
+              , Literal (Int 9)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 1))
+              , NormalArg (Literal (Int 4))
+              , KeyValArg (Identifier "step") (Literal (Int 1))
+              ])
+       , NormalArg
+           (Array [ Literal (Int 1) , Literal (Int 2) , Literal (Int 3) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 1))
+              , NormalArg (Literal (Int 8))
+              , KeyValArg (Identifier "step") (Literal (Int 2))
+              ])
+       , NormalArg
+           (Array
+              [ Literal (Int 1)
+              , Literal (Int 3)
+              , Literal (Int 5)
+              , Literal (Int 7)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 5))
+              , NormalArg (Literal (Int 2))
+              , KeyValArg (Identifier "step") (Negated (Literal (Int 1)))
+              ])
+       , NormalArg
+           (Array [ Literal (Int 5) , Literal (Int 4) , Literal (Int 3) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/calc-36.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 10))
+              , NormalArg (Literal (Int 0))
+              , KeyValArg (Identifier "step") (Negated (Literal (Int 3)))
+              ])
+       , NormalArg
+           (Array
+              [ Literal (Int 10)
+              , Literal (Int 7)
+              , Literal (Int 4)
+              , Literal (Int 1)
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/calc-37.out b/test/out/compute/calc-37.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-37.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-38.out b/test/out/compute/calc-38.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-38.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-39.out b/test/out/compute/calc-39.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-39.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/calc-40.out b/test/out/compute/calc-40.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/calc-40.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-00.out b/test/out/compute/construct-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-00.out
@@ -0,0 +1,193 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/construct-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/construct-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/construct-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/construct-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (Numeric 0.0 Percent))
+              , NormalArg (Literal (Numeric 30.0 Percent))
+              , NormalArg (Literal (Numeric 70.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (String "004db3")) ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compute/construct-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (Int 255))
+              , NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Numeric 50.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (String "ff000080")) ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/compute/construct-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lighten"))
+                 (FuncCall
+                    (Ident (Identifier "rgb"))
+                    [ NormalArg (Literal (Int 25))
+                    , NormalArg (Literal (Int 35))
+                    , NormalArg (Literal (Int 45))
+                    ]))
+              [ NormalArg (Literal (Numeric 10.0 Percent)) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (Int 48))
+              , NormalArg (Literal (Int 57))
+              , NormalArg (Literal (Int 66))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/construct-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "darken"))
+                 (FuncCall
+                    (Ident (Identifier "rgb"))
+                    [ NormalArg (Literal (Int 40))
+                    , NormalArg (Literal (Int 30))
+                    , NormalArg (Literal (Int 20))
+                    ]))
+              [ NormalArg (Literal (Numeric 10.0 Percent)) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (Int 36))
+              , NormalArg (Literal (Int 27))
+              , NormalArg (Literal (Int 18))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/construct-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "negate"))
+                 (FuncCall
+                    (Ident (Identifier "rgb"))
+                    [ NormalArg (Literal (String "#133337")) ]))
+              [])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (Int 236))
+              , NormalArg (Literal (Int 204))
+              , NormalArg (Literal (Int 200))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/construct-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "lighten")) (Ident (Identifier "white")))
+              [ NormalArg (Literal (Numeric 100.0 Percent)) ])
+       , NormalArg (Ident (Identifier "white"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [rgb(0%,30%,70%,100%)]), 
+  text(body: [ /= ]), 
+  text(body: [rgb(0%,30%,70%,100%)]), 
+  text(body: [)]), 
+  parbreak(), 
+  text(body: [❌(]), 
+  text(body: [rgb(100%,0%,0%,50%)]), 
+  text(body: [ /= ]), 
+  text(body: [rgb(100%,0%,0%,50%)]), 
+  text(body: [)]), 
+  parbreak(), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/construct-01.out b/test/out/compute/construct-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-01.out
@@ -0,0 +1,76 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/construct-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/construct-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/construct-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compute/construct-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "luma")) [ NormalArg (Literal (Int 0)) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "luma"))
+                     [ NormalArg (Literal (Numeric 80.0 Percent)) ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  stack(children: (rect(fill: luma(0%)), 
+                   rect(fill: luma(80%))), 
+        dir: ltr), 
+  parbreak() }
diff --git a/test/out/compute/construct-02.out b/test/out/compute/construct-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-03.out b/test/out/compute/construct-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-04.out b/test/out/compute/construct-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-05.out b/test/out/compute/construct-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-06.out b/test/out/compute/construct-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-07.out b/test/out/compute/construct-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-07.out
@@ -0,0 +1,121 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/construct-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/construct-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/construct-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/construct-07.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "envelope")))
+       (FuncCall
+          (Ident (Identifier "symbol"))
+          [ NormalArg (Literal (String "\128386"))
+          , NormalArg
+              (Array [ Literal (String "stamped") , Literal (String "\128387") ])
+          , NormalArg
+              (Array
+                 [ Literal (String "stamped.pen") , Literal (String "\128390") ])
+          , NormalArg
+              (Array
+                 [ Literal (String "lightning") , Literal (String "\128388") ])
+          , NormalArg
+              (Array [ Literal (String "fly") , Literal (String "\128389") ])
+          ]))
+, ParBreak
+, Code
+    "test/typ/compute/construct-07.typ"
+    ( line 11 , column 2 )
+    (Ident (Identifier "envelope"))
+, SoftBreak
+, Code
+    "test/typ/compute/construct-07.typ"
+    ( line 12 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "stamped")) (Ident (Identifier "envelope")))
+, SoftBreak
+, Code
+    "test/typ/compute/construct-07.typ"
+    ( line 13 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "pen")) (Ident (Identifier "envelope")))
+, SoftBreak
+, Code
+    "test/typ/compute/construct-07.typ"
+    ( line 14 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "pen"))
+       (FieldAccess
+          (Ident (Identifier "stamped")) (Ident (Identifier "envelope"))))
+, SoftBreak
+, Code
+    "test/typ/compute/construct-07.typ"
+    ( line 15 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "lightning")) (Ident (Identifier "envelope")))
+, SoftBreak
+, Code
+    "test/typ/compute/construct-07.typ"
+    ( line 16 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "fly")) (Ident (Identifier "envelope")))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [🖂]), 
+  text(body: [
+]), 
+  text(body: [🖃]), 
+  text(body: [
+]), 
+  text(body: [🖆]), 
+  text(body: [
+]), 
+  text(body: [🖆]), 
+  text(body: [
+]), 
+  text(body: [🖄]), 
+  text(body: [
+]), 
+  text(body: [🖅]), 
+  parbreak() }
diff --git a/test/out/compute/construct-08.out b/test/out/compute/construct-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-09.out b/test/out/compute/construct-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-09.out
@@ -0,0 +1,94 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/construct-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/construct-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/construct-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/construct-09.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "str")) [ NormalArg (Literal (Int 123)) ])
+       , NormalArg (Literal (String "123"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/construct-09.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "str")) [ NormalArg (Literal (Float 50.14)) ])
+       , NormalArg (Literal (String "50.14"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/construct-09.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (GreaterThan
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "len"))
+                    (FuncCall
+                       (Ident (Identifier "str"))
+                       [ NormalArg (Divided (Literal (Int 10)) (Literal (Int 3))) ]))
+                 [])
+              (Literal (Int 10)))
+       , NormalArg (Literal (Boolean True))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/construct-10.out b/test/out/compute/construct-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/construct-11.out b/test/out/compute/construct-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/construct-11.out
@@ -0,0 +1,59 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/construct-11.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/construct-11.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/construct-11.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compute/construct-11.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "assert"))
+       [ NormalArg
+           (Equals
+              (FuncCall
+                 (Ident (Identifier "range"))
+                 [ NormalArg (Literal (Int 2)) , NormalArg (Literal (Int 5)) ])
+              (Array [ Literal (Int 2) , Literal (Int 3) , Literal (Int 4) ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/compute/data-00.out b/test/out/compute/data-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-00.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/data-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/data-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/data-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/data-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "data")))
+       (FuncCall
+          (Ident (Identifier "read"))
+          [ NormalArg (Literal (String "test/assets/files/hello.txt")) ]))
+, SoftBreak
+, Code
+    "test/typ/compute/data-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "data"))
+       , NormalArg (Literal (String "Hello, world!"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/data-01.out b/test/out/compute/data-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/data-02.out b/test/out/compute/data-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/data-03.out b/test/out/compute/data-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-03.out
@@ -0,0 +1,126 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/data-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/data-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/data-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/compute/data-03.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-03.typ"
+    ( line 5 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "data")))
+       (FuncCall
+          (Ident (Identifier "csv"))
+          [ NormalArg (Literal (String "test/assets/files/zoo.csv")) ]))
+, SoftBreak
+, Code
+    "test/typ/compute/data-03.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "cells")))
+       (Plus
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "map"))
+                (FuncCall
+                   (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "data")))
+                   [ NormalArg (Literal (Int 0)) ]))
+             [ NormalArg (Ident (Identifier "strong")) ])
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "flatten"))
+                (FuncCall
+                   (FieldAccess
+                      (Ident (Identifier "slice")) (Ident (Identifier "data")))
+                   [ NormalArg (Literal (Int 1)) ]))
+             [])))
+, SoftBreak
+, Code
+    "test/typ/compute/data-03.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "columns")
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "len"))
+                 (FuncCall
+                    (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "data")))
+                    [ NormalArg (Literal (Int 0)) ]))
+              [])
+       , SpreadArg (Ident (Identifier "cells"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  table(children: (strong(body: [Name]), 
+                   strong(body: [Species]), 
+                   strong(body: [Weight]), 
+                   strong(body: [Length]), 
+                   [Debby], 
+                   [Rhinoceros], 
+                   [1900kg], 
+                   [390cm], 
+                   [Fluffy], 
+                   [Tiger], 
+                   [115kg], 
+                   [310cm], 
+                   [Sleepy], 
+                   [Dolphin], 
+                   [150kg], 
+                   [180cm]), 
+        columns: 4), 
+  parbreak() }
diff --git a/test/out/compute/data-04.out b/test/out/compute/data-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/data-05.out b/test/out/compute/data-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/data-06.out b/test/out/compute/data-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-06.out
@@ -0,0 +1,106 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/data-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/data-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/data-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/data-06.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "data")))
+       (FuncCall
+          (Ident (Identifier "json"))
+          [ NormalArg (Literal (String "test/assets/files/zoo.json")) ]))
+, SoftBreak
+, Code
+    "test/typ/compute/data-06.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "len")) (Ident (Identifier "data")))
+              [])
+       , NormalArg (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-06.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "name"))
+              (FuncCall
+                 (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "data")))
+                 [ NormalArg (Literal (Int 0)) ]))
+       , NormalArg (Literal (String "Debby"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-06.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "weight"))
+              (FuncCall
+                 (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "data")))
+                 [ NormalArg (Literal (Int 2)) ]))
+       , NormalArg (Literal (Int 150))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/data-07.out b/test/out/compute/data-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/data-08.out b/test/out/compute/data-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-08.out
@@ -0,0 +1,173 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/data-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/data-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/data-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "data")))
+       (FuncCall
+          (Ident (Identifier "toml"))
+          [ NormalArg (Literal (String "test/assets/files/toml-types.toml"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "string")) (Ident (Identifier "data")))
+       , NormalArg (Literal (String "wonderful"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "integer")) (Ident (Identifier "data")))
+       , NormalArg (Literal (Int 42))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "float")) (Ident (Identifier "data")))
+       , NormalArg (Literal (Float 3.14))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "boolean")) (Ident (Identifier "data")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "date_time")) (Ident (Identifier "data")))
+       , NormalArg (Literal (String "2023-02-01T15:38:57Z"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "array")) (Ident (Identifier "data")))
+       , NormalArg
+           (Array
+              [ Literal (Int 1)
+              , Literal (String "string")
+              , Literal (Float 3.0)
+              , Literal (Boolean False)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "inline_table")) (Ident (Identifier "data")))
+       , NormalArg
+           (Dict
+              [ ( Identifier "first" , Literal (String "amazing") )
+              , ( Identifier "second" , Literal (String "greater") )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "element"))
+              (FieldAccess
+                 (Ident (Identifier "table")) (Ident (Identifier "data"))))
+       , NormalArg (Literal (Int 5))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-08.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "others"))
+              (FieldAccess
+                 (Ident (Identifier "table")) (Ident (Identifier "data"))))
+       , NormalArg
+           (Array
+              [ Literal (Boolean False)
+              , Literal (String "indeed")
+              , Literal (Int 7)
+              ])
+       ])
+, ParBreak
+]
+"test/typ/compute/data-08.typ" (line 3, column 2):
+unimplemented toml
diff --git a/test/out/compute/data-09.out b/test/out/compute/data-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/data-10.out b/test/out/compute/data-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-10.out
@@ -0,0 +1,209 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/data-10.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/data-10.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/data-10.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "data")))
+       (FuncCall
+          (Ident (Identifier "yaml"))
+          [ NormalArg (Literal (String "test/assets/files/yaml-types.yaml"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "len")) (Ident (Identifier "data")))
+              [])
+       , NormalArg (Literal (Int 7))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "null_key")) (Ident (Identifier "data")))
+       , NormalArg (Array [ Literal None , Literal None ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "string")) (Ident (Identifier "data")))
+       , NormalArg (Literal (String "text"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "integer")) (Ident (Identifier "data")))
+       , NormalArg (Literal (Int 5))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "float")) (Ident (Identifier "data")))
+       , NormalArg (Literal (Float 1.12))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "mapping")) (Ident (Identifier "data")))
+       , NormalArg
+           (Dict
+              [ ( Identifier "1" , Literal (String "one") )
+              , ( Identifier "2" , Literal (String "two") )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "seq")) (Ident (Identifier "data")))
+       , NormalArg
+           (Array
+              [ Literal (Int 1)
+              , Literal (Int 2)
+              , Literal (Int 3)
+              , Literal (Int 4)
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess
+              (Ident (Identifier "bool")) (Ident (Identifier "data")))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/data-10.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "contains"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "keys")) (Ident (Identifier "data")))
+                    []))
+              [ NormalArg (Literal (String "true")) ])
+       , NormalArg (Literal (Boolean False))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [8]), 
+  text(body: [ /= ]), 
+  text(body: [7]), 
+  text(body: [)]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [❌(]), 
+  text(body: [true]), 
+  text(body: [ /= ]), 
+  text(body: [false]), 
+  text(body: [)]), 
+  parbreak() }
diff --git a/test/out/compute/data-11.out b/test/out/compute/data-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/data-12.out b/test/out/compute/data-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-12.out
@@ -0,0 +1,113 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/data-12.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/data-12.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/data-12.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/data-12.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "data")))
+       (FuncCall
+          (Ident (Identifier "xml"))
+          [ NormalArg (Literal (String "test/assets/files/data.xml")) ]))
+, SoftBreak
+, Code
+    "test/typ/compute/data-12.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "data"))
+       , NormalArg
+           (Array
+              [ Dict
+                  [ ( Identifier "tag" , Literal (String "data") )
+                  , ( Identifier "attrs" , Dict [] )
+                  , ( Identifier "children"
+                    , Array
+                        [ Literal (String "\n  ")
+                        , Dict
+                            [ ( Identifier "tag" , Literal (String "hello") )
+                            , ( Identifier "attrs"
+                              , Dict [ ( Identifier "name" , Literal (String "hi") ) ]
+                              )
+                            , ( Identifier "children" , Array [ Literal (String "1") ] )
+                            ]
+                        , Literal (String "\n  ")
+                        , Dict
+                            [ ( Identifier "tag" , Literal (String "data") )
+                            , ( Identifier "attrs" , Dict [] )
+                            , ( Identifier "children"
+                              , Array
+                                  [ Literal (String "\n    ")
+                                  , Dict
+                                      [ ( Identifier "tag" , Literal (String "hello") )
+                                      , ( Identifier "attrs" , Dict [] )
+                                      , ( Identifier "children"
+                                        , Array [ Literal (String "World") ]
+                                        )
+                                      ]
+                                  , Literal (String "\n    ")
+                                  , Dict
+                                      [ ( Identifier "tag" , Literal (String "hello") )
+                                      , ( Identifier "attrs" , Dict [] )
+                                      , ( Identifier "children"
+                                        , Array [ Literal (String "World") ]
+                                        )
+                                      ]
+                                  , Literal (String "\n  ")
+                                  ]
+                              )
+                            ]
+                        , Literal (String "\n")
+                        ]
+                    )
+                  ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/data-13.out b/test/out/compute/data-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/data-13.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-00.out b/test/out/compute/foundations-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-00.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/foundations-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/foundations-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/foundations-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (String "integer"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (Ident (Identifier "ltr")) ])
+       , NormalArg (Literal (String "direction"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (Divided (Literal (Int 10)) (Literal (Int 3))) ])
+       , NormalArg (Literal (String "float"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/foundations-01.out b/test/out/compute/foundations-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-01.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/foundations-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/foundations-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/foundations-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-01.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "repr"))
+              [ NormalArg (Ident (Identifier "ltr")) ])
+       , NormalArg (Literal (String "ltr"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "repr"))
+              [ NormalArg
+                  (Array
+                     [ Literal (Int 1) , Literal (Int 2) , Literal (Boolean False) ])
+              ])
+       , NormalArg (Literal (String "(1, 2, false)"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/foundations-02.out b/test/out/compute/foundations-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-03.out b/test/out/compute/foundations-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-04.out b/test/out/compute/foundations-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-05.out b/test/out/compute/foundations-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-06.out b/test/out/compute/foundations-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-07.out b/test/out/compute/foundations-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-08.out b/test/out/compute/foundations-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-09.out b/test/out/compute/foundations-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-10.out b/test/out/compute/foundations-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-11.out b/test/out/compute/foundations-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-12.out b/test/out/compute/foundations-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-12.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/foundations-12.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/foundations-12.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/foundations-12.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/foundations-12.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "assert"))
+       [ NormalArg (GreaterThan (Literal (Int 5)) (Literal (Int 3))) ])
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-12.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "eq")) (Ident (Identifier "assert")))
+       [ NormalArg (Literal (Int 15)) , NormalArg (Literal (Int 15)) ])
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-12.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "ne")) (Ident (Identifier "assert")))
+       [ NormalArg (Literal (Int 10)) , NormalArg (Literal (Int 12)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/compute/foundations-13.out b/test/out/compute/foundations-13.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-13.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/foundations-13.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/foundations-13.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/foundations-13.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compute/foundations-13.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type")) [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (String "integer"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-13.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (Ident (Identifier "ltr")) ])
+       , NormalArg (Literal (String "direction"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-13.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (Divided (Literal (Int 10)) (Literal (Int 3))) ])
+       , NormalArg (Literal (String "float"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/compute/foundations-14.out b/test/out/compute/foundations-14.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-14.out
@@ -0,0 +1,56 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/foundations-14.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/foundations-14.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/foundations-14.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-14.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "eval"))
+       [ NormalArg
+           (Plus (Literal (String "[_Hello")) (Literal (String " World!_]")))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  emph(body: text(body: [Hello World!])), 
+  parbreak() }
diff --git a/test/out/compute/foundations-15.out b/test/out/compute/foundations-15.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-15.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-16.out b/test/out/compute/foundations-16.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-16.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/compute/foundations-16.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compute/foundations-16.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compute/foundations-16.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/compute/foundations-16.typ"
+    ( line 2 , column 2 )
+    (Show
+       (Just (Ident (Identifier "raw")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (FuncCall
+             (Ident (Identifier "text"))
+             [ KeyValArg (Identifier "font") (Literal (String "PT Sans"))
+             , NormalArg
+                 (FuncCall
+                    (Ident (Identifier "eval"))
+                    [ NormalArg
+                        (Plus
+                           (Plus
+                              (Literal (String "["))
+                              (FieldAccess
+                                 (Ident (Identifier "text")) (Ident (Identifier "it"))))
+                           (Literal (String "]")))
+                    ])
+             ])))
+, ParBreak
+, Text "Interacting"
+, SoftBreak
+, RawBlock "" "#set text(blue)\nBlue #move(dy: -0.15em)[\127754]\n"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Interacting
+]), 
+  text(body: { text(body: [
+Blue ], 
+                    color: rgb(0%,45%,85%,100%)), 
+               move(body: text(body: [🌊], 
+                               color: rgb(0%,45%,85%,100%)), 
+                    dy: -0.15em), 
+               parbreak() }, 
+       font: "PT Sans"), 
+  parbreak() }
diff --git a/test/out/compute/foundations-17.out b/test/out/compute/foundations-17.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-17.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-18.out b/test/out/compute/foundations-18.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-18.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-19.out b/test/out/compute/foundations-19.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-19.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-20.out b/test/out/compute/foundations-20.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-20.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-21.out b/test/out/compute/foundations-21.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-21.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/compute/foundations-22.out b/test/out/compute/foundations-22.out
new file mode 100644
--- /dev/null
+++ b/test/out/compute/foundations-22.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/align-00.out b/test/out/layout/align-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/align-00.out
@@ -0,0 +1,165 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/align-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/align-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/align-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/align-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "left"))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "square"))
+                     [ KeyValArg (Identifier "size") (Literal (Numeric 15.0 Pt))
+                     , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "center"))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "square"))
+                     [ KeyValArg (Identifier "size") (Literal (Numeric 20.0 Pt))
+                     , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "right"))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "square"))
+                     [ KeyValArg (Identifier "size") (Literal (Numeric 15.0 Pt))
+                     , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+                     ])
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg
+           (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "bottom"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "stack"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "align"))
+                     [ NormalArg (Ident (Identifier "center"))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "rect"))
+                            [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                            , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+                     , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+                     ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  stack(children: (align(alignment: left, 
+                         body: square(fill: rgb(13%,61%,67%,100%), 
+                                      size: 15.0pt)), 
+                   align(alignment: center, 
+                         body: square(fill: rgb(13%,61%,67%,100%), 
+                                      size: 20.0pt)), 
+                   align(alignment: right, 
+                         body: square(fill: rgb(13%,61%,67%,100%), 
+                                      size: 15.0pt))), 
+        dir: ltr), 
+  text(body: [
+]), 
+  align(alignment: Axes(center, horizon), 
+        body: rect(fill: rgb(13%,61%,67%,100%), 
+                   height: 10.0pt)), 
+  text(body: [
+]), 
+  align(alignment: bottom, 
+        body: stack(children: (align(alignment: center, 
+                                     body: rect(fill: rgb(18%,80%,25%,100%), 
+                                                height: 10.0pt)), 
+                               rect(fill: rgb(100%,25%,21%,100%), 
+                                    height: 10.0pt, 
+                                    width: 100%)))), 
+  parbreak() }
diff --git a/test/out/layout/align-01.out b/test/out/layout/align-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/align-01.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/align-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/align-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/align-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/align-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , BlockArg
+           [ SoftBreak
+           , Text "Lorem"
+           , Space
+           , Text "Ipsum"
+           , ParBreak
+           , Text "Dolor"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  align(alignment: center, 
+        body: { text(body: [
+Lorem Ipsum]), 
+                parbreak(), 
+                text(body: [Dolor]), 
+                parbreak() }), 
+  parbreak() }
diff --git a/test/out/layout/align-02.out b/test/out/layout/align-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/align-02.out
@@ -0,0 +1,134 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/align-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/align-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/align-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/align-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rotate"))
+       [ NormalArg (Negated (Literal (Numeric 30.0 Deg)))
+       , KeyValArg
+           (Identifier "origin")
+           (Plus (Ident (Identifier "end")) (Ident (Identifier "horizon")))
+       , BlockArg [ Text "Hello" ]
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/align-02.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "de")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-02.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "start"))
+       , BlockArg [ Text "Start" ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-02.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "end"))
+       , BlockArg [ Text "Ende" ]
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/align-02.typ"
+    ( line 9 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ar")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-02.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "start"))
+       , BlockArg [ Text "\1610\1576\1583\1571" ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-02.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "end"))
+       , BlockArg [ Text "\1606\1607\1575\1610\1577" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  rotate(angle: -30.0deg, 
+         body: text(body: [Hello]), 
+         origin: Axes(end, horizon)), 
+  parbreak(), 
+  text(body: [
+], lang: "de"), 
+  align(alignment: start, 
+        body: text(body: [Start], 
+                   lang: "de")), 
+  text(body: [
+], lang: "de"), 
+  align(alignment: end, 
+        body: text(body: [Ende], 
+                   lang: "de")), 
+  parbreak(), 
+  text(body: [
+], lang: "ar"), 
+  align(alignment: start, 
+        body: text(body: [يبدأ], 
+                   lang: "ar")), 
+  text(body: [
+], lang: "ar"), 
+  align(alignment: end, 
+        body: text(body: [نهاية], 
+                   lang: "ar")), 
+  parbreak() }
diff --git a/test/out/layout/align-03.out b/test/out/layout/align-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/align-03.out
@@ -0,0 +1,92 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/align-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/align-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/align-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/align-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (Ident (Identifier "center")) ])
+       , NormalArg (Literal (String "alignment"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg (Ident (Identifier "horizon")) ])
+       , NormalArg (Literal (String "alignment"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/align-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type"))
+              [ NormalArg
+                  (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+              ])
+       , NormalArg (Literal (String "2d alignment"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/layout/align-04.out b/test/out/layout/align-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/align-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/align-05.out b/test/out/layout/align-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/align-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/block-sizing-00.out b/test/out/layout/block-sizing-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/block-sizing-00.out
@@ -0,0 +1,118 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/block-sizing-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/block-sizing-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/block-sizing-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/block-sizing-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/block-sizing-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center")) ])
+, ParBreak
+, Code
+    "test/typ/layout/block-sizing-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 10)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/block-sizing-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 80.0 Percent))
+       , KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "aqua"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/block-sizing-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 6)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/block-sizing-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "breakable") (Literal (Boolean False))
+       , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "inset") (Literal (Numeric 4.0 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "aqua"))
+       , NormalArg
+           (Plus
+              (FuncCall
+                 (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 8)) ])
+              (FuncCall (Ident (Identifier "colbreak")) []))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do]), 
+  text(body: [
+]), 
+  block(fill: rgb(49%,85%,100%,100%), 
+        height: 60.0pt, 
+        width: 80%), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur]), 
+  text(body: [
+]), 
+  block(body: { [Lorem ipsum dolor sit amet, consectetur adipiscing elit,], 
+                colbreak() }, 
+        breakable: false, 
+        fill: rgb(49%,85%,100%,100%), 
+        inset: 4.0pt, 
+        width: 100%), 
+  parbreak() }
diff --git a/test/out/layout/block-sizing-01.out b/test/out/layout/block-sizing-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/block-sizing-01.out
@@ -0,0 +1,112 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/block-sizing-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/block-sizing-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/block-sizing-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/layout/block-sizing-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 120.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/block-sizing-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 60.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 80.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "layout"))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "size") ]
+                     (Block
+                        (Content
+                           [ SoftBreak
+                           , Text "This"
+                           , Space
+                           , Text "block"
+                           , Space
+                           , Text "has"
+                           , Space
+                           , Text "a"
+                           , Space
+                           , Text "width"
+                           , Space
+                           , Text "of"
+                           , Space
+                           , Code
+                               "test/typ/layout/block-sizing-01.typ"
+                               ( line 6 , column 30 )
+                               (FieldAccess
+                                  (Ident (Identifier "width")) (Ident (Identifier "size")))
+                           , Space
+                           , Text "and"
+                           , Space
+                           , Text "height"
+                           , Space
+                           , Text "of"
+                           , Space
+                           , Code
+                               "test/typ/layout/block-sizing-01.typ"
+                               ( line 6 , column 56 )
+                               (FieldAccess
+                                  (Ident (Identifier "height")) (Ident (Identifier "size")))
+                           , ParBreak
+                           ])))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  block(body: layout(func: ), 
+        height: 80.0pt, 
+        width: 60.0pt), 
+  parbreak() }
diff --git a/test/out/layout/block-spacing-00.out b/test/out/layout/block-spacing-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/block-spacing-00.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/block-spacing-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/block-spacing-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/block-spacing-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/block-spacing-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 10.0 Pt)) ])
+, SoftBreak
+, Text "Hello"
+, ParBreak
+, Text "There"
+, ParBreak
+, Code
+    "test/typ/layout/block-spacing-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 20.0 Pt))
+       , BlockArg [ Text "Further" , Space , Text "down" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Hello]), 
+  parbreak(), 
+  text(body: [There]), 
+  parbreak(), 
+  block(body: text(body: [Further down]), 
+        spacing: 20.0pt), 
+  parbreak() }
diff --git a/test/out/layout/clip-00.out b/test/out/layout/clip-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/clip-00.out
@@ -0,0 +1,125 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/clip-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/clip-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/clip-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Hello"
+, Space
+, Code
+    "test/typ/layout/clip-00.typ"
+    ( line 3 , column 8 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Em))
+       , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+       , KeyValArg (Identifier "clip") (Literal (Boolean False))
+       , BlockArg
+           [ Code
+               "test/typ/layout/clip-00.typ"
+               ( line 3 , column 51 )
+               (FuncCall
+                  (Ident (Identifier "rect"))
+                  [ KeyValArg (Identifier "width") (Literal (Numeric 3.0 Em))
+                  , KeyValArg (Identifier "height") (Literal (Numeric 3.0 Em))
+                  , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                  ])
+           ]
+       ])
+, SoftBreak
+, Text "world"
+, Space
+, Text "1"
+, ParBreak
+, Text "Space"
+, ParBreak
+, Text "Hello"
+, Space
+, Code
+    "test/typ/layout/clip-00.typ"
+    ( line 8 , column 8 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Em))
+       , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+       , KeyValArg (Identifier "clip") (Literal (Boolean True))
+       , BlockArg
+           [ Code
+               "test/typ/layout/clip-00.typ"
+               ( line 8 , column 50 )
+               (FuncCall
+                  (Ident (Identifier "rect"))
+                  [ KeyValArg (Identifier "width") (Literal (Numeric 3.0 Em))
+                  , KeyValArg (Identifier "height") (Literal (Numeric 3.0 Em))
+                  , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                  ])
+           ]
+       ])
+, Space
+, SoftBreak
+, Text "world"
+, Space
+, Text "2"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Hello ]), 
+  box(body: rect(fill: rgb(100%,25%,21%,100%), 
+                 height: 3.0em, 
+                 width: 3.0em), 
+      clip: false, 
+      height: 1.0em, 
+      width: 1.0em), 
+  text(body: [
+world 1]), 
+  parbreak(), 
+  text(body: [Space]), 
+  parbreak(), 
+  text(body: [Hello ]), 
+  box(body: rect(fill: rgb(100%,25%,21%,100%), 
+                 height: 3.0em, 
+                 width: 3.0em), 
+      clip: true, 
+      height: 1.0em, 
+      width: 1.0em), 
+  text(body: [ 
+world 2]), 
+  parbreak() }
diff --git a/test/out/layout/clip-01.out b/test/out/layout/clip-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/clip-01.out
@@ -0,0 +1,151 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/clip-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/clip-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/clip-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/clip-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 5.0 Em))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Em))
+       , KeyValArg (Identifier "clip") (Literal (Boolean False))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 1.0 Pt)) (Ident (Identifier "black")))
+       , BlockArg
+           [ SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , ParBreak
+           ]
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/clip-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 2.0 Em)) ])
+, ParBreak
+, Code
+    "test/typ/layout/clip-01.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 5.0 Em))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Em))
+       , KeyValArg (Identifier "clip") (Literal (Boolean True))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 1.0 Pt)) (Ident (Identifier "black")))
+       , BlockArg
+           [ SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , Text "yonder"
+           , Space
+           , Text "window"
+           , Space
+           , Text "breaks?"
+           , Space
+           , Text "It"
+           , Space
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "east,"
+           , Space
+           , Text "and"
+           , Space
+           , Text "Juliet"
+           , SoftBreak
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "sun"
+           , Text "."
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  block(body: { text(body: [
+But, soft! what light through ]), 
+                parbreak() }, 
+        clip: false, 
+        height: 2.0em, 
+        stroke: (thickness: 1.0pt,
+                 color: rgb(0%,0%,0%,100%)), 
+        width: 5.0em), 
+  parbreak(), 
+  v(amount: 2.0em), 
+  parbreak(), 
+  block(body: { text(body: [
+But, soft! what light through yonder window breaks? It is the east, and Juliet
+is the sun.]), 
+                parbreak() }, 
+        clip: true, 
+        height: 2.0em, 
+        stroke: (thickness: 1.0pt,
+                 color: rgb(0%,0%,0%,100%)), 
+        width: 5.0em), 
+  parbreak() }
diff --git a/test/out/layout/clip-02.out b/test/out/layout/clip-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/clip-02.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/clip-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/clip-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/clip-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Emoji"
+, Text ":"
+, Space
+, Code
+    "test/typ/layout/clip-02.typ"
+    ( line 3 , column 9 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 0.5 Em))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 1.0 Pt)) (Ident (Identifier "black")))
+       , BlockArg
+           [ Text "\128042,"
+           , Space
+           , Text "\127755,"
+           , Space
+           , Text "\127966"
+           ]
+       ])
+, ParBreak
+, Text "Emoji"
+, Text ":"
+, Space
+, Code
+    "test/typ/layout/clip-02.typ"
+    ( line 5 , column 9 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 0.5 Em))
+       , KeyValArg (Identifier "clip") (Literal (Boolean True))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 1.0 Pt)) (Ident (Identifier "black")))
+       , BlockArg
+           [ Text "\128042,"
+           , Space
+           , Text "\127755,"
+           , Space
+           , Text "\127966"
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Emoji: ]), 
+  box(body: text(body: [🐪, 🌋, 🏞]), 
+      height: 0.5em, 
+      stroke: (thickness: 1.0pt,
+               color: rgb(0%,0%,0%,100%))), 
+  parbreak(), 
+  text(body: [Emoji: ]), 
+  box(body: text(body: [🐪, 🌋, 🏞]), 
+      clip: true, 
+      height: 0.5em, 
+      stroke: (thickness: 1.0pt,
+               color: rgb(0%,0%,0%,100%))), 
+  parbreak() }
diff --git a/test/out/layout/clip-03.out b/test/out/layout/clip-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/clip-03.out
@@ -0,0 +1,120 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/clip-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/clip-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/clip-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/layout/clip-03.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, ParBreak
+, Text "First!"
+, ParBreak
+, Code
+    "test/typ/layout/clip-03.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 4.0 Em))
+       , KeyValArg (Identifier "clip") (Literal (Boolean True))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 1.0 Pt)) (Ident (Identifier "black")))
+       , BlockArg
+           [ SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , Text "yonder"
+           , Space
+           , Text "window"
+           , Space
+           , Text "breaks?"
+           , Space
+           , Text "It"
+           , Space
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "east,"
+           , Space
+           , Text "and"
+           , Space
+           , Text "Juliet"
+           , SoftBreak
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "sun"
+           , Text "."
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [First!]), 
+  parbreak(), 
+  block(body: { text(body: [
+But, soft! what light through yonder window breaks? It is the east, and Juliet
+is the sun.]), 
+                parbreak() }, 
+        clip: true, 
+        height: 4.0em, 
+        stroke: (thickness: 1.0pt,
+                 color: rgb(0%,0%,0%,100%))), 
+  parbreak() }
diff --git a/test/out/layout/columns-00.out b/test/out/layout/columns-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-00.out
@@ -0,0 +1,177 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 3.25 Cm))
+       , KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       , KeyValArg (Identifier "columns") (Literal (Int 2))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/columns-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ar"))
+       , KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "Noto Sans Arabic")
+              , Literal (String "Linux Libertine")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/columns-00.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "columns"))
+       [ KeyValArg (Identifier "gutter") (Literal (Numeric 30.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/layout/columns-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , KeyValArg (Identifier "height") (Literal (Numeric 8.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 6.0 Pt))
+       ])
+, Space
+, Text "\1608\1578\1581\1601\1610\1586"
+, SoftBreak
+, Text "\1575\1604\1593\1583\1610\1583"
+, Space
+, Text "\1605\1606"
+, Space
+, Text "\1575\1604\1578\1601\1575\1593\1604\1575\1578"
+, Space
+, Text "\1575\1604\1603\1610\1605\1610\1575\1574\1610\1577"
+, Text "."
+, Space
+, Text "("
+, Text "DNA)"
+, Space
+, Text "\1605\1606"
+, Space
+, Text "\1571\1607\1605"
+, Space
+, Text "\1575\1604\1571\1581\1605\1575\1590"
+, Space
+, Text "\1575\1604\1606\1608\1608\1610\1577"
+, Space
+, Text "\1575\1604\1578\1610"
+, Space
+, Text "\1578\1615\1588\1603\1616\1617\1604"
+, SoftBreak
+, Text "\1573\1604\1609"
+, Space
+, Text "\1580\1575\1606\1576"
+, Space
+, Text "\1603\1604"
+, Space
+, Text "\1605\1606"
+, Space
+, Text "\1575\1604\1576\1585\1608\1578\1610\1606\1575\1578"
+, Space
+, Text "\1608\1575\1604\1604\1610\1576\1610\1583\1575\1578"
+, Space
+, Text "\1608\1575\1604\1587\1603\1585\1610\1575\1578"
+, Space
+, Text "\1575\1604\1605\1578\1593\1583\1583\1577"
+, SoftBreak
+, Code
+    "test/typ/layout/columns-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       , KeyValArg (Identifier "height") (Literal (Numeric 8.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 6.0 Pt))
+       ])
+, SoftBreak
+, Text "\1575\1604\1580\1586\1610\1574\1575\1578"
+, Space
+, Text "\1575\1604\1590\1582\1605\1577"
+, Space
+, Text "\1575\1604\1571\1585\1576\1593\1577"
+, Space
+, Text "\1575\1604\1590\1585\1608\1585\1610\1577"
+, Space
+, Text "\1604\1604\1581\1610\1575\1577"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       font: ("Noto Sans Arabic", 
+              "Linux Libertine"), 
+       lang: "ar"), 
+  parbreak(), 
+  box(fill: rgb(18%,80%,25%,100%), 
+      height: 8.0pt, 
+      width: 6.0pt), 
+  text(body: [ وتحفيز
+العديد من التفاعلات الكيميائية. (DNA) من أهم الأحماض النووية التي تُشكِّل
+إلى جانب كل من البروتينات والليبيدات والسكريات المتعددة
+], 
+       font: ("Noto Sans Arabic", 
+              "Linux Libertine"), 
+       lang: "ar"), 
+  box(fill: rgb(13%,61%,67%,100%), 
+      height: 8.0pt, 
+      width: 6.0pt), 
+  text(body: [
+الجزيئات الضخمة الأربعة الضرورية للحياة.], 
+       font: ("Noto Sans Arabic", 
+              "Linux Libertine"), 
+       lang: "ar"), 
+  parbreak() }
diff --git a/test/out/layout/columns-01.out b/test/out/layout/columns-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-01.out
@@ -0,0 +1,152 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, ParBreak
+, Code
+    "test/typ/layout/columns-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt))
+       , KeyValArg (Identifier "inset") (Literal (Numeric 8.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "columns"))
+              [ NormalArg (Literal (Int 2))
+              , NormalArg
+                  (Block
+                     (Content
+                        [ SoftBreak
+                        , Text "A"
+                        , Space
+                        , Text "special"
+                        , Space
+                        , Text "plight"
+                        , Space
+                        , Text "has"
+                        , Space
+                        , Text "befallen"
+                        , Space
+                        , Text "our"
+                        , Space
+                        , Text "document"
+                        , Text "."
+                        , SoftBreak
+                        , Text "Columns"
+                        , Space
+                        , Text "in"
+                        , Space
+                        , Text "text"
+                        , Space
+                        , Text "boxes"
+                        , Space
+                        , Text "reigned"
+                        , Space
+                        , Text "down"
+                        , Space
+                        , Text "unto"
+                        , Space
+                        , Text "the"
+                        , Space
+                        , Text "soil"
+                        , SoftBreak
+                        , Text "to"
+                        , Space
+                        , Text "waste"
+                        , Space
+                        , Text "a"
+                        , Space
+                        , Text "year"
+                        , Quote '\''
+                        , Text "s"
+                        , Space
+                        , Text "crop"
+                        , Space
+                        , Text "of"
+                        , Space
+                        , Text "rich"
+                        , Space
+                        , Text "layouts"
+                        , Text "."
+                        , SoftBreak
+                        , Text "The"
+                        , Space
+                        , Text "columns"
+                        , Space
+                        , Text "at"
+                        , Space
+                        , Text "least"
+                        , Space
+                        , Text "were"
+                        , Space
+                        , Text "graciously"
+                        , Space
+                        , Text "balanced"
+                        , Text "."
+                        , ParBreak
+                        ]))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  rect(body: columns(body: { text(body: [
+A special plight has befallen our document.
+Columns in text boxes reigned down unto the soil
+to waste a year’s crop of rich layouts.
+The columns at least were graciously balanced.]), 
+                             parbreak() }, 
+                     count: 2), 
+       height: 100.0pt, 
+       inset: 8.0pt, 
+       width: 180.0pt), 
+  parbreak() }
diff --git a/test/out/layout/columns-02.out b/test/out/layout/columns-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-02.out
@@ -0,0 +1,204 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 5.0 Cm))
+       , KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       , KeyValArg (Identifier "columns") (Literal (Int 2))
+       ])
+, ParBreak
+, Text "Lorem"
+, Space
+, Text "ipsum"
+, Space
+, Text "dolor"
+, Space
+, Text "sit"
+, Space
+, Text "amet"
+, Space
+, Text "is"
+, Space
+, Text "a"
+, Space
+, Text "common"
+, Space
+, Text "blind"
+, Space
+, Text "text"
+, SoftBreak
+, Text "and"
+, Space
+, Text "I"
+, Space
+, Text "again"
+, Space
+, Text "am"
+, Space
+, Text "in"
+, Space
+, Text "need"
+, Space
+, Text "of"
+, Space
+, Text "filling"
+, Space
+, Text "up"
+, Space
+, Text "this"
+, Space
+, Text "page"
+, SoftBreak
+, Code
+    "test/typ/layout/columns-02.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "bottom"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 12.0 Pt))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/columns-02.typ"
+    ( line 8 , column 2 )
+    (FuncCall (Ident (Identifier "colbreak")) [])
+, ParBreak
+, Text "so"
+, Space
+, Text "I"
+, Quote '\''
+, Text "m"
+, Space
+, Text "returning"
+, Space
+, Text "to"
+, Space
+, Text "this"
+, Space
+, Text "trusty"
+, Space
+, Text "tool"
+, Space
+, Text "of"
+, Space
+, Text "tangible"
+, Space
+, Text "terror"
+, Text "."
+, SoftBreak
+, Text "Sure,"
+, Space
+, Text "it"
+, Space
+, Text "is"
+, Space
+, Text "not"
+, Space
+, Text "the"
+, Space
+, Text "most"
+, Space
+, Text "creative"
+, Space
+, Text "way"
+, Space
+, Text "of"
+, Space
+, Text "filling"
+, Space
+, Text "up"
+, SoftBreak
+, Text "a"
+, Space
+, Text "page"
+, Space
+, Text "for"
+, Space
+, Text "a"
+, Space
+, Text "test"
+, Space
+, Text "but"
+, Space
+, Text "it"
+, Space
+, Text "does"
+, Space
+, Text "get"
+, Space
+, Text "the"
+, Space
+, Text "job"
+, Space
+, Text "done"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet is a common blind text
+and I again am in need of filling up this page
+]), 
+  align(alignment: bottom, 
+        body: rect(fill: rgb(13%,61%,67%,100%), 
+                   height: 12.0pt, 
+                   width: 100%)), 
+  text(body: [
+]), 
+  colbreak(), 
+  parbreak(), 
+  text(body: [so I’m returning to this trusty tool of tangible terror.
+Sure, it is not the most creative way of filling up
+a page for a test but it does get the job done.]), 
+  parbreak() }
diff --git a/test/out/layout/columns-03.out b/test/out/layout/columns-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-03.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 2.5 Cm))
+       , KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/columns-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 6.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "columns"))
+              [ NormalArg (Literal (Int 2))
+              , NormalArg
+                  (Block
+                     (Content
+                        [ SoftBreak
+                        , Text "ABC"
+                        , Space
+                        , HardBreak
+                        , Text "BCD"
+                        , SoftBreak
+                        , Code
+                            "test/typ/layout/columns-03.typ"
+                            ( line 8 , column 6 )
+                            (FuncCall (Ident (Identifier "colbreak")) [])
+                        , SoftBreak
+                        , Text "DEF"
+                        , ParBreak
+                        ]))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  rect(body: columns(body: { text(body: [
+ABC ]), 
+                             linebreak(), 
+                             text(body: [BCD
+]), 
+                             colbreak(), 
+                             text(body: [
+DEF]), 
+                             parbreak() }, 
+                     count: 2), 
+       inset: 6.0pt), 
+  parbreak() }
diff --git a/test/out/layout/columns-04.out b/test/out/layout/columns-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-04.out
@@ -0,0 +1,119 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 3.25 Cm))
+       , KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       , KeyValArg (Identifier "columns") (Literal (Int 3))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/columns-04.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "columns"))
+       [ KeyValArg (Identifier "gutter") (Literal (Numeric 30.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/layout/columns-04.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.5 Cm))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       ])
+, Space
+, Code
+    "test/typ/layout/columns-04.typ"
+    ( line 6 , column 49 )
+    (FuncCall (Ident (Identifier "parbreak")) [])
+, SoftBreak
+, Code
+    "test/typ/layout/columns-04.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       ])
+, Space
+, Code
+    "test/typ/layout/columns-04.typ"
+    ( line 7 , column 49 )
+    (FuncCall (Ident (Identifier "parbreak")) [])
+, SoftBreak
+, Code
+    "test/typ/layout/columns-04.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "circle"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern")) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  rect(fill: rgb(18%,80%,25%,100%), 
+       height: 2.5cm, 
+       width: 100%), 
+  text(body: [ ]), 
+  parbreak(), 
+  text(body: [
+]), 
+  rect(fill: rgb(13%,61%,67%,100%), 
+       height: 2.0cm, 
+       width: 100%), 
+  text(body: [ ]), 
+  parbreak(), 
+  text(body: [
+]), 
+  circle(fill: rgb(13%,61%,67%,100%)), 
+  parbreak() }
diff --git a/test/out/layout/columns-05.out b/test/out/layout/columns-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-05.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-05.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 1.0 Cm))
+       , KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       , KeyValArg (Identifier "columns") (Literal (Int 2))
+       ])
+, ParBreak
+, Text "A"
+, SoftBreak
+, Code
+    "test/typ/layout/columns-05.typ"
+    ( line 6 , column 2 )
+    (FuncCall (Ident (Identifier "colbreak")) [])
+, SoftBreak
+, Code
+    "test/typ/layout/columns-05.typ"
+    ( line 7 , column 2 )
+    (FuncCall (Ident (Identifier "colbreak")) [])
+, SoftBreak
+, Text "B"
+, SoftBreak
+, Code
+    "test/typ/layout/columns-05.typ"
+    ( line 9 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, SoftBreak
+, Text "C"
+, SoftBreak
+, Code
+    "test/typ/layout/columns-05.typ"
+    ( line 11 , column 2 )
+    (FuncCall (Ident (Identifier "colbreak")) [])
+, SoftBreak
+, Text "D"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [A
+]), 
+  colbreak(), 
+  text(body: [
+]), 
+  colbreak(), 
+  text(body: [
+B
+]), 
+  pagebreak(), 
+  text(body: [
+C
+]), 
+  colbreak(), 
+  text(body: [
+D]), 
+  parbreak() }
diff --git a/test/out/layout/columns-06.out b/test/out/layout/columns-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-06.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-06.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       , KeyValArg (Identifier "columns") (Literal (Int 2))
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/columns-06.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "inset") (Literal (Numeric 3.0 Pt))
+       , BlockArg
+           [ Text "So"
+           , Space
+           , Text "there"
+           , Space
+           , Text "isn"
+           , Quote '\''
+           , Text "t"
+           , Space
+           , Text "anything"
+           , Space
+           , Text "in"
+           , Space
+           , Text "the"
+           , Space
+           , Text "second"
+           , Space
+           , Text "column?"
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  rect(body: text(body: [So there isn’t anything in the second column?]), 
+       inset: 3.0pt, 
+       width: 100%), 
+  parbreak() }
diff --git a/test/out/layout/columns-07.out b/test/out/layout/columns-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-07.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-07.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto)
+       , KeyValArg (Identifier "columns") (Literal (Int 3))
+       ])
+, ParBreak
+, Text "Arbitrary"
+, Space
+, Text "horizontal"
+, Space
+, Text "growth"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Arbitrary horizontal growth.]), 
+  parbreak() }
diff --git a/test/out/layout/columns-08.out b/test/out/layout/columns-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-08.out
@@ -0,0 +1,151 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-08.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       , KeyValArg (Identifier "columns") (Literal (Int 2))
+       ])
+, ParBreak
+, Text "There"
+, Space
+, Text "can"
+, Space
+, Text "be"
+, Space
+, Text "as"
+, Space
+, Text "much"
+, Space
+, Text "content"
+, Space
+, Text "as"
+, Space
+, Text "you"
+, Space
+, Text "want"
+, Space
+, Text "in"
+, Space
+, Text "the"
+, Space
+, Text "left"
+, Space
+, Text "column"
+, SoftBreak
+, Text "and"
+, Space
+, Text "the"
+, Space
+, Text "document"
+, Space
+, Text "will"
+, Space
+, Text "grow"
+, Space
+, Text "with"
+, Space
+, Text "it"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/layout/columns-08.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "height") (Literal (Numeric 30.0 Pt))
+       ])
+, ParBreak
+, Text "Only"
+, Space
+, Text "an"
+, Space
+, Text "explicit"
+, Space
+, Code
+    "test/typ/layout/columns-08.typ"
+    ( line 10 , column 19 )
+    (FuncCall (Ident (Identifier "colbreak")) [])
+, Space
+, RawInline "#colbreak()"
+, Space
+, Text "can"
+, Space
+, Text "put"
+, Space
+, Text "content"
+, Space
+, Text "in"
+, Space
+, Text "the"
+, SoftBreak
+, Text "second"
+, Space
+, Text "column"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [There can be as much content as you want in the left column
+and the document will grow with it.]), 
+  parbreak(), 
+  rect(fill: rgb(18%,80%,25%,100%), 
+       height: 30.0pt, 
+       width: 100%), 
+  parbreak(), 
+  text(body: [Only an explicit ]), 
+  colbreak(), 
+  text(body: [ ]), 
+  raw(block: false, 
+      lang: none, 
+      text: "#colbreak()"), 
+  text(body: [ can put content in the
+second column.]), 
+  parbreak() }
diff --git a/test/out/layout/columns-09.out b/test/out/layout/columns-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-09.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/columns-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/columns-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/columns-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/columns-09.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal Auto)
+       , KeyValArg (Identifier "width") (Literal (Numeric 7.05 Cm))
+       , KeyValArg (Identifier "columns") (Literal (Int 1))
+       ])
+, ParBreak
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "a"
+, Space
+, Text "normal"
+, Space
+, Text "page"
+, Text "."
+, Space
+, Text "Very"
+, Space
+, Text "normal"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [This is a normal page. Very normal.]), 
+  parbreak() }
diff --git a/test/out/layout/columns-10.out b/test/out/layout/columns-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/columns-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/container-00.out b/test/out/layout/container-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/container-00.out
@@ -0,0 +1,85 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/container-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/container-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/container-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Space
+, Code
+    "test/typ/layout/container-00.typ"
+    ( line 3 , column 4 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ BlockArg [ Text "B" , Space , HardBreak , Text "C" ] ])
+, Space
+, Text "D"
+, Text "."
+, ParBreak
+, Comment
+, Text "Spaced"
+, Space
+, HardBreak
+, Code
+    "test/typ/layout/container-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 0.5 Cm)) ])
+, Space
+, HardBreak
+, Text "Apart"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A ]), 
+  box(body: { text(body: [B ]), 
+              linebreak(), 
+              text(body: [C]) }), 
+  text(body: [ D.]), 
+  parbreak(), 
+  text(body: [Spaced ]), 
+  linebreak(), 
+  box(height: 0.5cm), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [Apart]), 
+  parbreak() }
diff --git a/test/out/layout/container-01.out b/test/out/layout/container-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/container-01.out
@@ -0,0 +1,115 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/container-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/container-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/container-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/container-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 120.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/container-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 0.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/container-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 90.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 80.0 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/layout/container-01.typ"
+               ( line 6 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "block"))
+                  [ KeyValArg (Identifier "width") (Literal (Numeric 60.0 Percent))
+                  , KeyValArg (Identifier "height") (Literal (Numeric 60.0 Percent))
+                  , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                  ])
+           , SoftBreak
+           , Code
+               "test/typ/layout/container-01.typ"
+               ( line 7 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "block"))
+                  [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+                  , KeyValArg (Identifier "height") (Literal (Numeric 60.0 Percent))
+                  , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+                  ])
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  block(body: { text(body: [
+]), 
+                block(fill: rgb(18%,80%,25%,100%), 
+                      height: 60%, 
+                      spacing: 0.0pt, 
+                      width: 60%), 
+                text(body: [
+]), 
+                block(fill: rgb(0%,45%,85%,100%), 
+                      height: 60%, 
+                      spacing: 0.0pt, 
+                      width: 50%), 
+                parbreak() }, 
+        fill: rgb(100%,25%,21%,100%), 
+        height: 80.0pt, 
+        spacing: 0.0pt, 
+        width: 90.0pt), 
+  parbreak() }
diff --git a/test/out/layout/container-02.out b/test/out/layout/container-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/container-02.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/container-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/container-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/container-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/container-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 50.0 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "yellow"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "path"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "purple"))
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 30.0 Pt) , Literal (Numeric 30.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 30.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 30.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  box(body: path(fill: rgb(69%,5%,78%,100%), 
+                 vertices: ((0.0pt, 0.0pt), 
+                            (30.0pt, 30.0pt), 
+                            (0.0pt, 30.0pt), 
+                            (30.0pt, 0.0pt))), 
+      fill: rgb(100%,86%,0%,100%), 
+      height: 50.0pt, 
+      width: 50.0pt), 
+  parbreak() }
diff --git a/test/out/layout/container-03.out b/test/out/layout/container-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/container-03.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/container-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/container-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/container-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Hello"
+, Space
+, Code
+    "test/typ/layout/container-03.typ"
+    ( line 3 , column 8 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 0.7 Em))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              ])
+       ])
+, Space
+, Text "World"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Hello ]), 
+  box(body: rect(height: 0.7em, 
+                 width: 100%), 
+      width: 1.0fr), 
+  text(body: [ World]), 
+  parbreak() }
diff --git a/test/out/layout/container-04.out b/test/out/layout/container-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/container-04.out
@@ -0,0 +1,111 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/container-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/container-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/container-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/layout/container-04.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, ParBreak
+, Text "First!"
+, ParBreak
+, Code
+    "test/typ/layout/container-04.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ BlockArg
+           [ SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , Text "yonder"
+           , Space
+           , Text "window"
+           , Space
+           , Text "breaks?"
+           , Space
+           , Text "It"
+           , Space
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "east,"
+           , Space
+           , Text "and"
+           , Space
+           , Text "Juliet"
+           , SoftBreak
+           , Text "is"
+           , Space
+           , Text "the"
+           , Space
+           , Text "sun"
+           , Text "."
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [First!]), 
+  parbreak(), 
+  block(body: { text(body: [
+But, soft! what light through yonder window breaks? It is the east, and Juliet
+is the sun.]), 
+                parbreak() }), 
+  parbreak() }
diff --git a/test/out/layout/container-fill-00.out b/test/out/layout/container-fill-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/container-fill-00.out
@@ -0,0 +1,138 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/container-fill-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/container-fill-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/container-fill-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/container-fill-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/container-fill-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "words")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "split"))
+             (FuncCall
+                (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 18)) ]))
+          []))
+, SoftBreak
+, Code
+    "test/typ/layout/container-fill-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 8.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "aqua"))
+       , KeyValArg
+           (Identifier "stroke")
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "darken")) (Ident (Identifier "aqua")))
+              [ NormalArg (Literal (Numeric 30.0 Percent)) ])
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/layout/container-fill-00.typ"
+               ( line 5 , column 4 )
+               (FuncCall
+                  (FieldAccess
+                     (Ident (Identifier "join"))
+                     (FuncCall
+                        (FieldAccess
+                           (Ident (Identifier "slice")) (Ident (Identifier "words")))
+                        [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 13)) ]))
+                  [ NormalArg (Literal (String " ")) ])
+           , SoftBreak
+           , Code
+               "test/typ/layout/container-fill-00.typ"
+               ( line 6 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "box"))
+                  [ KeyValArg (Identifier "fill") (Ident (Identifier "teal"))
+                  , KeyValArg (Identifier "outset") (Literal (Numeric 2.0 Pt))
+                  , BlockArg [ Text "tempor" ]
+                  ])
+           , SoftBreak
+           , Code
+               "test/typ/layout/container-fill-00.typ"
+               ( line 7 , column 4 )
+               (FuncCall
+                  (FieldAccess
+                     (Ident (Identifier "join"))
+                     (FuncCall
+                        (FieldAccess
+                           (Ident (Identifier "slice")) (Ident (Identifier "words")))
+                        [ NormalArg (Literal (Int 13)) ]))
+                  [ NormalArg (Literal (String " ")) ])
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  block(body: { text(body: [
+]), 
+                text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt]), 
+                text(body: [
+]), 
+                box(body: text(body: [tempor]), 
+                    fill: rgb(22%,80%,80%,100%), 
+                    outset: 2.0pt), 
+                text(body: [
+]), 
+                text(body: [ut labore et dolore magna]), 
+                parbreak() }, 
+        fill: rgb(49%,85%,100%,100%), 
+        inset: 8.0pt, 
+        stroke: rgb(34%,60%,70%,100%), 
+        width: 100%), 
+  parbreak() }
diff --git a/test/out/layout/enum-00.out b/test/out/layout/enum-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-00.out
@@ -0,0 +1,59 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/enum-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "enum"))
+       [ BlockArg [ Text "Embrace" ]
+       , BlockArg [ Text "Extend" ]
+       , BlockArg [ Text "Extinguish" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  enum(children: (text(body: [Embrace]), 
+                  text(body: [Extend]), 
+                  text(body: [Extinguish]))), 
+  parbreak() }
diff --git a/test/out/layout/enum-01.out b/test/out/layout/enum-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-01.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, EnumListItem (Just 0) [ Text "Before" , Space , Text "first!" ]
+, SoftBreak
+, EnumListItem
+    (Just 1)
+    [ Text "First"
+    , Text "."
+    , SoftBreak
+    , EnumListItem (Just 2) [ Text "Indented" , SoftBreak ]
+    ]
+, SoftBreak
+, EnumListItem Nothing [ Text "Second" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  enum(children: (text(body: [Before first!]), 
+                  { text(body: [First.
+]), 
+                    enum(children: (text(body: [Indented
+])), 
+                         start: 2) }, 
+                  { text(body: [Second]), 
+                    parbreak() }), 
+       start: 0) }
diff --git a/test/out/layout/enum-02.out b/test/out/layout/enum-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-02.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-02.typ"
+    ( line 3 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range")) [ NormalArg (Literal (Int 5)) ])
+       (Block
+          (CodeBlock
+             [ Block
+                 (Content
+                    [ EnumListItem
+                        Nothing
+                        [ Code
+                            "test/typ/layout/enum-02.typ"
+                            ( line 4 , column 8 )
+                            (FuncCall
+                               (Ident (Identifier "numbering"))
+                               [ NormalArg (Literal (String "I"))
+                               , NormalArg (Plus (Literal (Int 1)) (Ident (Identifier "i")))
+                               ])
+                        ]
+                    ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  enum(children: (numbering(numbering: "I", 
+                            numbers: (1)))), 
+  enum(children: (numbering(numbering: "I", 
+                            numbers: (2)))), 
+  enum(children: (numbering(numbering: "I", 
+                            numbers: (3)))), 
+  enum(children: (numbering(numbering: "I", 
+                            numbers: (4)))), 
+  enum(children: (numbering(numbering: "I", 
+                            numbers: (5)))), 
+  parbreak() }
diff --git a/test/out/layout/enum-03.out b/test/out/layout/enum-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-03.out
@@ -0,0 +1,56 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, BulletListItem [ Text "Bullet" , Space , Text "List" ]
+, SoftBreak
+, EnumListItem Nothing [ Text "Numbered" , Space , Text "List" ]
+, SoftBreak
+, DescListItem [ Text "Term" ] [ Text "List" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  list(children: (text(body: [Bullet List]))), 
+  enum(children: (text(body: [Numbered List]))), 
+  terms(children: ((text(body: [Term]), 
+                    { text(body: [List]), 
+                      parbreak() }))) }
diff --git a/test/out/layout/enum-04.out b/test/out/layout/enum-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-04.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "1"
+, Text "."
+, Text "2"
+, Space
+, HardBreak
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "0"
+, Text "."
+, Space
+, HardBreak
+, Text "See"
+, Space
+, Text "0"
+, Text "."
+, Text "3"
+, Text "."
+, Space
+, HardBreak
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [1.2 ]), 
+  linebreak(), 
+  text(body: [This is 0. ]), 
+  linebreak(), 
+  text(body: [See 0.3. ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/layout/enum-05.out b/test/out/layout/enum-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-05.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, EnumListItem Nothing []
+, SoftBreak
+, Text "Empty"
+, Space
+, HardBreak
+, Text "+Nope"
+, Space
+, HardBreak
+, Text "a"
+, Space
+, Text "+"
+, Space
+, Text "0"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  enum(children: ({  })), 
+  text(body: [Empty ]), 
+  linebreak(), 
+  text(body: [+Nope ]), 
+  linebreak(), 
+  text(body: [a + 0.]), 
+  parbreak() }
diff --git a/test/out/layout/enum-06.out b/test/out/layout/enum-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-06.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, EnumListItem (Just 1) [ Text "first" ]
+, SoftBreak
+, EnumListItem Nothing [ Text "second" ]
+, SoftBreak
+, EnumListItem (Just 5) [ Text "fifth" , SoftBreak ]
+, SoftBreak
+, Code
+    "test/typ/layout/enum-06.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "enum"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "item")) (Ident (Identifier "enum")))
+              [ NormalArg (Literal (Int 1)) , BlockArg [ Text "First" ] ])
+       , NormalArg (Block (Content [ Text "Second" ]))
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "item")) (Ident (Identifier "enum")))
+              [ NormalArg (Literal (Int 5)) , BlockArg [ Text "Fifth" ] ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  enum(children: (text(body: [first]), 
+                  text(body: [second]), 
+                  text(body: [fifth
+])), 
+       start: 1), 
+  enum(children: (enum.item(body: text(body: [First]), 
+                            number: 1), 
+                  text(body: [Second]), 
+                  enum.item(body: text(body: [Fifth]), 
+                            number: 5))), 
+  parbreak() }
diff --git a/test/out/layout/enum-align-00.out b/test/out/layout/enum-align-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-align-00.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-align-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-align-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-align-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-align-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "horizon")) ])
+, ParBreak
+, EnumListItem
+    Nothing
+    [ Text "ABCDEF"
+    , HardBreak
+    , Text "GHIJKL"
+    , HardBreak
+    , Text "MNOPQR"
+    , SoftBreak
+    , EnumListItem
+        Nothing
+        [ Text "INNER"
+        , HardBreak
+        , Text "INNER"
+        , HardBreak
+        , Text "INNER"
+        ]
+    ]
+, SoftBreak
+, EnumListItem
+    Nothing [ Text "BACK" , HardBreak , Text "HERE" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  enum(children: ({ text(body: [ABCDEF]), 
+                    linebreak(), 
+                    text(body: [GHIJKL]), 
+                    linebreak(), 
+                    text(body: [MNOPQR
+]), 
+                    enum(children: ({ text(body: [INNER]), 
+                                      linebreak(), 
+                                      text(body: [INNER]), 
+                                      linebreak(), 
+                                      text(body: [INNER]) })) }, 
+                  { text(body: [BACK]), 
+                    linebreak(), 
+                    text(body: [HERE]), 
+                    parbreak() })) }
diff --git a/test/out/layout/enum-align-01.out b/test/out/layout/enum-align-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-align-01.out
@@ -0,0 +1,79 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-align-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-align-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-align-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, EnumListItem (Just 1) [ Text "a" ]
+, SoftBreak
+, EnumListItem (Just 10) [ Text "b" ]
+, SoftBreak
+, EnumListItem (Just 100) [ Text "c" , SoftBreak ]
+, SoftBreak
+, Code
+    "test/typ/layout/enum-align-01.typ"
+    ( line 7 , column 2 )
+    (Set
+       (Ident (Identifier "enum"))
+       [ KeyValArg
+           (Identifier "number-align") (Ident (Identifier "start"))
+       ])
+, SoftBreak
+, EnumListItem (Just 1) [ Space , Text "a" ]
+, SoftBreak
+, EnumListItem (Just 8) [ Space , Text "b" ]
+, SoftBreak
+, EnumListItem (Just 16) [ Text "c" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  enum(children: (text(body: [a]), 
+                  text(body: [b]), 
+                  text(body: [c
+])), 
+       start: 1), 
+  text(body: [
+]), 
+  enum(children: (text(body: [ a]), 
+                  text(body: [ b]), 
+                  { text(body: [c]), 
+                    parbreak() }), 
+       number-align: start, 
+       start: 1) }
diff --git a/test/out/layout/enum-align-02.out b/test/out/layout/enum-align-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-align-02.out
@@ -0,0 +1,97 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-align-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-align-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-align-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-align-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/enum-align-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "enum"))
+       [ KeyValArg
+           (Identifier "number-align") (Ident (Identifier "start"))
+       ])
+, ParBreak
+, EnumListItem (Just 4) [ Space , Text "c" ]
+, SoftBreak
+, EnumListItem (Just 8) [ Space , Text "d" ]
+, SoftBreak
+, EnumListItem
+    (Just 16)
+    [ Text "e"
+    , HardBreak
+    , Text "f"
+    , SoftBreak
+    , EnumListItem (Just 2) [ Space , Text "f" , HardBreak , Text "g" ]
+    , SoftBreak
+    , EnumListItem (Just 32) [ Text "g" ]
+    , SoftBreak
+    , EnumListItem (Just 64) [ Text "h" , ParBreak ]
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  enum(children: (text(body: [ c]), 
+                  text(body: [ d]), 
+                  { text(body: [e]), 
+                    linebreak(), 
+                    text(body: [f
+]), 
+                    enum(children: ({ text(body: [ f]), 
+                                      linebreak(), 
+                                      text(body: [g]) }, 
+                                    text(body: [g]), 
+                                    { text(body: [h]), 
+                                      parbreak() }), 
+                         number-align: start, 
+                         start: 2) }), 
+       number-align: start, 
+       start: 4) }
diff --git a/test/out/layout/enum-align-03.out b/test/out/layout/enum-align-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-align-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/enum-numbering-00.out b/test/out/layout/enum-numbering-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-numbering-00.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-numbering-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-numbering-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-numbering-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-numbering-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "enum"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "(1.a.*)"))
+       ])
+, SoftBreak
+, EnumListItem Nothing [ Text "First" ]
+, SoftBreak
+, EnumListItem
+    Nothing
+    [ Text "Second"
+    , SoftBreak
+    , EnumListItem
+        (Just 2)
+        [ Text "Nested"
+        , SoftBreak
+        , EnumListItem Nothing [ Text "Deep" ]
+        ]
+    ]
+, SoftBreak
+, EnumListItem Nothing [ Text "Normal" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  enum(children: (text(body: [First]), 
+                  { text(body: [Second
+]), 
+                    enum(children: ({ text(body: [Nested
+]), 
+                                      enum(children: (text(body: [Deep])), 
+                                           numbering: "(1.a.*)") }), 
+                         numbering: "(1.a.*)", 
+                         start: 2) }, 
+                  { text(body: [Normal]), 
+                    parbreak() }), 
+       numbering: "(1.a.*)") }
diff --git a/test/out/layout/enum-numbering-01.out b/test/out/layout/enum-numbering-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-numbering-01.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-numbering-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-numbering-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-numbering-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-numbering-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "enum"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "1.a."))
+       , KeyValArg (Identifier "full") (Literal (Boolean True))
+       ])
+, SoftBreak
+, EnumListItem
+    Nothing
+    [ Text "First"
+    , SoftBreak
+    , EnumListItem Nothing [ Text "Nested" , ParBreak ]
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  enum(children: ({ text(body: [First
+]), 
+                    enum(children: ({ text(body: [Nested]), 
+                                      parbreak() }), 
+                         full: true, 
+                         numbering: "1.a.") }), 
+       full: true, 
+       numbering: "1.a.") }
diff --git a/test/out/layout/enum-numbering-02.out b/test/out/layout/enum-numbering-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-numbering-02.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-numbering-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-numbering-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-numbering-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-numbering-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "enum"))
+       [ KeyValArg (Identifier "start") (Literal (Int 3))
+       , KeyValArg
+           (Identifier "spacing")
+           (Minus (Literal (Numeric 0.65 Em)) (Literal (Numeric 3.0 Pt)))
+       , KeyValArg (Identifier "tight") (Literal (Boolean False))
+       , KeyValArg
+           (Identifier "numbering")
+           (FuncExpr
+              [ NormalParam (Identifier "n") ]
+              (FuncCall
+                 (Ident (Identifier "text"))
+                 [ KeyValArg
+                     (Identifier "fill")
+                     (FuncCall
+                        (FieldAccess
+                           (Ident (Identifier "at"))
+                           (Array
+                              [ Ident (Identifier "red")
+                              , Ident (Identifier "green")
+                              , Ident (Identifier "blue")
+                              ]))
+                        [ NormalArg
+                            (FuncCall
+                               (FieldAccess
+                                  (Ident (Identifier "rem")) (Ident (Identifier "calc")))
+                               [ NormalArg (Ident (Identifier "n"))
+                               , NormalArg (Literal (Int 3))
+                               ])
+                        ])
+                 , NormalArg
+                     (FuncCall
+                        (Ident (Identifier "numbering"))
+                        [ NormalArg (Literal (String "A"))
+                        , NormalArg (Ident (Identifier "n"))
+                        ])
+                 ]))
+       , NormalArg (Block (Content [ Text "Red" ]))
+       , NormalArg (Block (Content [ Text "Green" ]))
+       , NormalArg (Block (Content [ Text "Blue" ]))
+       , NormalArg (Block (Content [ Text "Red" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  enum(children: (text(body: [Red]), 
+                  text(body: [Green]), 
+                  text(body: [Blue]), 
+                  text(body: [Red])), 
+       numbering: , 
+       spacing: 0.65em + -3.0pt, 
+       start: 3, 
+       tight: false), 
+  parbreak() }
diff --git a/test/out/layout/enum-numbering-03.out b/test/out/layout/enum-numbering-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-numbering-03.out
@@ -0,0 +1,80 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-numbering-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-numbering-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-numbering-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-numbering-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "enum"))
+       [ KeyValArg
+           (Identifier "numbering")
+           (FuncExpr
+              [ NormalParam (Identifier "n") ]
+              (FuncCall
+                 (Ident (Identifier "super"))
+                 [ BlockArg
+                     [ Code
+                         "test/typ/layout/enum-numbering-03.typ"
+                         ( line 3 , column 34 )
+                         (Ident (Identifier "n"))
+                     ]
+                 ]))
+       ])
+, SoftBreak
+, EnumListItem
+    Nothing
+    [ Text "A" , SoftBreak , EnumListItem Nothing [ Text "B" ] ]
+, SoftBreak
+, EnumListItem Nothing [ Text "C" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  enum(children: ({ text(body: [A
+]), 
+                    enum(children: (text(body: [B])), 
+                         numbering: ) }, 
+                  { text(body: [C]), 
+                    parbreak() }), 
+       numbering: ) }
diff --git a/test/out/layout/enum-numbering-04.out b/test/out/layout/enum-numbering-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-numbering-04.out
@@ -0,0 +1,117 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/enum-numbering-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/enum-numbering-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/enum-numbering-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/enum-numbering-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "New Computer Modern"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/enum-numbering-04.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "enum"))
+       [ KeyValArg
+           (Identifier "numbering")
+           (FuncExpr
+              [ SinkParam (Just (Identifier "args")) ]
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "mat")) (Ident (Identifier "math")))
+                 [ NormalArg
+                     (FuncCall
+                        (FieldAccess
+                           (Ident (Identifier "pos")) (Ident (Identifier "args")))
+                        [])
+                 ]))
+       , KeyValArg (Identifier "full") (Literal (Boolean True))
+       ])
+, SoftBreak
+, EnumListItem
+    Nothing
+    [ Text "A"
+    , SoftBreak
+    , EnumListItem Nothing [ Text "B" ]
+    , SoftBreak
+    , EnumListItem
+        Nothing
+        [ Text "C" , SoftBreak , EnumListItem Nothing [ Text "D" ] ]
+    ]
+, SoftBreak
+, EnumListItem Nothing [ Text "E" ]
+, SoftBreak
+, EnumListItem Nothing [ Text "F" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       font: "New Computer Modern"), 
+  text(body: [
+], 
+       font: "New Computer Modern"), 
+  enum(children: ({ text(body: [A
+], 
+                         font: "New Computer Modern"), 
+                    enum(children: (text(body: [B], 
+                                         font: "New Computer Modern"), 
+                                    { text(body: [C
+], 
+                                           font: "New Computer Modern"), 
+                                      enum(children: (text(body: [D], 
+                                                           font: "New Computer Modern")), 
+                                           full: true, 
+                                           numbering: ) }), 
+                         full: true, 
+                         numbering: ) }, 
+                  text(body: [E], 
+                       font: "New Computer Modern"), 
+                  { text(body: [F], 
+                         font: "New Computer Modern"), 
+                    parbreak() }), 
+       full: true, 
+       numbering: ) }
diff --git a/test/out/layout/enum-numbering-05.out b/test/out/layout/enum-numbering-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-numbering-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/enum-numbering-06.out b/test/out/layout/enum-numbering-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/enum-numbering-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/flow-orphan-00.out b/test/out/layout/flow-orphan-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/flow-orphan-00.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/flow-orphan-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/flow-orphan-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/flow-orphan-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/flow-orphan-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/flow-orphan-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 12)) ])
+, ParBreak
+, Heading 1 [ Text "Introduction" ]
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "start"
+, Space
+, Text "and"
+, Space
+, Text "it"
+, Space
+, Text "goes"
+, Space
+, Text "on"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor]), 
+  parbreak(), 
+  heading(body: text(body: [Introduction]), 
+          level: 1), 
+  text(body: [This is the start and it goes on.]), 
+  parbreak() }
diff --git a/test/out/layout/flow-orphan-01.out b/test/out/layout/flow-orphan-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/flow-orphan-01.out
@@ -0,0 +1,152 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/flow-orphan-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/flow-orphan-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ NormalArg (Literal (String "a8"))
+       , KeyValArg (Identifier "height") (Literal (Numeric 140.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "weight") (Literal (Int 700)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Ident (Identifier "blue")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 27)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+, ParBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 14 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Ident (Identifier "maroon")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 11)) ])
+, ParBreak
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 13)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 20 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Ident (Identifier "olive")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/flow-orphan-01.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 10)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+], 
+       color: rgb(0%,45%,85%,100%), 
+       weight: 700), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation], 
+       color: rgb(0%,45%,85%,100%), 
+       weight: 700), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut], 
+       color: rgb(0%,45%,85%,100%), 
+       weight: 700), 
+  parbreak(), 
+  text(body: [
+], 
+       color: rgb(52%,7%,29%,100%), 
+       weight: 700), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod], 
+       color: rgb(52%,7%,29%,100%), 
+       weight: 700), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt], 
+       color: rgb(52%,7%,29%,100%), 
+       weight: 700), 
+  parbreak(), 
+  text(body: [
+], 
+       color: rgb(23%,60%,43%,100%), 
+       weight: 700), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do], 
+       color: rgb(23%,60%,43%,100%), 
+       weight: 700), 
+  parbreak() }
diff --git a/test/out/layout/grid-1-00.out b/test/out/layout/grid-1-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-1-00.out
@@ -0,0 +1,229 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-1-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-1-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-1-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-1-00.typ"
+    ( line 2 , column 2 )
+    (LetFunc
+       (Identifier "cell")
+       [ NormalParam (Identifier "width")
+       , NormalParam (Identifier "color")
+       ]
+       (FuncCall
+          (Ident (Identifier "rect"))
+          [ KeyValArg (Identifier "width") (Ident (Identifier "width"))
+          , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm))
+          , KeyValArg (Identifier "fill") (Ident (Identifier "color"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-1-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 140.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-1-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array
+              [ Literal Auto
+              , Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 3.0 Fr)
+              , Literal (Numeric 0.25 Cm)
+              , Literal (Numeric 3.0 Percent)
+              , Plus (Literal (Numeric 2.0 Mm)) (Literal (Numeric 10.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 0.5 Cm))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "2a631a")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg (Ident (Identifier "red"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "ff0000")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "00ff00")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 80.0 Percent))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "00faf0")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 1.0 Cm))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "00ff00")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 0.5 Cm))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "2a631a")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg (Ident (Identifier "red"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "ff0000")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "cell"))
+              [ NormalArg (Literal (Numeric 100.0 Percent))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "00ff00")) ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (rect(fill: rgb(16%,38%,10%,100%), 
+                       height: 2.0cm, 
+                       width: 0.5cm), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 2.0cm, 
+                       width: 100%), 
+                  rect(fill: rgb(18%,80%,25%,100%), 
+                       height: 2.0cm, 
+                       width: 100%), 
+                  rect(fill: rgb(100%,0%,0%,100%), 
+                       height: 2.0cm, 
+                       width: 100%), 
+                  rect(fill: rgb(0%,100%,0%,100%), 
+                       height: 2.0cm, 
+                       width: 100%), 
+                  rect(fill: rgb(0%,98%,94%,100%), 
+                       height: 2.0cm, 
+                       width: 80%), 
+                  rect(fill: rgb(0%,100%,0%,100%), 
+                       height: 2.0cm, 
+                       width: 1.0cm), 
+                  rect(fill: rgb(16%,38%,10%,100%), 
+                       height: 2.0cm, 
+                       width: 0.5cm), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 2.0cm, 
+                       width: 100%), 
+                  rect(fill: rgb(18%,80%,25%,100%), 
+                       height: 2.0cm, 
+                       width: 100%), 
+                  rect(fill: rgb(100%,0%,0%,100%), 
+                       height: 2.0cm, 
+                       width: 100%), 
+                  rect(fill: rgb(0%,100%,0%,100%), 
+                       height: 2.0cm, 
+                       width: 100%)), 
+       columns: (auto, 
+                 1.0fr, 
+                 3.0fr, 
+                 0.25cm, 
+                 3%, 
+                 2.0mm + 10%)), 
+  parbreak() }
diff --git a/test/out/layout/grid-1-01.out b/test/out/layout/grid-1-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-1-01.out
@@ -0,0 +1,103 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-1-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-1-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-1-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-1-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-1-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array
+              [ Literal Auto , Literal Auto , Literal (Numeric 40.0 Percent) ])
+       , KeyValArg (Identifier "column-gutter") (Literal (Numeric 1.0 Fr))
+       , KeyValArg (Identifier "row-gutter") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              , BlockArg
+                  [ Text "dddaa" , Space , Text "aaa" , Space , Text "aaa" ]
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              , BlockArg [ Text "ccc" ]
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "dddddd")) ])
+              , BlockArg [ Text "aaa" ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (rect(body: text(body: [dddaa aaa aaa]), 
+                       fill: rgb(13%,61%,67%,100%), 
+                       inset: 0.0pt), 
+                  rect(body: text(body: [ccc]), 
+                       fill: rgb(18%,80%,25%,100%), 
+                       inset: 0.0pt), 
+                  rect(body: text(body: [aaa]), 
+                       fill: rgb(86%,86%,86%,100%), 
+                       inset: 0.0pt)), 
+       column-gutter: 1.0fr, 
+       columns: (auto, auto, 40%), 
+       row-gutter: 1.0fr), 
+  parbreak() }
diff --git a/test/out/layout/grid-1-02.out b/test/out/layout/grid-1-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-1-02.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-1-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-1-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-1-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-1-02.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 3.0 Cm))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-1-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns") (Array [ Literal (Numeric 1.0 Fr) ])
+       , KeyValArg
+           (Identifier "rows")
+           (Array
+              [ Literal (Numeric 1.0 Fr)
+              , Literal Auto
+              , Literal (Numeric 2.0 Fr)
+              ])
+       , NormalArg (Block (Content []))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "center"))
+              , BlockArg
+                  [ Text "A"
+                  , Space
+                  , Text "bit"
+                  , Space
+                  , Text "more"
+                  , Space
+                  , Text "to"
+                  , Space
+                  , Text "the"
+                  , Space
+                  , Text "top"
+                  ]
+              ])
+       , NormalArg (Block (Content []))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: ({  }, 
+                  align(alignment: center, 
+                        body: text(body: [A bit more to the top])), 
+                  {  }), 
+       columns: (1.0fr), 
+       rows: (1.0fr, auto, 2.0fr)), 
+  parbreak() }
diff --git a/test/out/layout/grid-2-00.out b/test/out/layout/grid-2-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-2-00.out
@@ -0,0 +1,165 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-2-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-2-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-2-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-2-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 11.0 Cm))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.5 Cm))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-2-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 5))
+       , KeyValArg
+           (Identifier "column-gutter")
+           (Array
+              [ Literal (Numeric 2.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              ])
+       , KeyValArg (Identifier "row-gutter") (Literal (Numeric 6.0 Pt))
+       , NormalArg (Block (Content [ Strong [ Text "Quarter" ] ]))
+       , NormalArg (Block (Content [ Text "Expenditure" ]))
+       , NormalArg
+           (Block (Content [ Text "External" , Space , Text "Revenue" ]))
+       , NormalArg
+           (Block (Content [ Text "Financial" , Space , Text "ROI" ]))
+       , NormalArg (Block (Content [ Emph [ Text "total" ] ]))
+       , NormalArg (Block (Content [ Strong [ Text "Q1" ] ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "173,472" , Text "." , Text "57" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "472,860" , Text "." , Text "91" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "51,286" , Text "." , Text "84" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Emph [ Text "350,675" , Text "." , Text "18" , Space , Text "$" ]
+                 ]))
+       , NormalArg (Block (Content [ Strong [ Text "Q2" ] ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "93,382" , Text "." , Text "12" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "439,382" , Text "." , Text "85" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "-"
+                 , Text "1,134"
+                 , Text "."
+                 , Text "30"
+                 , Space
+                 , Text "$"
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Emph [ Text "344,866" , Text "." , Text "43" , Space , Text "$" ]
+                 ]))
+       , NormalArg (Block (Content [ Strong [ Text "Q3" ] ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "96,421" , Text "." , Text "49" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "238,583" , Text "." , Text "54" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "3,497" , Text "." , Text "12" , Space , Text "$" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Emph [ Text "145,659" , Text "." , Text "17" , Space , Text "$" ]
+                 ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (strong(body: text(body: [Quarter])), 
+                  text(body: [Expenditure]), 
+                  text(body: [External Revenue]), 
+                  text(body: [Financial ROI]), 
+                  emph(body: text(body: [total])), 
+                  strong(body: text(body: [Q1])), 
+                  text(body: [173,472.57 $]), 
+                  text(body: [472,860.91 $]), 
+                  text(body: [51,286.84 $]), 
+                  emph(body: text(body: [350,675.18 $])), 
+                  strong(body: text(body: [Q2])), 
+                  text(body: [93,382.12 $]), 
+                  text(body: [439,382.85 $]), 
+                  text(body: [-1,134.30 $]), 
+                  emph(body: text(body: [344,866.43 $])), 
+                  strong(body: text(body: [Q3])), 
+                  text(body: [96,421.49 $]), 
+                  text(body: [238,583.54 $]), 
+                  text(body: [3,497.12 $]), 
+                  emph(body: text(body: [145,659.17 $]))), 
+       column-gutter: (2.0fr, 
+                       1.0fr, 
+                       1.0fr), 
+       columns: 5, 
+       row-gutter: 6.0pt), 
+  parbreak() }
diff --git a/test/out/layout/grid-3-00.out b/test/out/layout/grid-3-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-3-00.out
@@ -0,0 +1,130 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-3-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-3-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-3-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-3-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 5.0 Cm))
+       , KeyValArg (Identifier "height") (Literal (Numeric 3.0 Cm))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-3-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 2))
+       , KeyValArg (Identifier "row-gutter") (Literal (Numeric 8.0 Pt))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "Lorem"
+                 , Space
+                 , Text "ipsum"
+                 , Space
+                 , Text "dolor"
+                 , Space
+                 , Text "sit"
+                 , Space
+                 , Text "amet"
+                 , Text "."
+                 , ParBreak
+                 , Text "Aenean"
+                 , Space
+                 , Text "commodo"
+                 , Space
+                 , Text "ligula"
+                 , Space
+                 , Text "eget"
+                 , Space
+                 , Text "dolor"
+                 , Text "."
+                 , Space
+                 , Text "Aenean"
+                 , Space
+                 , Text "massa"
+                 , Text "."
+                 , Space
+                 , Text "Penatibus"
+                 , Space
+                 , Text "et"
+                 , Space
+                 , Text "magnis"
+                 , Text "."
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "Text"
+                 , Space
+                 , Text "that"
+                 , Space
+                 , Text "is"
+                 , Space
+                 , Text "rather"
+                 , Space
+                 , Text "short"
+                 ]))
+       , NormalArg (Block (Content [ Text "Fireflies" ]))
+       , NormalArg (Block (Content [ Text "Critical" ]))
+       , NormalArg (Block (Content [ Text "Decorum" ]))
+       , NormalArg (Block (Content [ Text "Rampage" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: ({ text(body: [Lorem ipsum dolor sit amet.]), 
+                    parbreak(), 
+                    text(body: [Aenean commodo ligula eget dolor. Aenean massa. Penatibus et magnis.]) }, 
+                  text(body: [Text that is rather short]), 
+                  text(body: [Fireflies]), 
+                  text(body: [Critical]), 
+                  text(body: [Decorum]), 
+                  text(body: [Rampage])), 
+       columns: 2, 
+       row-gutter: 8.0pt), 
+  parbreak() }
diff --git a/test/out/layout/grid-3-01.out b/test/out/layout/grid-3-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-3-01.out
@@ -0,0 +1,133 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-3-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-3-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-3-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/grid-3-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 5.0 Cm))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-3-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Times (Literal (Int 4)) (Array [ Literal (Numeric 1.0 Fr) ]))
+       , KeyValArg (Identifier "row-gutter") (Literal (Numeric 10.0 Pt))
+       , KeyValArg
+           (Identifier "column-gutter")
+           (Array
+              [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Percent) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "top"))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "image"))
+                     [ NormalArg (Literal (String "test/assets/files/rhino.png")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "top"))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+                     , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "align"))
+                            [ NormalArg (Ident (Identifier "right"))
+                            , BlockArg [ Text "LoL" ]
+                            ])
+                     ])
+              ])
+       , NormalArg (Block (Content [ Text "rofl" ]))
+       , NormalArg
+           (Times
+              (Block (Content [ HardBreak , Text "A" ])) (Literal (Int 3)))
+       , NormalArg
+           (Times
+              (Block (Content [ Text "Ha!" , HardBreak ])) (Literal (Int 3)))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (align(alignment: top, 
+                        body: image(path: "test/assets/files/rhino.png")), 
+                  align(alignment: top, 
+                        body: rect(body: align(alignment: right, 
+                                               body: text(body: [LoL])), 
+                                   fill: rgb(13%,61%,67%,100%), 
+                                   inset: 0.0pt)), 
+                  text(body: [rofl]), 
+                  { linebreak(), 
+                    text(body: [A]), 
+                    linebreak(), 
+                    text(body: [A]), 
+                    linebreak(), 
+                    text(body: [A]) }, 
+                  { text(body: [Ha!]), 
+                    linebreak(), 
+                    text(body: [Ha!]), 
+                    linebreak(), 
+                    text(body: [Ha!]), 
+                    linebreak() }), 
+       column-gutter: (0.0pt, 10%), 
+       columns: (1.0fr, 
+                 1.0fr, 
+                 1.0fr, 
+                 1.0fr), 
+       row-gutter: 10.0pt), 
+  parbreak() }
diff --git a/test/out/layout/grid-3-02.out b/test/out/layout/grid-3-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-3-02.out
@@ -0,0 +1,116 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-3-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-3-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-3-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/grid-3-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 5.0 Cm))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-3-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Times (Literal (Int 3)) (Array [ Literal (Numeric 1.0 Fr) ]))
+       , KeyValArg (Identifier "row-gutter") (Literal (Numeric 8.0 Pt))
+       , KeyValArg
+           (Identifier "column-gutter")
+           (Array
+              [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Percent) ])
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Block (Content [ Text "B" ]))
+       , NormalArg (Block (Content [ Text "C" ]))
+       , NormalArg
+           (Times
+              (Block (Content [ Text "Ha!" , HardBreak ])) (Literal (Int 6)))
+       , NormalArg (Block (Content [ Text "rofl" ]))
+       , NormalArg
+           (Times
+              (Block (Content [ HardBreak , Text "A" ])) (Literal (Int 3)))
+       , NormalArg (Block (Content [ Text "hello" ]))
+       , NormalArg (Block (Content [ Text "darkness" ]))
+       , NormalArg (Block (Content [ Text "my" , Space , Text "old" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (text(body: [A]), 
+                  text(body: [B]), 
+                  text(body: [C]), 
+                  { text(body: [Ha!]), 
+                    linebreak(), 
+                    text(body: [Ha!]), 
+                    linebreak(), 
+                    text(body: [Ha!]), 
+                    linebreak(), 
+                    text(body: [Ha!]), 
+                    linebreak(), 
+                    text(body: [Ha!]), 
+                    linebreak(), 
+                    text(body: [Ha!]), 
+                    linebreak() }, 
+                  text(body: [rofl]), 
+                  { linebreak(), 
+                    text(body: [A]), 
+                    linebreak(), 
+                    text(body: [A]), 
+                    linebreak(), 
+                    text(body: [A]) }, 
+                  text(body: [hello]), 
+                  text(body: [darkness]), 
+                  text(body: [my old])), 
+       column-gutter: (0.0pt, 10%), 
+       columns: (1.0fr, 
+                 1.0fr, 
+                 1.0fr), 
+       row-gutter: 8.0pt), 
+  parbreak() }
diff --git a/test/out/layout/grid-3-03.out b/test/out/layout/grid-3-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-3-03.out
@@ -0,0 +1,143 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-3-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-3-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-3-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/grid-3-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 5.0 Cm))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.25 Cm))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-3-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Times (Literal (Int 4)) (Array [ Literal (Numeric 1.0 Fr) ]))
+       , KeyValArg (Identifier "row-gutter") (Literal (Numeric 10.0 Pt))
+       , KeyValArg
+           (Identifier "column-gutter")
+           (Array
+              [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Percent) ])
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Block (Content [ Text "B" ]))
+       , NormalArg (Block (Content [ Text "C" ]))
+       , NormalArg (Block (Content [ Text "D" ]))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "grid"))
+              [ KeyValArg (Identifier "columns") (Literal (Int 2))
+              , NormalArg (Block (Content [ Text "A" ]))
+              , NormalArg (Block (Content [ Text "B" ]))
+              , NormalArg
+                  (Times
+                     (Block (Content [ Text "C" , HardBreak ])) (Literal (Int 3)))
+              , NormalArg (Block (Content [ Text "D" ]))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "top"))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+                     , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "align"))
+                            [ NormalArg (Ident (Identifier "right"))
+                            , BlockArg [ Text "LoL" ]
+                            ])
+                     ])
+              ])
+       , NormalArg (Block (Content [ Text "rofl" ]))
+       , NormalArg
+           (Times
+              (Block (Content [ Text "E" , HardBreak ])) (Literal (Int 4)))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (text(body: [A]), 
+                  text(body: [B]), 
+                  text(body: [C]), 
+                  text(body: [D]), 
+                  grid(children: (text(body: [A]), 
+                                  text(body: [B]), 
+                                  { text(body: [C]), 
+                                    linebreak(), 
+                                    text(body: [C]), 
+                                    linebreak(), 
+                                    text(body: [C]), 
+                                    linebreak() }, 
+                                  text(body: [D])), 
+                       columns: 2), 
+                  align(alignment: top, 
+                        body: rect(body: align(alignment: right, 
+                                               body: text(body: [LoL])), 
+                                   fill: rgb(13%,61%,67%,100%), 
+                                   inset: 0.0pt)), 
+                  text(body: [rofl]), 
+                  { text(body: [E]), 
+                    linebreak(), 
+                    text(body: [E]), 
+                    linebreak(), 
+                    text(body: [E]), 
+                    linebreak(), 
+                    text(body: [E]), 
+                    linebreak() }), 
+       column-gutter: (0.0pt, 10%), 
+       columns: (1.0fr, 
+                 1.0fr, 
+                 1.0fr, 
+                 1.0fr), 
+       row-gutter: 10.0pt), 
+  parbreak() }
diff --git a/test/out/layout/grid-4-00.out b/test/out/layout/grid-4-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-4-00.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-4-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-4-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-4-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/grid-4-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array [ Literal Auto , Literal (Numeric 60.0 Percent) ])
+       , KeyValArg
+           (Identifier "rows") (Array [ Literal Auto , Literal Auto ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 0.5 Cm))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 0.5 Cm))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 0.5 Cm))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  grid(children: (rect(fill: rgb(18%,80%,25%,100%), 
+                       height: 0.5cm, 
+                       width: 50%), 
+                  rect(fill: rgb(13%,61%,67%,100%), 
+                       height: 0.5cm, 
+                       width: 100%), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 0.5cm, 
+                       width: 50%)), 
+       columns: (auto, 60%), 
+       rows: (auto, auto)), 
+  parbreak() }
diff --git a/test/out/layout/grid-4-01.out b/test/out/layout/grid-4-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-4-01.out
@@ -0,0 +1,96 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-4-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-4-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-4-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/grid-4-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Times (Array [ Literal (Numeric 1.0 Fr) ]) (Literal (Int 4)))
+       , KeyValArg
+           (Identifier "rows") (Array [ Literal (Numeric 1.0 Cm) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  grid(children: (rect(fill: rgb(18%,80%,25%,100%), 
+                       width: 50%), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       width: 50%), 
+                  rect(fill: rgb(18%,80%,25%,100%), 
+                       width: 50%), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       width: 50%)), 
+       columns: (1.0fr, 
+                 1.0fr, 
+                 1.0fr, 
+                 1.0fr), 
+       rows: (1.0cm)), 
+  parbreak() }
diff --git a/test/out/layout/grid-4-02.out b/test/out/layout/grid-4-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-4-02.out
@@ -0,0 +1,117 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-4-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-4-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-4-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/grid-4-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 4.0 Cm))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Cm))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-4-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "rows")
+           (Array
+              [ Literal (Numeric 1.0 Cm)
+              , Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              , Literal Auto
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 25.0 Percent))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (rect(fill: rgb(18%,80%,25%,100%), 
+                       height: 50%, 
+                       width: 100%), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 50%, 
+                       width: 100%), 
+                  rect(fill: rgb(18%,80%,25%,100%), 
+                       height: 50%, 
+                       width: 100%), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 25%, 
+                       width: 100%)), 
+       rows: (1.0cm, 
+              1.0fr, 
+              1.0fr, 
+              auto)), 
+  parbreak() }
diff --git a/test/out/layout/grid-5-00.out b/test/out/layout/grid-5-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-5-00.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-5-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-5-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-5-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/grid-5-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-5-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ BlockArg
+           [ SoftBreak
+           , Text "Hello"
+           , Space
+           , HardBreak
+           , Text "Hello"
+           , Space
+           , HardBreak
+           , Text "Hello"
+           , Space
+           , HardBreak
+           , SoftBreak
+           , Text "World"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: ({ text(body: [
+Hello ]), 
+                    linebreak(), 
+                    text(body: [Hello ]), 
+                    linebreak(), 
+                    text(body: [Hello ]), 
+                    linebreak(), 
+                    text(body: [
+World]), 
+                    parbreak() })), 
+  parbreak() }
diff --git a/test/out/layout/grid-5-01.out b/test/out/layout/grid-5-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-5-01.out
@@ -0,0 +1,128 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-5-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-5-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-5-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/grid-5-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 2.25 Cm)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-5-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 2))
+       , KeyValArg (Identifier "gutter") (Literal (Numeric 10.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "bottom"))
+              , BlockArg [ Text "A" ]
+              ])
+       , NormalArg
+           (Block
+              (Content
+                 [ SoftBreak
+                 , Text "Top"
+                 , SoftBreak
+                 , Code
+                     "test/typ/layout/grid-5-01.typ"
+                     ( line 10 , column 6 )
+                     (FuncCall
+                        (Ident (Identifier "align"))
+                        [ NormalArg (Ident (Identifier "bottom"))
+                        , BlockArg
+                            [ SoftBreak
+                            , Text "Bottom"
+                            , Space
+                            , HardBreak
+                            , Text "Bottom"
+                            , Space
+                            , HardBreak
+                            , Code
+                                "test/typ/layout/grid-5-01.typ"
+                                ( line 13 , column 8 )
+                                (FuncCall
+                                   (Ident (Identifier "v"))
+                                   [ NormalArg (Literal (Numeric 0.0 Pt)) ])
+                            , SoftBreak
+                            , Text "Top"
+                            , ParBreak
+                            ]
+                        ])
+                 , ParBreak
+                 ]))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "top")) , BlockArg [ Text "B" ] ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (align(alignment: bottom, 
+                        body: text(body: [A])), 
+                  { text(body: [
+Top
+]), 
+                    align(alignment: bottom, 
+                          body: { text(body: [
+Bottom ]), 
+                                  linebreak(), 
+                                  text(body: [Bottom ]), 
+                                  linebreak(), 
+                                  v(amount: 0.0pt), 
+                                  text(body: [
+Top]), 
+                                  parbreak() }), 
+                    parbreak() }, 
+                  align(alignment: top, 
+                        body: text(body: [B]))), 
+       columns: 2, 
+       gutter: 10.0pt), 
+  parbreak() }
diff --git a/test/out/layout/grid-auto-shrink-00.out b/test/out/layout/grid-auto-shrink-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-auto-shrink-00.out
@@ -0,0 +1,139 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-auto-shrink-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-auto-shrink-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-auto-shrink-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-auto-shrink-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg
+           (Identifier "width")
+           (Plus
+              (Minus
+                 (Literal (Numeric 210.0 Mm))
+                 (Times (Literal (Int 2)) (Literal (Numeric 2.5 Cm))))
+              (Times (Literal (Int 2)) (Literal (Numeric 10.0 Pt))))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-auto-shrink-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 11.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-auto-shrink-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 4))
+       , NormalArg (Block (Content [ Text "Hello!" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "Hello"
+                 , Space
+                 , Text "there,"
+                 , Space
+                 , Text "my"
+                 , Space
+                 , Text "friend!"
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "Hello"
+                 , Space
+                 , Text "there,"
+                 , Space
+                 , Text "my"
+                 , Space
+                 , Text "friends!"
+                 , Space
+                 , Text "Hi!"
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "Hello"
+                 , Space
+                 , Text "there,"
+                 , Space
+                 , Text "my"
+                 , Space
+                 , Text "friends!"
+                 , Space
+                 , Text "Hi!"
+                 , Space
+                 , Text "What"
+                 , Space
+                 , Text "is"
+                 , Space
+                 , Text "going"
+                 , Space
+                 , Text "on"
+                 , Space
+                 , Text "right"
+                 , Space
+                 , Text "now?"
+                 ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       size: 11.0pt), 
+  table(children: (text(body: [Hello!], 
+                        size: 11.0pt), 
+                   text(body: [Hello there, my friend!], 
+                        size: 11.0pt), 
+                   text(body: [Hello there, my friends! Hi!], 
+                        size: 11.0pt), 
+                   text(body: [Hello there, my friends! Hi! What is going on right now?], 
+                        size: 11.0pt)), 
+        columns: 4), 
+  parbreak() }
diff --git a/test/out/layout/grid-rtl-00.out b/test/out/layout/grid-rtl-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-rtl-00.out
@@ -0,0 +1,63 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-rtl-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-rtl-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-rtl-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-rtl-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl")) ])
+, SoftBreak
+, BulletListItem
+    [ Text "\1502\1497\1502\1497\1503"
+    , Space
+    , Text "\1500\1513\1502\1488\1500"
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], dir: rtl), 
+  list(children: ({ text(body: [מימין לשמאל], 
+                         dir: rtl), 
+                    parbreak() })) }
diff --git a/test/out/layout/grid-rtl-01.out b/test/out/layout/grid-rtl-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/grid-rtl-01.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/grid-rtl-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/grid-rtl-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/grid-rtl-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/grid-rtl-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/grid-rtl-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 2))
+       , BlockArg [ Text "A" ]
+       , BlockArg [ Text "B" ]
+       , BlockArg [ Text "C" ]
+       , BlockArg [ Text "D" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], dir: rtl), 
+  table(children: (text(body: [A], 
+                        dir: rtl), 
+                   text(body: [B], dir: rtl), 
+                   text(body: [C], dir: rtl), 
+                   text(body: [D], dir: rtl)), 
+        columns: 2), 
+  parbreak() }
diff --git a/test/out/layout/hide-00.out b/test/out/layout/hide-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/hide-00.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/hide-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/hide-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/hide-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Text "AB"
+, Space
+, Code
+    "test/typ/layout/hide-00.typ"
+    ( line 2 , column 5 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "CD"
+, Space
+, HardBreak
+, Code
+    "test/typ/layout/hide-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall (Ident (Identifier "hide")) [ BlockArg [ Text "A" ] ])
+, Text "B"
+, Space
+, Code
+    "test/typ/layout/hide-00.typ"
+    ( line 3 , column 12 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "C"
+, Code
+    "test/typ/layout/hide-00.typ"
+    ( line 3 , column 21 )
+    (FuncCall (Ident (Identifier "hide")) [ BlockArg [ Text "D" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+AB ]), 
+  h(amount: 1.0fr), 
+  text(body: [ CD ]), 
+  linebreak(), 
+  hide(body: text(body: [A])), 
+  text(body: [B ]), 
+  h(amount: 1.0fr), 
+  text(body: [ C]), 
+  hide(body: text(body: [D])), 
+  parbreak() }
diff --git a/test/out/layout/list-00.out b/test/out/layout/list-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-00.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Emph [ Text "Shopping" , Space , Text "list" ]
+, SoftBreak
+, Code
+    "test/typ/layout/list-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "list"))
+       [ BlockArg [ Text "Apples" ]
+       , BlockArg [ Text "Potatoes" ]
+       , BlockArg [ Text "Juice" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  emph(body: text(body: [Shopping list])), 
+  text(body: [
+]), 
+  list(children: (text(body: [Apples]), 
+                  text(body: [Potatoes]), 
+                  text(body: [Juice]))), 
+  parbreak() }
diff --git a/test/out/layout/list-01.out b/test/out/layout/list-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-01.out
@@ -0,0 +1,115 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, BulletListItem
+    [ Text "First"
+    , Space
+    , Text "level"
+    , Text "."
+    , ParBreak
+    , BulletListItem
+        [ Text "Second"
+        , Space
+        , Text "level"
+        , Text "."
+        , SoftBreak
+        , Text "There"
+        , Space
+        , Text "are"
+        , Space
+        , Text "multiple"
+        , Space
+        , Text "paragraphs"
+        , Text "."
+        , ParBreak
+        , BulletListItem
+            [ Text "Third" , Space , Text "level" , Text "." , SoftBreak ]
+        , SoftBreak
+        , Text "Still"
+        , Space
+        , Text "the"
+        , Space
+        , Text "same"
+        , Space
+        , Text "bullet"
+        , Space
+        , Text "point"
+        , Text "."
+        , SoftBreak
+        ]
+    , SoftBreak
+    , BulletListItem
+        [ Text "Still"
+        , Space
+        , Text "level"
+        , Space
+        , Text "2"
+        , Text "."
+        , SoftBreak
+        ]
+    ]
+, SoftBreak
+, BulletListItem
+    [ Text "At"
+    , Space
+    , Text "the"
+    , Space
+    , Text "top"
+    , Text "."
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  list(children: ({ text(body: [First level.]), 
+                    parbreak(), 
+                    list(children: ({ text(body: [Second level.
+There are multiple paragraphs.]), 
+                                      parbreak(), 
+                                      list(children: (text(body: [Third level.
+]))), 
+                                      text(body: [Still the same bullet point.
+]) }, 
+                                    text(body: [Still level 2.
+]))) }, 
+                  { text(body: [At the top.]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-02.out b/test/out/layout/list-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-02.out
@@ -0,0 +1,76 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Text "-"
+, Space
+, Text "Level"
+, Space
+, Text "1"
+, SoftBreak
+, Text "-"
+, Space
+, Text "Level"
+, Space
+, Code
+    "test/typ/layout/list-02.typ"
+    ( line 3 , column 12 )
+    (Block
+       (Content
+          [ SoftBreak
+          , Text "2"
+          , Space
+          , Text "through"
+          , Space
+          , Text "content"
+          , Space
+          , Text "block"
+          , ParBreak
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+- Level 1
+- Level ]), 
+  text(body: [
+2 through content block]), 
+  parbreak(), 
+  parbreak() }
diff --git a/test/out/layout/list-03.out b/test/out/layout/list-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-03.out
@@ -0,0 +1,53 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, BulletListItem
+    [ Text "Top" , Text "-" , Text "level" , Space , Text "indent" ]
+, SoftBreak
+, BulletListItem
+    [ Text "is" , Space , Text "fine" , Text "." , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  list(children: (text(body: [Top-level indent]), 
+                  { text(body: [is fine.]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-04.out b/test/out/layout/list-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-04.out
@@ -0,0 +1,60 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, BulletListItem
+    [ Text "A"
+    , SoftBreak
+    , BulletListItem [ Text "B" ]
+    , SoftBreak
+    , BulletListItem [ Text "C" ]
+    ]
+, SoftBreak
+, BulletListItem [ Text "D" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  list(children: ({ text(body: [A
+]), 
+                    list(children: (text(body: [B]), 
+                                    text(body: [C]))) }, 
+                  { text(body: [D]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-05.out b/test/out/layout/list-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-05.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Space
+, Text "-"
+, Space
+, Text "A"
+, Space
+, Text "with"
+, Space
+, Text "1"
+, Space
+, Text "tab"
+, SoftBreak
+, BulletListItem
+    [ Text "B"
+    , Space
+    , Text "with"
+    , Space
+    , Text "2"
+    , Space
+    , Text "tabs"
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [ - A with 1 tab
+]), 
+  list(children: ({ text(body: [B with 2 tabs]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-06.out b/test/out/layout/list-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-06.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Space
+, Text "-"
+, Space
+, Text "A"
+, Space
+, Text "with"
+, Space
+, Text "2"
+, Space
+, Text "spaces"
+, SoftBreak
+, BulletListItem
+    [ Text "B"
+    , Space
+    , Text "with"
+    , Space
+    , Text "2"
+    , Space
+    , Text "tabs"
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [ - A with 2 spaces
+]), 
+  list(children: ({ text(body: [B with 2 tabs]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-07.out b/test/out/layout/list-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-07.out
@@ -0,0 +1,61 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, BulletListItem []
+, SoftBreak
+, Text "Not"
+, Space
+, Text "in"
+, Space
+, Text "list"
+, SoftBreak
+, Text "-"
+, Text "Nope"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  list(children: ({  })), 
+  text(body: [Not in list
+-Nope]), 
+  parbreak() }
diff --git a/test/out/layout/list-08.out b/test/out/layout/list-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-08.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-08.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "horizon")) ])
+, ParBreak
+, BulletListItem
+    [ Text "ABCDEF"
+    , HardBreak
+    , Text "GHIJKL"
+    , HardBreak
+    , Text "MNOPQR"
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  list(children: ({ text(body: [ABCDEF]), 
+                    linebreak(), 
+                    text(body: [GHIJKL]), 
+                    linebreak(), 
+                    text(body: [MNOPQR]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-attach-00.out b/test/out/layout/list-attach-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-attach-00.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-attach-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-attach-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-attach-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Attached"
+, Space
+, Text "to"
+, Text ":"
+, SoftBreak
+, BulletListItem [ Text "the" , Space , Text "bottom" ]
+, SoftBreak
+, BulletListItem
+    [ Text "of"
+    , Space
+    , Text "the"
+    , Space
+    , Text "paragraph"
+    , SoftBreak
+    ]
+, SoftBreak
+, Text "Next"
+, Space
+, Text "paragraph"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Attached to:
+]), 
+  list(children: (text(body: [the bottom]), 
+                  text(body: [of the paragraph
+]))), 
+  text(body: [Next paragraph.]), 
+  parbreak() }
diff --git a/test/out/layout/list-attach-01.out b/test/out/layout/list-attach-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-attach-01.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-attach-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-attach-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-attach-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-attach-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (Set
+          (Ident (Identifier "block"))
+          [ KeyValArg (Identifier "above") (Literal (Numeric 100.0 Pt)) ]))
+, SoftBreak
+, Text "Hello"
+, SoftBreak
+, BulletListItem [ Text "A" ]
+, SoftBreak
+, Text "World"
+, SoftBreak
+, BulletListItem [ Text "B" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Hello
+]), 
+  list(children: (text(body: [A]))), 
+  text(body: [World
+]), 
+  list(children: ({ text(body: [B]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-attach-02.out b/test/out/layout/list-attach-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-attach-02.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-attach-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-attach-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-attach-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Text "Hello"
+, ParBreak
+, BulletListItem [ Text "A" , SoftBreak ]
+, SoftBreak
+, Text "World"
+, SoftBreak
+, BulletListItem [ Text "B" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Hello]), 
+  parbreak(), 
+  list(children: (text(body: [A
+]))), 
+  text(body: [World
+]), 
+  list(children: ({ text(body: [B]), 
+                    parbreak() })) }
diff --git a/test/out/layout/list-attach-03.out b/test/out/layout/list-attach-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-attach-03.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-attach-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-attach-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-attach-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-attach-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 15.0 Pt)) ])
+, SoftBreak
+, Text "Hello"
+, SoftBreak
+, BulletListItem [ Text "A" ]
+, SoftBreak
+, Text "World"
+, ParBreak
+, BulletListItem [ Text "B" ]
+, SoftBreak
+, BulletListItem [ Text "C" , SoftBreak ]
+, SoftBreak
+, Text "More"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Hello
+]), 
+  list(children: (text(body: [A]))), 
+  text(body: [World]), 
+  parbreak(), 
+  list(children: (text(body: [B]), 
+                  text(body: [C
+]))), 
+  text(body: [More.]), 
+  parbreak() }
diff --git a/test/out/layout/list-attach-04.out b/test/out/layout/list-attach-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-attach-04.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-attach-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-attach-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-attach-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-attach-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 15.0 Pt)) ])
+, SoftBreak
+, Text "Hello"
+, SoftBreak
+, BulletListItem [ Text "A" , SoftBreak ]
+, SoftBreak
+, BulletListItem [ Text "B" ]
+, SoftBreak
+, Text "World"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Hello
+]), 
+  list(children: (text(body: [A
+]), 
+                  text(body: [B]))), 
+  text(body: [World]), 
+  parbreak() }
diff --git a/test/out/layout/list-attach-05.out b/test/out/layout/list-attach-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-attach-05.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-attach-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-attach-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-attach-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Hello"
+, SoftBreak
+, Code
+    "test/typ/layout/list-attach-05.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "list"))
+       [ KeyValArg (Identifier "tight") (Literal (Boolean False))
+       , BlockArg [ Text "A" ]
+       , BlockArg [ Text "B" ]
+       ])
+, SoftBreak
+, Text "World"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Hello
+]), 
+  list(children: (text(body: [A]), 
+                  text(body: [B])), 
+       tight: false), 
+  text(body: [
+World]), 
+  parbreak() }
diff --git a/test/out/layout/list-marker-00.out b/test/out/layout/list-marker-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-marker-00.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-marker-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-marker-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-marker-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-marker-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "list"))
+       [ KeyValArg (Identifier "marker") (Block (Content [ EnDash ])) ])
+, SoftBreak
+, BulletListItem [ Text "A" ]
+, SoftBreak
+, BulletListItem [ Text "B" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  list(children: (text(body: [A]), 
+                  { text(body: [B]), 
+                    parbreak() }), 
+       marker: text(body: [–])) }
diff --git a/test/out/layout/list-marker-01.out b/test/out/layout/list-marker-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-marker-01.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-marker-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-marker-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-marker-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-marker-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "list"))
+       [ KeyValArg
+           (Identifier "marker")
+           (Array
+              [ Block (Content [ EnDash ]) , Block (Content [ Text "\8226" ]) ])
+       ])
+, SoftBreak
+, BulletListItem
+    [ Text "A"
+    , SoftBreak
+    , BulletListItem
+        [ Text "B" , SoftBreak , BulletListItem [ Text "C" , ParBreak ] ]
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  list(children: ({ text(body: [A
+]), 
+                    list(children: ({ text(body: [B
+]), 
+                                      list(children: ({ text(body: [C]), 
+                                                        parbreak() }), 
+                                           marker: (text(body: [–]), 
+                                                    text(body: [•]))) }), 
+                         marker: (text(body: [–]), 
+                                  text(body: [•]))) }), 
+       marker: (text(body: [–]), 
+                text(body: [•]))) }
diff --git a/test/out/layout/list-marker-02.out b/test/out/layout/list-marker-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-marker-02.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-marker-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-marker-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-marker-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-marker-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "list"))
+       [ KeyValArg
+           (Identifier "marker")
+           (FuncExpr
+              [ NormalParam (Identifier "n") ]
+              (If
+                 [ ( Equals (Ident (Identifier "n")) (Literal (Int 1))
+                   , Block (Content [ EnDash ])
+                   )
+                 , ( Literal (Boolean True) , Block (Content [ Text "\8226" ]) )
+                 ]))
+       ])
+, SoftBreak
+, BulletListItem [ Text "A" ]
+, SoftBreak
+, BulletListItem
+    [ Text "B"
+    , SoftBreak
+    , BulletListItem [ Text "C" ]
+    , SoftBreak
+    , BulletListItem
+        [ Text "D" , SoftBreak , BulletListItem [ Text "E" ] ]
+    ]
+, SoftBreak
+, BulletListItem [ Text "F" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  list(children: (text(body: [A]), 
+                  { text(body: [B
+]), 
+                    list(children: (text(body: [C]), 
+                                    { text(body: [D
+]), 
+                                      list(children: (text(body: [E])), 
+                                           marker: ) }), 
+                         marker: ) }, 
+                  { text(body: [F]), 
+                    parbreak() }), 
+       marker: ) }
diff --git a/test/out/layout/list-marker-03.out b/test/out/layout/list-marker-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-marker-03.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/list-marker-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/list-marker-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/list-marker-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/list-marker-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "list"))
+       [ KeyValArg
+           (Identifier "marker") (Block (Content [ BulletListItem [] ]))
+       ])
+, SoftBreak
+, BulletListItem
+    [ Text "Bare" , Space , Text "hyphen" , Space , Text "is" ]
+, SoftBreak
+, BulletListItem
+    [ Text "a"
+    , Space
+    , Text "bad"
+    , Space
+    , Text "marker"
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  list(children: (text(body: [Bare hyphen is]), 
+                  { text(body: [a bad marker]), 
+                    parbreak() }), 
+       marker: list(children: ({  }))) }
diff --git a/test/out/layout/list-marker-04.out b/test/out/layout/list-marker-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/list-marker-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/pad-00.out b/test/out/layout/pad-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pad-00.out
@@ -0,0 +1,124 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pad-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pad-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pad-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/pad-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pad"))
+       [ KeyValArg (Identifier "left") (Literal (Numeric 10.0 Pt))
+       , NormalArg (Block (Content [ Text "Indented!" ]))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/pad-00.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/pad-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "pad"))
+              [ NormalArg (Literal (Numeric 10.0 Pt))
+              , KeyValArg (Identifier "right") (Literal (Numeric 20.0 Pt))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Pt))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+                     , KeyValArg
+                         (Identifier "fill")
+                         (FuncCall
+                            (Ident (Identifier "rgb"))
+                            [ NormalArg (Literal (String "eb5278")) ])
+                     ])
+              ])
+       ])
+, ParBreak
+, Text "Hi"
+, Space
+, Code
+    "test/typ/layout/pad-00.typ"
+    ( line 13 , column 5 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "pad"))
+              [ KeyValArg (Identifier "left") (Literal (Numeric 10.0 Pt))
+              , BlockArg [ Text "A" ]
+              ])
+       ])
+, Space
+, Text "there"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  pad(body: text(body: [Indented!]), 
+      left: 10.0pt), 
+  parbreak(), 
+  text(body: [
+]), 
+  rect(body: pad(body: rect(fill: rgb(92%,32%,47%,100%), 
+                            height: 20.0pt, 
+                            inset: 0.0pt, 
+                            width: 20.0pt), 
+                 rest: 10.0pt, 
+                 right: 20.0pt), 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 0.0pt), 
+  parbreak(), 
+  text(body: [Hi ]), 
+  box(body: pad(body: text(body: [A]), 
+                left: 10.0pt)), 
+  text(body: [ there]), 
+  parbreak() }
diff --git a/test/out/layout/pad-01.out b/test/out/layout/pad-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pad-01.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pad-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pad-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pad-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/pad-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pad"))
+       [ KeyValArg (Identifier "left") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "right") (Literal (Numeric 10.0 Pt))
+       , BlockArg
+           [ Text "PL"
+           , Space
+           , Code
+               "test/typ/layout/pad-01.typ"
+               ( line 3 , column 35 )
+               (FuncCall
+                  (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+           , Space
+           , Text "PR"
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  pad(body: { text(body: [PL ]), 
+              h(amount: 1.0fr), 
+              text(body: [ PR]) }, 
+      left: 10.0pt, 
+      right: 10.0pt), 
+  parbreak() }
diff --git a/test/out/layout/pad-02.out b/test/out/layout/pad-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pad-02.out
@@ -0,0 +1,96 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pad-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pad-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pad-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/pad-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 6.0 Cm)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/pad-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "left"))
+       , BlockArg [ Text "Before" ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/pad-02.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pad"))
+       [ NormalArg (Literal (Numeric 10.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg")) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/pad-02.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "right"))
+       , BlockArg [ Text "After" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  align(alignment: left, 
+        body: text(body: [Before])), 
+  text(body: [
+]), 
+  pad(body: image(path: "test/assets/files/tiger.jpg"), 
+      rest: 10.0pt), 
+  text(body: [
+]), 
+  align(alignment: right, 
+        body: text(body: [After])), 
+  parbreak() }
diff --git a/test/out/layout/pad-03.out b/test/out/layout/pad-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pad-03.out
@@ -0,0 +1,55 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pad-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pad-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pad-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/pad-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pad"))
+       [ NormalArg (Literal (Numeric 50.0 Percent)) , BlockArg [] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  pad(body: {  }, rest: 50%), 
+  parbreak() }
diff --git a/test/out/layout/page-00.out b/test/out/layout/page-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-00.out
@@ -0,0 +1,54 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall (Ident (Identifier "page")) [ BlockArg [] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  page(body: {  }), 
+  parbreak() }
diff --git a/test/out/layout/page-01.out b/test/out/layout/page-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-01.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "page"))
+       [ NormalArg (Literal (String "a11"))
+       , KeyValArg (Identifier "flipped") (Literal (Boolean True))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , BlockArg []
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  page(body: [a11], 
+       fill: rgb(18%,80%,25%,100%), 
+       flipped: true), 
+  parbreak() }
diff --git a/test/out/layout/page-02.out b/test/out/layout/page-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-02.out
@@ -0,0 +1,112 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 80.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-02.typ"
+    ( line 5 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-02.typ"
+              ( line 5 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg (Identifier "width") (Literal (Numeric 40.0 Pt)) ])
+          , Text "High"
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/page-02.typ"
+    ( line 6 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-02.typ"
+              ( line 6 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg (Identifier "height") (Literal (Numeric 40.0 Pt)) ])
+          , Text "Wide"
+          ]))
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/page-02.typ"
+    ( line 9 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-02.typ"
+              ( line 9 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg (Identifier "paper") (Literal (String "a11"))
+                 , KeyValArg (Identifier "flipped") (Literal (Boolean True))
+                 ])
+          , Text "Flipped"
+          , Space
+          , Text "A11"
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [High]), 
+  text(body: [
+]), 
+  text(body: [Wide]), 
+  parbreak(), 
+  text(body: [Flipped A11]), 
+  parbreak() }
diff --git a/test/out/layout/page-03.out b/test/out/layout/page-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-03.out
@@ -0,0 +1,100 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/page-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 40.0 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 15.0 Pt))
+       , KeyValArg (Identifier "font") (Literal (String "Roboto"))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "white"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "smallcaps")) [ BlockArg [ Text "Typst" ] ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 40.0 Pt))
+       , KeyValArg (Identifier "fill") (Literal None)
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "top" , Literal (Numeric 10.0 Pt) )
+              , ( Identifier "rest" , Literal Auto )
+              ])
+       , BlockArg [ Text "Hi" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: smallcaps(body: text(body: [Typst])), 
+       fill: rgb(100%,100%,100%,100%), 
+       font: "Roboto", 
+       size: 15.0pt), 
+  text(body: [
+]), 
+  page(body: text(body: [Hi]), 
+       fill: none, 
+       height: 40.0pt, 
+       margin: (top: 10.0pt,
+                rest: auto), 
+       width: 40.0pt), 
+  parbreak() }
diff --git a/test/out/layout/page-04.out b/test/out/layout/page-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-04.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "page"))
+       [ NormalArg (Literal (String "a11"))
+       , KeyValArg (Identifier "flipped") (Literal (Boolean True))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , BlockArg []
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  page(body: [a11], 
+       fill: rgb(100%,25%,21%,100%), 
+       flipped: true), 
+  text(body: [
+]), 
+  pagebreak(), 
+  parbreak() }
diff --git a/test/out/layout/page-05.out b/test/out/layout/page-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-05.out
@@ -0,0 +1,121 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/layout/page-05.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt))
+       , NormalArg
+           (Block
+              (CodeBlock
+                 [ FuncCall
+                     (Ident (Identifier "layout"))
+                     [ NormalArg
+                         (FuncExpr
+                            [ NormalParam (Identifier "size") ]
+                            (Block
+                               (Content
+                                  [ Text "This"
+                                  , Space
+                                  , Text "page"
+                                  , Space
+                                  , Text "has"
+                                  , Space
+                                  , Text "a"
+                                  , Space
+                                  , Text "width"
+                                  , Space
+                                  , Text "of"
+                                  , Space
+                                  , Code
+                                      "test/typ/layout/page-05.typ"
+                                      ( line 5 , column 45 )
+                                      (FieldAccess
+                                         (Ident (Identifier "width")) (Ident (Identifier "size")))
+                                  , Space
+                                  , Text "and"
+                                  , Space
+                                  , Text "height"
+                                  , Space
+                                  , Text "of"
+                                  , Space
+                                  , Code
+                                      "test/typ/layout/page-05.typ"
+                                      ( line 5 , column 71 )
+                                      (FieldAccess
+                                         (Ident (Identifier "height")) (Ident (Identifier "size")))
+                                  , Space
+                                  ])))
+                     ]
+                 , FuncCall
+                     (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Em)) ]
+                 , FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg (Ident (Identifier "left"))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "rect"))
+                            [ KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt))
+                            , KeyValArg (Identifier "stroke") (Ident (Identifier "blue"))
+                            ])
+                     ]
+                 ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  page(body: { layout(func: ), 
+               h(amount: 1.0em), 
+               place(alignment: left, 
+                     body: rect(stroke: rgb(0%,45%,85%,100%), 
+                                width: 80.0pt)) }, 
+       height: 100.0pt, 
+       width: 100.0pt), 
+  parbreak() }
diff --git a/test/out/layout/page-margin-00.out b/test/out/layout/page-margin-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-margin-00.out
@@ -0,0 +1,95 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-margin-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-margin-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-margin-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/page-margin-00.typ"
+    ( line 3 , column 2 )
+    (Block
+       (Content
+          [ SoftBreak
+          , Code
+              "test/typ/layout/page-margin-00.typ"
+              ( line 4 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+                 , KeyValArg (Identifier "margin") (Literal (Numeric 5.0 Pt))
+                 ])
+          , SoftBreak
+          , Code
+              "test/typ/layout/page-margin-00.typ"
+              ( line 5 , column 4 )
+              (FuncCall
+                 (Ident (Identifier "place"))
+                 [ NormalArg
+                     (Plus (Ident (Identifier "top")) (Ident (Identifier "left")))
+                 , BlockArg [ Text "TL" ]
+                 ])
+          , SoftBreak
+          , Code
+              "test/typ/layout/page-margin-00.typ"
+              ( line 6 , column 4 )
+              (FuncCall
+                 (Ident (Identifier "place"))
+                 [ NormalArg
+                     (Plus (Ident (Identifier "bottom")) (Ident (Identifier "right")))
+                 , BlockArg [ Text "BR" ]
+                 ])
+          , ParBreak
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  place(alignment: Axes(left, top), 
+        body: text(body: [TL])), 
+  text(body: [
+]), 
+  place(alignment: Axes(right, bottom), 
+        body: text(body: [BR])), 
+  parbreak(), 
+  parbreak() }
diff --git a/test/out/layout/page-margin-01.out b/test/out/layout/page-margin-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-margin-01.out
@@ -0,0 +1,196 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-margin-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-margin-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-margin-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/page-margin-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 40.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-margin-01.typ"
+    ( line 4 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 4 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg
+                     (Identifier "margin")
+                     (Dict [ ( Identifier "left" , Literal (Numeric 0.0 Pt) ) ])
+                 ])
+          , Space
+          , Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 4 , column 36 )
+              (FuncCall
+                 (Ident (Identifier "align"))
+                 [ NormalArg (Ident (Identifier "left"))
+                 , BlockArg [ Text "Left" ]
+                 ])
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/page-margin-01.typ"
+    ( line 5 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 5 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg
+                     (Identifier "margin")
+                     (Dict [ ( Identifier "right" , Literal (Numeric 0.0 Pt) ) ])
+                 ])
+          , Space
+          , Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 5 , column 37 )
+              (FuncCall
+                 (Ident (Identifier "align"))
+                 [ NormalArg (Ident (Identifier "right"))
+                 , BlockArg [ Text "Right" ]
+                 ])
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/page-margin-01.typ"
+    ( line 6 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 6 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg
+                     (Identifier "margin")
+                     (Dict [ ( Identifier "top" , Literal (Numeric 0.0 Pt) ) ])
+                 ])
+          , Space
+          , Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 6 , column 35 )
+              (FuncCall
+                 (Ident (Identifier "align"))
+                 [ NormalArg (Ident (Identifier "top")) , BlockArg [ Text "Top" ] ])
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/page-margin-01.typ"
+    ( line 7 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 7 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg
+                     (Identifier "margin")
+                     (Dict [ ( Identifier "bottom" , Literal (Numeric 0.0 Pt) ) ])
+                 ])
+          , Space
+          , Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 7 , column 38 )
+              (FuncCall
+                 (Ident (Identifier "align"))
+                 [ NormalArg (Ident (Identifier "bottom"))
+                 , BlockArg [ Text "Bottom" ]
+                 ])
+          ]))
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/page-margin-01.typ"
+    ( line 10 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/page-margin-01.typ"
+              ( line 10 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg
+                     (Identifier "margin")
+                     (Dict
+                        [ ( Identifier "rest" , Literal (Numeric 0.0 Pt) )
+                        , ( Identifier "left" , Literal (Numeric 20.0 Pt) )
+                        ])
+                 ])
+          , Space
+          , Text "Overridden"
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  align(alignment: left, 
+        body: text(body: [Left])), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  align(alignment: right, 
+        body: text(body: [Right])), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  align(alignment: top, 
+        body: text(body: [Top])), 
+  text(body: [
+]), 
+  text(body: [ ]), 
+  align(alignment: bottom, 
+        body: text(body: [Bottom])), 
+  parbreak(), 
+  text(body: [ Overridden]), 
+  parbreak() }
diff --git a/test/out/layout/page-marginals-00.out b/test/out/layout/page-marginals-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-marginals-00.out
@@ -0,0 +1,372 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-marginals-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-marginals-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-marginals-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/page-marginals-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "paper") (Literal (String "a8"))
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "x" , Literal (Numeric 15.0 Pt) )
+              , ( Identifier "y" , Literal (Numeric 30.0 Pt) )
+              ])
+       , KeyValArg
+           (Identifier "header")
+           (Block
+              (CodeBlock
+                 [ FuncCall
+                     (Ident (Identifier "text"))
+                     [ NormalArg (Ident (Identifier "eastern"))
+                     , BlockArg [ Strong [ Text "Typst" ] ]
+                     ]
+                 , FuncCall
+                     (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ]
+                 , FuncCall
+                     (Ident (Identifier "text"))
+                     [ NormalArg (Literal (Numeric 0.8 Em))
+                     , BlockArg [ Emph [ Text "Chapter" , Space , Text "1" ] ]
+                     ]
+                 ]))
+       , KeyValArg
+           (Identifier "footer")
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "center"))
+              , BlockArg
+                  [ Text "~"
+                  , Space
+                  , Code
+                      "test/typ/layout/page-marginals-00.typ"
+                      ( line 10 , column 29 )
+                      (FuncCall
+                         (FieldAccess
+                            (Ident (Identifier "display"))
+                            (FuncCall
+                               (Ident (Identifier "counter"))
+                               [ NormalArg (Ident (Identifier "page")) ]))
+                         [])
+                  , Space
+                  , Text "~"
+                  ]
+              ])
+       , KeyValArg
+           (Identifier "background")
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "display"))
+                 (FuncCall
+                    (Ident (Identifier "counter"))
+                    [ NormalArg (Ident (Identifier "page")) ]))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "n") ]
+                     (If
+                        [ ( LessThanOrEqual (Ident (Identifier "n")) (Literal (Int 2))
+                          , Block
+                              (CodeBlock
+                                 [ FuncCall
+                                     (Ident (Identifier "place"))
+                                     [ NormalArg
+                                         (Plus
+                                            (Ident (Identifier "center"))
+                                            (Ident (Identifier "horizon")))
+                                     , NormalArg
+                                         (FuncCall
+                                            (Ident (Identifier "circle"))
+                                            [ KeyValArg
+                                                (Identifier "radius") (Literal (Numeric 1.0 Cm))
+                                            , KeyValArg
+                                                (Identifier "fill")
+                                                (FuncCall
+                                                   (Ident (Identifier "luma"))
+                                                   [ NormalArg (Literal (Numeric 90.0 Percent)) ])
+                                            ])
+                                     ]
+                                 ])
+                          )
+                        ]))
+              ])
+       ])
+, ParBreak
+, Text "But,"
+, Space
+, Text "soft!"
+, Space
+, Text "what"
+, Space
+, Text "light"
+, Space
+, Text "through"
+, Space
+, Text "yonder"
+, Space
+, Text "window"
+, Space
+, Text "breaks?"
+, Space
+, Text "It"
+, Space
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "east,"
+, Space
+, Text "and"
+, Space
+, Text "Juliet"
+, SoftBreak
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "sun"
+, Text "."
+, Space
+, Text "Arise,"
+, Space
+, Text "fair"
+, Space
+, Text "sun,"
+, Space
+, Text "and"
+, Space
+, Text "kill"
+, Space
+, Text "the"
+, Space
+, Text "envious"
+, Space
+, Text "moon,"
+, Space
+, Text "Who"
+, Space
+, Text "is"
+, Space
+, Text "already"
+, Space
+, Text "sick"
+, Space
+, Text "and"
+, SoftBreak
+, Text "pale"
+, Space
+, Text "with"
+, Space
+, Text "grief,"
+, Space
+, Text "That"
+, Space
+, Text "thou"
+, Space
+, Text "her"
+, Space
+, Text "maid"
+, Space
+, Text "art"
+, Space
+, Text "far"
+, Space
+, Text "more"
+, Space
+, Text "fair"
+, Space
+, Text "than"
+, Space
+, Text "she"
+, Text ":"
+, Space
+, Text "Be"
+, Space
+, Text "not"
+, Space
+, Text "her"
+, Space
+, Text "maid,"
+, SoftBreak
+, Text "since"
+, Space
+, Text "she"
+, Space
+, Text "is"
+, Space
+, Text "envious;"
+, Space
+, Text "Her"
+, Space
+, Text "vestal"
+, Space
+, Text "livery"
+, Space
+, Text "is"
+, Space
+, Text "but"
+, Space
+, Text "sick"
+, Space
+, Text "and"
+, Space
+, Text "green"
+, Space
+, Text "And"
+, Space
+, Text "none"
+, Space
+, Text "but"
+, Space
+, Text "fools"
+, SoftBreak
+, Text "do"
+, Space
+, Text "wear"
+, Space
+, Text "it;"
+, Space
+, Text "cast"
+, Space
+, Text "it"
+, Space
+, Text "off"
+, Text "."
+, Space
+, Text "It"
+, Space
+, Text "is"
+, Space
+, Text "my"
+, Space
+, Text "lady,"
+, Space
+, Text "O,"
+, Space
+, Text "it"
+, Space
+, Text "is"
+, Space
+, Text "my"
+, Space
+, Text "love!"
+, Space
+, Text "O,"
+, Space
+, Text "that"
+, Space
+, Text "she"
+, Space
+, Text "knew"
+, Space
+, Text "she"
+, SoftBreak
+, Text "were!"
+, Space
+, Text "She"
+, Space
+, Text "speaks"
+, Space
+, Text "yet"
+, Space
+, Text "she"
+, Space
+, Text "says"
+, Space
+, Text "nothing"
+, Text ":"
+, Space
+, Text "what"
+, Space
+, Text "of"
+, Space
+, Text "that?"
+, Space
+, Text "Her"
+, Space
+, Text "eye"
+, Space
+, Text "discourses;"
+, Space
+, Text "I"
+, Space
+, Text "will"
+, SoftBreak
+, Text "answer"
+, Space
+, Text "it"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/layout/page-marginals-00.typ"
+    ( line 24 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "header") (Literal None)
+       , KeyValArg (Identifier "height") (Literal Auto)
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "top" , Literal (Numeric 15.0 Pt) )
+              , ( Identifier "bottom" , Literal (Numeric 25.0 Pt) )
+              ])
+       ])
+, SoftBreak
+, Text "The"
+, Space
+, Text "END"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [But, soft! what light through yonder window breaks? It is the east, and Juliet
+is the sun. Arise, fair sun, and kill the envious moon, Who is already sick and
+pale with grief, That thou her maid art far more fair than she: Be not her maid,
+since she is envious; Her vestal livery is but sick and green And none but fools
+do wear it; cast it off. It is my lady, O, it is my love! O, that she knew she
+were! She speaks yet she says nothing: what of that? Her eye discourses; I will
+answer it.]), 
+  parbreak(), 
+  text(body: [
+The END.]), 
+  parbreak() }
diff --git a/test/out/layout/page-style-00.out b/test/out/layout/page-style-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-style-00.out
@@ -0,0 +1,58 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-style-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-style-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-style-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-style-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ NormalArg (Literal (String "a11"))
+       , KeyValArg (Identifier "flipped") (Literal (Boolean True))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/layout/page-style-01.out b/test/out/layout/page-style-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-style-01.out
@@ -0,0 +1,63 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-style-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-style-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-style-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-style-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-style-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  pagebreak(), 
+  parbreak() }
diff --git a/test/out/layout/page-style-02.out b/test/out/layout/page-style-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-style-02.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-style-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-style-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-style-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-style-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page")) [ NormalArg (Literal (String "a4")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-style-02.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "page")) [ NormalArg (Literal (String "a5")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-style-02.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Cm))
+       , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Cm))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/layout/page-style-03.out b/test/out/layout/page-style-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/page-style-03.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/page-style-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/page-style-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/page-style-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/page-style-03.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page")) [ NormalArg (Literal (String "a4")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-style-03.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "page")) [ NormalArg (Literal (String "a5")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-style-03.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ NormalArg (Literal (String "a11"))
+       , KeyValArg (Identifier "flipped") (Literal (Boolean True))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-style-03.typ"
+    ( line 7 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "Roboto"))
+       , NormalArg (Ident (Identifier "white"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/page-style-03.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "smallcaps")) [ BlockArg [ Text "Typst" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       color: rgb(100%,100%,100%,100%), 
+       font: "Roboto"), 
+  smallcaps(body: text(body: [Typst], 
+                       color: rgb(100%,100%,100%,100%), 
+                       font: "Roboto")), 
+  parbreak() }
diff --git a/test/out/layout/pagebreak-00.out b/test/out/layout/pagebreak-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pagebreak-00.out
@@ -0,0 +1,54 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pagebreak-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pagebreak-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pagebreak-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/pagebreak-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  pagebreak(), 
+  parbreak() }
diff --git a/test/out/layout/pagebreak-01.out b/test/out/layout/pagebreak-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pagebreak-01.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pagebreak-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pagebreak-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pagebreak-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/pagebreak-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 2.0 Cm))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  pagebreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  pagebreak(), 
+  parbreak() }
diff --git a/test/out/layout/pagebreak-02.out b/test/out/layout/pagebreak-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pagebreak-02.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pagebreak-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pagebreak-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pagebreak-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/pagebreak-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "aqua")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-02.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pagebreak"))
+       [ KeyValArg (Identifier "weak") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "First"
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-02.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pagebreak"))
+       [ KeyValArg (Identifier "weak") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "Second"
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-02.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pagebreak"))
+       [ KeyValArg (Identifier "weak") (Literal (Boolean True)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  pagebreak(weak: true), 
+  text(body: [
+First
+]), 
+  pagebreak(weak: true), 
+  text(body: [
+Second
+]), 
+  pagebreak(weak: true), 
+  parbreak() }
diff --git a/test/out/layout/pagebreak-03.out b/test/out/layout/pagebreak-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pagebreak-03.out
@@ -0,0 +1,126 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pagebreak-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pagebreak-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pagebreak-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/pagebreak-03.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 30.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-03.typ"
+    ( line 5 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/pagebreak-03.typ"
+              ( line 5 , column 4 )
+              (Set
+                 (Ident (Identifier "page"))
+                 [ KeyValArg (Identifier "width") (Literal (Numeric 60.0 Pt)) ])
+          , Space
+          , Text "First"
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-03.typ"
+    ( line 7 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, SoftBreak
+, Text "Third"
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-03.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , BlockArg []
+       ])
+, SoftBreak
+, Text "Fif"
+, Code
+    "test/typ/layout/pagebreak-03.typ"
+    ( line 10 , column 5 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/layout/pagebreak-03.typ"
+              ( line 10 , column 7 )
+              (Set (Ident (Identifier "page")) [])
+          , Text "th"
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [ First]), 
+  text(body: [
+]), 
+  pagebreak(), 
+  text(body: [
+]), 
+  pagebreak(), 
+  text(body: [
+Third
+]), 
+  page(body: {  }, 
+       fill: rgb(100%,25%,21%,100%), 
+       height: 20.0pt, 
+       width: 60.0pt), 
+  text(body: [
+Fif]), 
+  text(body: [th]), 
+  parbreak() }
diff --git a/test/out/layout/pagebreak-04.out b/test/out/layout/pagebreak-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/pagebreak-04.out
@@ -0,0 +1,111 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/pagebreak-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/pagebreak-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/pagebreak-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/pagebreak-04.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "navy")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-04.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "white")) ])
+, SoftBreak
+, Text "First"
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-04.typ"
+    ( line 7 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-04.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "page")) [ BlockArg [ Text "Second" ] ])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-04.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "pagebreak"))
+       [ KeyValArg (Identifier "weak") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/pagebreak-04.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "page")) [ BlockArg [ Text "Third" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+First
+], 
+       fill: rgb(100%,100%,100%,100%)), 
+  pagebreak(), 
+  text(body: [
+], 
+       fill: rgb(100%,100%,100%,100%)), 
+  page(body: text(body: [Second], 
+                  fill: rgb(100%,100%,100%,100%)), 
+       fill: rgb(0%,12%,24%,100%)), 
+  text(body: [
+], 
+       fill: rgb(100%,100%,100%,100%)), 
+  pagebreak(weak: true), 
+  text(body: [
+], 
+       fill: rgb(100%,100%,100%,100%)), 
+  page(body: text(body: [Third], 
+                  fill: rgb(100%,100%,100%,100%)), 
+       fill: rgb(0%,12%,24%,100%)), 
+  parbreak() }
diff --git a/test/out/layout/par-00.out b/test/out/layout/par-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-00.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "right")) ])
+, SoftBreak
+, Text "To"
+, Space
+, Text "the"
+, Space
+, Text "right!"
+, Space
+, Text "Where"
+, Space
+, Text "the"
+, Space
+, Text "sunlight"
+, Space
+, Text "peeks"
+, Space
+, Text "behind"
+, Space
+, Text "the"
+, Space
+, Text "mountain"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+To the right! Where the sunlight peeks behind the mountain.]), 
+  parbreak() }
diff --git a/test/out/layout/par-01.out b/test/out/layout/par-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-01.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Em)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "leading") (Literal (Numeric 2.0 Pt)) ])
+, SoftBreak
+, Text "But,"
+, Space
+, Text "soft!"
+, Space
+, Text "what"
+, Space
+, Text "light"
+, Space
+, Text "through"
+, Space
+, Text "yonder"
+, Space
+, Text "window"
+, Space
+, Text "breaks?"
+, ParBreak
+, Text "It"
+, Space
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "east,"
+, Space
+, Text "and"
+, Space
+, Text "Juliet"
+, Space
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "sun"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+But, soft! what light through yonder window breaks?]), 
+  parbreak(), 
+  text(body: [It is the east, and Juliet is the sun.]), 
+  parbreak() }
diff --git a/test/out/layout/par-02.out b/test/out/layout/par-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-02.out
@@ -0,0 +1,105 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/par-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 100.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-02.typ"
+    ( line 5 , column 2 )
+    (Show
+       (Just (Ident (Identifier "table")))
+       (Set
+          (Ident (Identifier "block"))
+          [ KeyValArg (Identifier "above") (Literal (Numeric 5.0 Pt))
+          , KeyValArg (Identifier "below") (Literal (Numeric 5.0 Pt))
+          ]))
+, SoftBreak
+, Text "Hello"
+, SoftBreak
+, Code
+    "test/typ/layout/par-02.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 4))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncExpr
+              [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+              (If
+                 [ ( FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "odd")) (Ident (Identifier "calc")))
+                       [ NormalArg
+                           (Plus (Ident (Identifier "x")) (Ident (Identifier "y")))
+                       ]
+                   , Block (CodeBlock [ Ident (Identifier "silver") ])
+                   )
+                 ]))
+       , BlockArg [ Text "A" ]
+       , BlockArg [ Text "B" ]
+       , BlockArg [ Text "C" ]
+       , BlockArg [ Text "D" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+Hello
+]), 
+  table(children: (text(body: [A]), 
+                   text(body: [B]), 
+                   text(body: [C]), 
+                   text(body: [D])), 
+        columns: 4, 
+        fill: ), 
+  parbreak() }
diff --git a/test/out/layout/par-03.out b/test/out/layout/par-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-03.out
@@ -0,0 +1,90 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 0.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-03.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "raw")))
+       (Set
+          (Ident (Identifier "block"))
+          [ KeyValArg (Identifier "spacing") (Literal (Numeric 15.0 Pt)) ]))
+, SoftBreak
+, Code
+    "test/typ/layout/par-03.typ"
+    ( line 5 , column 2 )
+    (Show
+       (Just (Ident (Identifier "list")))
+       (Set
+          (Ident (Identifier "block"))
+          [ KeyValArg (Identifier "spacing") (Literal (Numeric 2.5 Pt)) ]))
+, ParBreak
+, RawBlock "rust" "fn main() {}\n"
+, ParBreak
+, BulletListItem [ Text "List" , SoftBreak ]
+, SoftBreak
+, Text "Paragraph"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  raw(block: true, 
+      lang: "rust", 
+      text: "fn main() {}\n"), 
+  parbreak(), 
+  list(children: (text(body: [List
+]))), 
+  text(body: [Paragraph]), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-00.out b/test/out/layout/par-bidi-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-00.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-bidi-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "content")))
+       (FuncCall
+          (Ident (Identifier "par"))
+          [ BlockArg
+              [ Text "Text" , Space , Text "\1496\1462\1511\1505\1496" ]
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "he"))
+       , NormalArg (Ident (Identifier "content"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "de"))
+       , NormalArg (Ident (Identifier "content"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: par(body: text(body: [Text טֶקסט])), 
+       lang: "he"), 
+  text(body: [
+]), 
+  text(body: par(body: text(body: [Text טֶקסט])), 
+       lang: "de"), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-01.out b/test/out/layout/par-bidi-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-01.out
@@ -0,0 +1,120 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/par-bidi-01.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "content")))
+       (FuncCall
+          (Ident (Identifier "par"))
+          [ BlockArg
+              [ Text "\1571\1606\1578"
+              , Space
+              , Text "A"
+              , Code
+                  "test/typ/layout/par-bidi-01.typ"
+                  ( line 4 , column 26 )
+                  (FuncCall (Ident (Identifier "emph")) [ BlockArg [ Text "B" ] ])
+              , Text "\1605\1591\1585C"
+              ]
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "PT Sans")
+              , Literal (String "Noto Sans Arabic")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ar"))
+       , NormalArg (Ident (Identifier "content"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "de"))
+       , NormalArg (Ident (Identifier "content"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       font: ("PT Sans", 
+              "Noto Sans Arabic")), 
+  text(body: par(body: { text(body: [أنت A]), 
+                         emph(body: text(body: [B])), 
+                         text(body: [مطرC]) }), 
+       font: ("PT Sans", 
+              "Noto Sans Arabic"), 
+       lang: "ar"), 
+  text(body: [
+], 
+       font: ("PT Sans", 
+              "Noto Sans Arabic")), 
+  text(body: par(body: { text(body: [أنت A]), 
+                         emph(body: text(body: [B])), 
+                         text(body: [مطرC]) }), 
+       font: ("PT Sans", 
+              "Noto Sans Arabic"), 
+       lang: "de"), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-02.out b/test/out/layout/par-bidi-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-02.out
@@ -0,0 +1,120 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/par-bidi-02.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "content")))
+       (FuncCall
+          (Ident (Identifier "par"))
+          [ BlockArg
+              [ Text "A\1490\1462"
+              , Code
+                  "test/typ/layout/par-bidi-02.typ"
+                  ( line 4 , column 24 )
+                  (FuncCall
+                     (Ident (Identifier "strong"))
+                     [ BlockArg [ Text "\1513\1473\1462" ] ])
+              , Text "\1501B"
+              ]
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-02.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "Linux Libertine")
+              , Literal (String "Noto Serif Hebrew")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-02.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "he"))
+       , NormalArg (Ident (Identifier "content"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-bidi-02.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "de"))
+       , NormalArg (Ident (Identifier "content"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       font: ("Linux Libertine", 
+              "Noto Serif Hebrew")), 
+  text(body: par(body: { text(body: [Aגֶ]), 
+                         strong(body: text(body: [שֶׁ])), 
+                         text(body: [םB]) }), 
+       font: ("Linux Libertine", 
+              "Noto Serif Hebrew"), 
+       lang: "he"), 
+  text(body: [
+], 
+       font: ("Linux Libertine", 
+              "Noto Serif Hebrew")), 
+  text(body: par(body: { text(body: [Aגֶ]), 
+                         strong(body: text(body: [שֶׁ])), 
+                         text(body: [םB]) }), 
+       font: ("Linux Libertine", 
+              "Noto Serif Hebrew"), 
+       lang: "de"), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-03.out b/test/out/layout/par-bidi-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-03.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-bidi-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl")) ])
+, SoftBreak
+, Text "\1488"
+, Text "\8294"
+, Text "A"
+, Text "\8295"
+, Text "B\1489"
+, Text "\8297"
+, Text "?"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+א⁦A⁧Bב⁩?], 
+       dir: rtl), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-04.out b/test/out/layout/par-bidi-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-04.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-bidi-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ar"))
+       , KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "Noto Sans Arabic")
+              , Literal (String "PT Sans")
+              ])
+       ])
+, SoftBreak
+, Text "Life"
+, Space
+, Text "\1575\1604\1605\1591\1585"
+, Space
+, Text "\1607\1608"
+, Space
+, Text "\1575\1604\1581\1610\1575\1577"
+, Space
+, HardBreak
+, Text "\1575\1604\1581\1610\1575\1577"
+, Space
+, Text "\1578\1605\1591\1585"
+, Space
+, Text "is"
+, Space
+, Text "rain"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Life المطر هو الحياة ], 
+       font: ("Noto Sans Arabic", 
+              "PT Sans"), 
+       lang: "ar"), 
+  linebreak(), 
+  text(body: [الحياة تمطر is rain.], 
+       font: ("Noto Sans Arabic", 
+              "PT Sans"), 
+       lang: "ar"), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-05.out b/test/out/layout/par-bidi-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-05.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "L"
+, Space
+, Code
+    "test/typ/layout/par-bidi-05.typ"
+    ( line 3 , column 4 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Cm)) ])
+, Space
+, Text "\1512\1497\1493\1493\1495R"
+, Space
+, HardBreak
+, Text "L\1512\1497\1493\1493\1495"
+, Space
+, Code
+    "test/typ/layout/par-bidi-05.typ"
+    ( line 4 , column 9 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Cm)) ])
+, Space
+, Text "R"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [L ]), 
+  h(amount: 1.0cm), 
+  text(body: [ ריווחR ]), 
+  linebreak(), 
+  text(body: [Lריווח ]), 
+  h(amount: 1.0cm), 
+  text(body: [ R]), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-06.out b/test/out/layout/par-bidi-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-06.out
@@ -0,0 +1,76 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-bidi-06.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "he")) ])
+, SoftBreak
+, Text "\1511\1512\1504\1508\1497\1501Rh"
+, Code
+    "test/typ/layout/par-bidi-06.typ"
+    ( line 4 , column 10 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/rhino.png"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 11.0 Pt))
+              ])
+       ])
+, Text "ino\1495\1497\1497\1501"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+קרנפיםRh], 
+       lang: "he"), 
+  box(body: image(height: 11.0pt, 
+                  path: "test/assets/files/rhino.png")), 
+  text(body: [inoחיים], 
+       lang: "he"), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-07.out b/test/out/layout/par-bidi-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-07.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-bidi-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-bidi-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-bidi-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "\1575\1604\1594\1575\1604\1576"
+, Space
+, Code
+    "test/typ/layout/par-bidi-07.typ"
+    ( line 3 , column 9 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 70.0 Pt)) ])
+, Space
+, Text "\1606"
+, Code
+    "test/typ/layout/par-bidi-07.typ"
+    ( line 3 , column 19 )
+    (Literal (String " "))
+, Text "\1577"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [الغالب ]), 
+  h(amount: 70.0pt), 
+  text(body: [ ن]), 
+  text(body: [ ]), 
+  text(body: [ة]), 
+  parbreak() }
diff --git a/test/out/layout/par-bidi-08.out b/test/out/layout/par-bidi-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-bidi-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/par-indent-00.out b/test/out/layout/par-indent-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-indent-00.out
@@ -0,0 +1,265 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-indent-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-indent-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg
+           (Identifier "first-line-indent") (Literal (Numeric 12.0 Pt))
+       , KeyValArg (Identifier "leading") (Literal (Numeric 5.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 5.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (Set
+          (Ident (Identifier "text"))
+          [ KeyValArg (Identifier "size") (Literal (Numeric 10.0 Pt)) ]))
+, ParBreak
+, Text "The"
+, Space
+, Text "first"
+, Space
+, Text "paragraph"
+, Space
+, Text "has"
+, Space
+, Text "no"
+, Space
+, Text "indent"
+, Text "."
+, ParBreak
+, Text "But"
+, Space
+, Text "the"
+, Space
+, Text "second"
+, Space
+, Text "one"
+, Space
+, Text "does"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 6.0 Pt))
+              ])
+       ])
+, SoftBreak
+, Text "starts"
+, Space
+, Text "a"
+, Space
+, Text "paragraph,"
+, Space
+, Text "also"
+, Space
+, Text "with"
+, Space
+, Text "indent"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/rhino.png"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 1.0 Cm))
+              ])
+       ])
+, ParBreak
+, Heading 1 [ Text "Headings" ]
+, BulletListItem [ Text "And" , Space , Text "lists" , Text "." ]
+, SoftBreak
+, BulletListItem
+    [ Text "Have"
+    , Space
+    , Text "no"
+    , Space
+    , Text "indent"
+    , Text "."
+    , ParBreak
+    , Text "Except"
+    , Space
+    , Text "if"
+    , Space
+    , Text "you"
+    , Space
+    , Text "have"
+    , Space
+    , Text "another"
+    , Space
+    , Text "paragraph"
+    , Space
+    , Text "in"
+    , Space
+    , Text "them"
+    , Text "."
+    , SoftBreak
+    ]
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 21 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 8.0 Pt))
+       , KeyValArg (Identifier "lang") (Literal (String "ar"))
+       , KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "Noto Sans Arabic")
+              , Literal (String "Linux Libertine")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-00.typ"
+    ( line 22 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "leading") (Literal (Numeric 8.0 Pt)) ])
+, ParBreak
+, Heading 1 [ Text "Arabic" ]
+, Text "\1583\1593"
+, Space
+, Text "\1575\1604\1606\1589"
+, Space
+, Text "\1610\1605\1591\1585"
+, Space
+, Text "\1593\1604\1610\1603"
+, ParBreak
+, Text "\1579\1605"
+, Space
+, Text "\1610\1589\1576\1581"
+, Space
+, Text "\1575\1604\1606\1589"
+, Space
+, Text "\1585\1591\1576\1611\1575"
+, Space
+, Text "\1608\1602\1575\1576\1604"
+, Space
+, Text "\1604\1604\1591\1585\1602"
+, Space
+, Text "\1608\1610\1576\1583\1608"
+, Space
+, Text "\1575\1604\1605\1587\1578\1606\1583"
+, Space
+, Text "\1585\1575\1574\1593\1611\1575"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [The first paragraph has no indent.]), 
+  parbreak(), 
+  text(body: [But the second one does.]), 
+  parbreak(), 
+  box(body: image(height: 6.0pt, 
+                  path: "test/assets/files/tiger.jpg")), 
+  text(body: [
+starts a paragraph, also with indent.]), 
+  parbreak(), 
+  align(alignment: center, 
+        body: image(path: "test/assets/files/rhino.png", 
+                    width: 1.0cm)), 
+  parbreak(), 
+  heading(body: text(body: [Headings]), 
+          level: 1), 
+  list(children: (text(body: [And lists.]), 
+                  { text(body: [Have no indent.]), 
+                    parbreak(), 
+                    text(body: [Except if you have another paragraph in them.
+]) })), 
+  text(body: [
+], 
+       font: ("Noto Sans Arabic", 
+              "Linux Libertine"), 
+       lang: "ar", 
+       size: 8.0pt), 
+  parbreak(), 
+  heading(body: text(body: [Arabic], 
+                     font: ("Noto Sans Arabic", 
+                            "Linux Libertine"), 
+                     lang: "ar", 
+                     size: 8.0pt), 
+          level: 1), 
+  text(body: [دع النص يمطر عليك], 
+       font: ("Noto Sans Arabic", 
+              "Linux Libertine"), 
+       lang: "ar", 
+       size: 8.0pt), 
+  parbreak(), 
+  text(body: [ثم يصبح النص رطبًا وقابل للطرق ويبدو المستند رائعًا.], 
+       font: ("Noto Sans Arabic", 
+              "Linux Libertine"), 
+       lang: "ar", 
+       size: 8.0pt), 
+  parbreak() }
diff --git a/test/out/layout/par-indent-01.out b/test/out/layout/par-indent-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-indent-01.out
@@ -0,0 +1,80 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-indent-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-indent-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-indent-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-indent-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg
+           (Identifier "first-line-indent") (Literal (Numeric 12.0 Pt))
+       ])
+, SoftBreak
+, Text "Why"
+, Space
+, Text "would"
+, Space
+, Text "anybody"
+, Space
+, Text "ever"
+, Space
+, Ellipsis
+, ParBreak
+, Ellipsis
+, Space
+, Text "want"
+, Space
+, Text "spacing"
+, Space
+, Text "and"
+, Space
+, Text "indent?"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Why would anybody ever …]), 
+  parbreak(), 
+  text(body: [… want spacing and indent?]), 
+  parbreak() }
diff --git a/test/out/layout/par-indent-02.out b/test/out/layout/par-indent-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-indent-02.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-indent-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-indent-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-indent-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-indent-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg
+           (Identifier "hanging-indent") (Literal (Numeric 15.0 Pt))
+       , KeyValArg (Identifier "justify") (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 10)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do]), 
+  parbreak() }
diff --git a/test/out/layout/par-indent-03.out b/test/out/layout/par-indent-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-indent-03.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-indent-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-indent-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-indent-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-03.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg
+           (Identifier "hanging-indent") (Literal (Numeric 1.0 Em))
+       ])
+, SoftBreak
+, Text "Welcome"
+, Space
+, HardBreak
+, Text "here"
+, Text "."
+, Space
+, Text "Does"
+, Space
+, Text "this"
+, Space
+, Text "work"
+, Space
+, Text "well?"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Welcome ]), 
+  linebreak(), 
+  text(body: [here. Does this work well?]), 
+  parbreak() }
diff --git a/test/out/layout/par-indent-04.out b/test/out/layout/par-indent-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-indent-04.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-indent-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-indent-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-indent-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-04.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg
+           (Identifier "hanging-indent") (Literal (Numeric 2.0 Em))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-indent-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl")) ])
+, SoftBreak
+, Text "\1604\1570\1606"
+, Space
+, Text "\1608\1602\1583"
+, Space
+, Text "\1571\1592\1604\1605"
+, Space
+, Text "\1575\1604\1604\1610\1604"
+, Space
+, Text "\1608\1576\1583\1571\1578"
+, Space
+, Text "\1575\1604\1606\1580\1608\1605"
+, SoftBreak
+, Text "\1578\1606\1590\1582"
+, Space
+, Text "\1608\1580\1607"
+, Space
+, Text "\1575\1604\1591\1576\1610\1593\1577"
+, Space
+, Text "\1575\1604\1578\1610"
+, Space
+, Text "\1571\1593\1618\1610\1614\1578\1618"
+, Space
+, Text "\1605\1606"
+, Space
+, Text "\1591\1608\1604"
+, Space
+, Text "\1605\1575"
+, Space
+, Text "\1575\1606\1576\1593\1579\1578"
+, Space
+, Text "\1601\1610"
+, Space
+, Text "\1575\1604\1606\1607\1575\1585"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+لآن وقد أظلم الليل وبدأت النجوم
+تنضخ وجه الطبيعة التي أعْيَتْ من طول ما انبعثت في النهار], 
+       dir: rtl), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-00.out b/test/out/layout/par-justify-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-00.out
@@ -0,0 +1,148 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 5.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True))
+       , KeyValArg
+           (Identifier "first-line-indent") (Literal (Numeric 14.0 Pt))
+       , KeyValArg (Identifier "leading") (Literal (Numeric 5.0 Pt))
+       ])
+, ParBreak
+, Text "This"
+, Space
+, Text "text"
+, Space
+, Text "is"
+, Space
+, Text "justified,"
+, Space
+, Text "meaning"
+, Space
+, Text "that"
+, Space
+, Text "spaces"
+, Space
+, Text "are"
+, Space
+, Text "stretched"
+, Space
+, Text "so"
+, Space
+, Text "that"
+, Space
+, Text "the"
+, Space
+, Text "text"
+, SoftBreak
+, Text "forms"
+, Space
+, Text "a"
+, Space
+, Quote '"'
+, Text "block"
+, Quote '"'
+, Space
+, Text "with"
+, Space
+, Text "flush"
+, Space
+, Text "edges"
+, Space
+, Text "at"
+, Space
+, Text "both"
+, Space
+, Text "sides"
+, Text "."
+, ParBreak
+, Text "First"
+, Space
+, Text "line"
+, Space
+, Text "indents"
+, Space
+, Text "and"
+, Space
+, Text "hyphenation"
+, Space
+, Text "play"
+, Space
+, Text "nicely"
+, Space
+, Text "with"
+, Space
+, Text "justified"
+, Space
+, Text "text"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [This text is justified, meaning that spaces are stretched so that the text
+forms a “block” with flush edges at both sides.]), 
+  parbreak(), 
+  text(body: [First line indents and hyphenation play nicely with justified text.]), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-01.out b/test/out/layout/par-justify-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-01.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-justify-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "A"
+, Space
+, Text "B"
+, Space
+, Text "C"
+, Space
+, HardBreak
+, Text "D"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+A B C ]), 
+  linebreak(), 
+  text(body: [D]), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-02.out b/test/out/layout/par-justify-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-02.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Space
+, Text "B"
+, Space
+, Text "C"
+, Space
+, Code
+    "test/typ/layout/par-justify-02.typ"
+    ( line 3 , column 8 )
+    (FuncCall
+       (Ident (Identifier "linebreak"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "D"
+, Space
+, Text "E"
+, Space
+, Text "F"
+, Space
+, Code
+    "test/typ/layout/par-justify-02.typ"
+    ( line 4 , column 8 )
+    (FuncCall
+       (Ident (Identifier "linebreak"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A B C ]), 
+  linebreak(justify: true), 
+  text(body: [
+D E F ]), 
+  linebreak(justify: true), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-03.out b/test/out/layout/par-justify-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-03.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/layout/par-justify-03.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-03.typ"
+    ( line 5 , column 2 )
+    (Literal (String ""))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-04.out b/test/out/layout/par-justify-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-04.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-justify-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 155.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-04.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "This"
+, Space
+, Text "text"
+, Space
+, Text "can"
+, Space
+, Text "be"
+, Space
+, Text "fitted"
+, Space
+, Text "in"
+, Space
+, Text "one"
+, Space
+, Text "line"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+This text can be fitted in one line.]), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-cjk-00.out b/test/out/layout/par-justify-cjk-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-cjk-00.out
@@ -0,0 +1,117 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-cjk-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/layout/par-justify-cjk-00.typ"
+    ( line 7 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-00.typ"
+    ( line 8 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-00.typ"
+    ( line 9 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "Noto Serif CJK SC"))
+       , KeyValArg (Identifier "lang") (Literal (String "zh"))
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/par-justify-cjk-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb")) [ NormalArg (Literal (String "eee")) ])
+       , BlockArg
+           [ SoftBreak
+           , Text
+               "\20013\25991\32500\22522\30334\31185\20351\29992\27721\23383\20070\20889\65292\27721\23383\26159\27721\26063\25110\21326\20154\30340\20849\21516\25991\23383\65292\26159\20013\22269\22823\38470\12289\26032\21152\22369\12289\39532\26469\35199\20122\12289\21488\28286\12289\39321\28207\12289\28595\38376\30340\21807\19968\23448\26041\25991\23383\25110\23448\26041\25991\23383\20043\19968\12290\&25"
+           , Text "."
+           , Text
+               "9%\65292\32780\32654\22269\21644\33655\20848\21017\20998\21029\21344\&13"
+           , Text "."
+           , Text "7%\21450\&8"
+           , Text "."
+           , Text
+               "2%\12290\36817\24180\20358\65292\20013\22269\22823\38470\22320\21306\30340\32500\22522\30334\31185\32534\36753\32773\27491\22312\36805\36895\22686\21152\65307"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  rect(body: { text(body: [
+中文维基百科使用汉字书写，汉字是汉族或华人的共同文字，是中国大陆、新加坡、马来西亚、台湾、香港、澳门的唯一官方文字或官方文字之一。25.9%，而美国和荷兰则分別占13.7%及8.2%。近年來，中国大陆地区的维基百科编辑者正在迅速增加；], 
+                    font: "Noto Serif CJK SC", 
+                    lang: "zh"), 
+               parbreak() }, 
+       fill: rgb(5%,5%,5%,100%), 
+       inset: 0.0pt, 
+       width: 80.0pt), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-cjk-01.out b/test/out/layout/par-justify-cjk-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-cjk-01.out
@@ -0,0 +1,121 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-cjk-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-justify-cjk-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "jp")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb")) [ NormalArg (Literal (String "eee")) ])
+       , BlockArg
+           [ SoftBreak
+           , Text "\12454\12451\12461\12506\12487\12451\12450\65288\33521"
+           , Text ":"
+           , Space
+           , Text
+               "Wikipedia\65289\12399\12289\19990\30028\20013\12398\12508\12521\12531\12486\12451\12450\12398\20849\21516\20316\26989\12395\12424\12387\12390\22519\31558\21450\12403\20316\25104\12373\12428\12427\12501\12522\12540\12398\22810\35328\35486\12452\12531\12479\12540\12493\12483\12488\30334\31185\20107\20856\12391\12354\12427\12290\20027\12395\23492\20184\12395\20381\12387\12390\27963\21205\12375\12390\12356\12427\38750\21942\21033\22243\20307\12300\12454\12451\12461\12513\12487\12451\12450\36001\22243\12301\12364\25152\26377\12539\36939\21942\12375\12390\12356\12427\12290"
+           , ParBreak
+           , Text
+               "\23554\38272\23478\12395\12424\12427\12458\12531\12521\12452\12531\30334\31185\20107\20856\12503\12525\12472\12455\12463\12488Nupedia\65288\12492\12540\12506\12487\12451\12450\65289\12434\21069\36523\12392\12375\12390\12289\&2001\24180\&1\26376\12289\12521\12522\12540\12539\12469\12531\12460\12540\12392\12472\12511\12540\12539\12454\12455\12540\12523\12474\65288\33521"
+           , Text ":"
+           , Space
+           , Text "Jimmy"
+           , Space
+           , Text "Donal"
+           , Space
+           , Quote '"'
+           , Text "Jimbo"
+           , Quote '"'
+           , Space
+           , Text
+               "Wales\65289\12395\12424\12426\33521\35486\12391\12503\12525\12472\12455\12463\12488\12364\38283\22987\12373\12428\12383\12290"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], lang: "jp"), 
+  rect(body: { text(body: [
+ウィキペディア（英: Wikipedia）は、世界中のボランティアの共同作業によって執筆及び作成されるフリーの多言語インターネット百科事典である。主に寄付に依って活動している非営利団体「ウィキメディア財団」が所有・運営している。], 
+                    lang: "jp"), 
+               parbreak(), 
+               text(body: [専門家によるオンライン百科事典プロジェクトNupedia（ヌーペディア）を前身として、2001年1月、ラリー・サンガーとジミー・ウェールズ（英: Jimmy Donal “Jimbo” Wales）により英語でプロジェクトが開始された。], 
+                    lang: "jp"), 
+               parbreak() }, 
+       fill: rgb(5%,5%,5%,100%), 
+       inset: 0.0pt, 
+       width: 80.0pt), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-cjk-02.out b/test/out/layout/par-justify-cjk-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-cjk-02.out
@@ -0,0 +1,120 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-cjk-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-justify-cjk-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "zh"))
+       , KeyValArg
+           (Identifier "font") (Literal (String "Noto Serif CJK SC"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-02.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-02.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb")) [ NormalArg (Literal (String "eee")) ])
+       , BlockArg
+           [ SoftBreak
+           , Text "\8220\24341\21495\27979\35797\8221\65292\36824\65292"
+           , ParBreak
+           , Text
+               "\12298\20070\21517\12299\12298\27979\35797\12299\19979\19968\34892"
+           , ParBreak
+           , Text "\12298\20070\21517\12299\12298\27979\35797\12299\12290"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       font: "Noto Serif CJK SC", 
+       lang: "zh"), 
+  text(body: [
+], 
+       font: "Noto Serif CJK SC", 
+       lang: "zh"), 
+  rect(body: { text(body: [
+“引号测试”，还，], 
+                    font: "Noto Serif CJK SC", 
+                    lang: "zh"), 
+               parbreak(), 
+               text(body: [《书名》《测试》下一行], 
+                    font: "Noto Serif CJK SC", 
+                    lang: "zh"), 
+               parbreak(), 
+               text(body: [《书名》《测试》。], 
+                    font: "Noto Serif CJK SC", 
+                    lang: "zh"), 
+               parbreak() }, 
+       fill: rgb(5%,5%,5%,100%), 
+       inset: 0.0pt, 
+       width: 80.0pt), 
+  parbreak() }
diff --git a/test/out/layout/par-justify-cjk-03.out b/test/out/layout/par-justify-cjk-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-justify-cjk-03.out
@@ -0,0 +1,117 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-justify-cjk-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-justify-cjk-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/par-justify-cjk-03.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg
+           (Identifier "width")
+           (Plus (Literal (Numeric 170.0 Pt)) (Literal (Numeric 10.0 Pt)))
+       , KeyValArg
+           (Identifier "margin")
+           (Dict [ ( Identifier "x" , Literal (Numeric 5.0 Pt) ) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-03.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "Noto Serif CJK SC"))
+       , KeyValArg (Identifier "lang") (Literal (String "zh"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-justify-cjk-03.typ"
+    ( line 7 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, ParBreak
+, Text
+    "\23380\38592\26368\26089\35265\20110\12298\23665\28023\32463\12299\20013\30340\12298\28023\20869\32463\12299\65306"
+, Text "\8203"
+, Text
+    "\8220\26377\23380\38592\12290\8221\19996\27721\26472\23386\33879\12298\24322\29289\24535\12299\35760\36733\65292\23725\21335\65306\8220\23380\38592\65292\20854\22823\22914\22823\38593\32780\36275\39640\65292\27611\30342\26377\26001\32441\24425\65292\25429\32780\33988\20043\65292\25293\25163\21363\33310\12290\8221"
+, ParBreak
+, Code
+    "test/typ/layout/par-justify-cjk-03.typ"
+    ( line 11 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "Noto Serif CJK TC"))
+       , KeyValArg (Identifier "lang") (Literal (String "zh"))
+       , KeyValArg (Identifier "region") (Literal (String "hk"))
+       ])
+, SoftBreak
+, Text
+    "\23380\38592\26368\26089\35265\20110\12298\23665\28023\32463\12299\20013\30340\12298\28023\20869\32463\12299\65306\12300\26377\23380\38592\12290\12301\19996\27721\26472\23386\33879\12298\24322\29289\24535\12299\35760\36733\65292\23725\21335\65306\12300\23380\38592\65292\20854\22823\22914\22823\38593\32780\36275\39640\65292\27611\30342\26377\26001\32441\24425\65292\25429\32780\33988\20043\65292\25293\25163\21363\33310\12290\12301"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       font: "Noto Serif CJK SC", 
+       lang: "zh"), 
+  parbreak(), 
+  text(body: [孔雀最早见于《山海经》中的《海内经》：​“有孔雀。”东汉杨孚著《异物志》记载，岭南：“孔雀，其大如大雁而足高，毛皆有斑纹彩，捕而蓄之，拍手即舞。”], 
+       font: "Noto Serif CJK SC", 
+       lang: "zh"), 
+  parbreak(), 
+  text(body: [
+孔雀最早见于《山海经》中的《海内经》：「有孔雀。」东汉杨孚著《异物志》记载，岭南：「孔雀，其大如大雁而足高，毛皆有斑纹彩，捕而蓄之，拍手即舞。」], 
+       font: "Noto Serif CJK TC", 
+       lang: "zh", 
+       region: "hk"), 
+  parbreak() }
diff --git a/test/out/layout/par-knuth-00.out b/test/out/layout/par-knuth-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-knuth-00.out
@@ -0,0 +1,518 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-knuth-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-knuth-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-knuth-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/par-knuth-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto)
+       , KeyValArg (Identifier "height") (Literal Auto)
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-knuth-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "leading") (Literal (Numeric 4.0 Pt))
+       , KeyValArg (Identifier "justify") (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/par-knuth-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "New Computer Modern"))
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/par-knuth-00.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "story")))
+       (Block
+          (Content
+             [ SoftBreak
+             , Text "In"
+             , Space
+             , Text "olden"
+             , Space
+             , Text "times"
+             , Space
+             , Text "when"
+             , Space
+             , Text "wishing"
+             , Space
+             , Text "still"
+             , Space
+             , Text "helped"
+             , Space
+             , Text "one,"
+             , Space
+             , Text "there"
+             , Space
+             , Text "lived"
+             , Space
+             , Text "a"
+             , Space
+             , Text "king"
+             , Space
+             , Text "whose"
+             , SoftBreak
+             , Text "daughters"
+             , Space
+             , Text "were"
+             , Space
+             , Text "all"
+             , Space
+             , Text "beautiful;"
+             , Space
+             , Text "and"
+             , Space
+             , Text "the"
+             , Space
+             , Text "youngest"
+             , Space
+             , Text "was"
+             , Space
+             , Text "so"
+             , Space
+             , Text "beautiful"
+             , Space
+             , Text "that"
+             , Space
+             , Text "the"
+             , Space
+             , Text "sun"
+             , SoftBreak
+             , Text "itself,"
+             , Space
+             , Text "which"
+             , Space
+             , Text "has"
+             , Space
+             , Text "seen"
+             , Space
+             , Text "so"
+             , Space
+             , Text "much,"
+             , Space
+             , Text "was"
+             , Space
+             , Text "astonished"
+             , Space
+             , Text "whenever"
+             , Space
+             , Text "it"
+             , Space
+             , Text "shone"
+             , Space
+             , Text "in"
+             , Space
+             , Text "her"
+             , Space
+             , Text "face"
+             , Text "."
+             , SoftBreak
+             , Text "Close"
+             , Space
+             , Text "by"
+             , Space
+             , Text "the"
+             , Space
+             , Text "king\8217s"
+             , Space
+             , Text "castle"
+             , Space
+             , Text "lay"
+             , Space
+             , Text "a"
+             , Space
+             , Text "great"
+             , Space
+             , Text "dark"
+             , Space
+             , Text "red,"
+             , Space
+             , Text "and"
+             , Space
+             , Text "under"
+             , Space
+             , Text "an"
+             , Space
+             , Text "old"
+             , Space
+             , Text "lime"
+             , Text "-"
+             , Text "tree"
+             , SoftBreak
+             , Text "in"
+             , Space
+             , Text "the"
+             , Space
+             , Text "red"
+             , Space
+             , Text "was"
+             , Space
+             , Text "a"
+             , Space
+             , Text "well,"
+             , Space
+             , Text "and"
+             , Space
+             , Text "when"
+             , Space
+             , Text "the"
+             , Space
+             , Text "day"
+             , Space
+             , Text "was"
+             , Space
+             , Text "very"
+             , Space
+             , Text "warm,"
+             , Space
+             , Text "the"
+             , Space
+             , Text "king\8217s"
+             , Space
+             , Text "child"
+             , SoftBreak
+             , Text "went"
+             , Space
+             , Text "out"
+             , Space
+             , Text "into"
+             , Space
+             , Text "the"
+             , Space
+             , Text "red"
+             , Space
+             , Text "and"
+             , Space
+             , Text "sat"
+             , Space
+             , Text "down"
+             , Space
+             , Text "by"
+             , Space
+             , Text "the"
+             , Space
+             , Text "side"
+             , Space
+             , Text "of"
+             , Space
+             , Text "the"
+             , Space
+             , Text "cool"
+             , Space
+             , Text "fountain;"
+             , Space
+             , Text "and"
+             , SoftBreak
+             , Text "when"
+             , Space
+             , Text "she"
+             , Space
+             , Text "was"
+             , Space
+             , Text "bored"
+             , Space
+             , Text "she"
+             , Space
+             , Text "took"
+             , Space
+             , Text "a"
+             , Space
+             , Text "golden"
+             , Space
+             , Text "ball,"
+             , Space
+             , Text "and"
+             , Space
+             , Text "threw"
+             , Space
+             , Text "it"
+             , Space
+             , Text "up"
+             , Space
+             , Text "on"
+             , Space
+             , Text "high"
+             , Space
+             , Text "and"
+             , Space
+             , Text "caught"
+             , SoftBreak
+             , Text "it;"
+             , Space
+             , Text "and"
+             , Space
+             , Text "this"
+             , Space
+             , Text "ball"
+             , Space
+             , Text "was"
+             , Space
+             , Text "her"
+             , Space
+             , Text "favorite"
+             , Space
+             , Text "plaything"
+             , Text "."
+             , ParBreak
+             ])))
+, ParBreak
+, Code
+    "test/typ/layout/par-knuth-00.typ"
+    ( line 17 , column 2 )
+    (LetFunc
+       (Identifier "column")
+       [ NormalParam (Identifier "title")
+       , NormalParam (Identifier "linebreaks")
+       , NormalParam (Identifier "hyphenate")
+       ]
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "rect"))
+                 [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+                 , KeyValArg (Identifier "width") (Literal (Numeric 132.0 Pt))
+                 , KeyValArg
+                     (Identifier "fill")
+                     (FuncCall
+                        (Ident (Identifier "rgb")) [ NormalArg (Literal (String "eee")) ])
+                 , BlockArg
+                     [ SoftBreak
+                     , Code
+                         "test/typ/layout/par-knuth-00.typ"
+                         ( line 19 , column 6 )
+                         (Set
+                            (Ident (Identifier "par"))
+                            [ KeyValArg
+                                (Identifier "linebreaks") (Ident (Identifier "linebreaks"))
+                            ])
+                     , SoftBreak
+                     , Code
+                         "test/typ/layout/par-knuth-00.typ"
+                         ( line 20 , column 6 )
+                         (Set
+                            (Ident (Identifier "text"))
+                            [ KeyValArg
+                                (Identifier "hyphenate") (Ident (Identifier "hyphenate"))
+                            ])
+                     , SoftBreak
+                     , Code
+                         "test/typ/layout/par-knuth-00.typ"
+                         ( line 21 , column 6 )
+                         (FuncCall
+                            (Ident (Identifier "strong"))
+                            [ NormalArg (Ident (Identifier "title")) ])
+                     , Space
+                     , HardBreak
+                     , Code
+                         "test/typ/layout/par-knuth-00.typ"
+                         ( line 21 , column 23 )
+                         (Ident (Identifier "story"))
+                     , ParBreak
+                     ]
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/layout/par-knuth-00.typ"
+    ( line 25 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 3))
+       , KeyValArg (Identifier "gutter") (Literal (Numeric 10.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "column"))
+              [ NormalArg
+                  (Block
+                     (Content
+                        [ Text "Simple"
+                        , Space
+                        , Text "without"
+                        , Space
+                        , Text "hyphens"
+                        ]))
+              , NormalArg (Literal (String "simple"))
+              , NormalArg (Literal (Boolean False))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "column"))
+              [ NormalArg
+                  (Block
+                     (Content
+                        [ Text "Simple" , Space , Text "with" , Space , Text "hyphens" ]))
+              , NormalArg (Literal (String "simple"))
+              , NormalArg (Literal (Boolean True))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "column"))
+              [ NormalArg
+                  (Block
+                     (Content
+                        [ Text "Optimized"
+                        , Space
+                        , Text "with"
+                        , Space
+                        , Text "hyphens"
+                        ]))
+              , NormalArg (Literal (String "optimized"))
+              , NormalArg (Literal (Boolean True))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  parbreak(), 
+  grid(children: (rect(body: { text(body: [
+], 
+                                    font: "New Computer Modern"), 
+                               text(body: [
+], 
+                                    font: "New Computer Modern"), 
+                               text(body: [
+], 
+                                    font: "New Computer Modern", 
+                                    hyphenate: false), 
+                               strong(body: text(body: [Simple without hyphens], 
+                                                 font: "New Computer Modern")), 
+                               text(body: [ ], 
+                                    font: "New Computer Modern", 
+                                    hyphenate: false), 
+                               linebreak(), 
+                               text(body: [
+In olden times when wishing still helped one, there lived a king whose
+daughters were all beautiful; and the youngest was so beautiful that the sun
+itself, which has seen so much, was astonished whenever it shone in her face.
+Close by the king’s castle lay a great dark red, and under an old lime-tree
+in the red was a well, and when the day was very warm, the king’s child
+went out into the red and sat down by the side of the cool fountain; and
+when she was bored she took a golden ball, and threw it up on high and caught
+it; and this ball was her favorite plaything.], 
+                                    font: "New Computer Modern"), 
+                               parbreak(), 
+                               parbreak() }, 
+                       fill: rgb(5%,5%,5%,100%), 
+                       inset: 0.0pt, 
+                       width: 132.0pt), 
+                  rect(body: { text(body: [
+], 
+                                    font: "New Computer Modern"), 
+                               text(body: [
+], 
+                                    font: "New Computer Modern"), 
+                               text(body: [
+], 
+                                    font: "New Computer Modern", 
+                                    hyphenate: true), 
+                               strong(body: text(body: [Simple with hyphens], 
+                                                 font: "New Computer Modern")), 
+                               text(body: [ ], 
+                                    font: "New Computer Modern", 
+                                    hyphenate: true), 
+                               linebreak(), 
+                               text(body: [
+In olden times when wishing still helped one, there lived a king whose
+daughters were all beautiful; and the youngest was so beautiful that the sun
+itself, which has seen so much, was astonished whenever it shone in her face.
+Close by the king’s castle lay a great dark red, and under an old lime-tree
+in the red was a well, and when the day was very warm, the king’s child
+went out into the red and sat down by the side of the cool fountain; and
+when she was bored she took a golden ball, and threw it up on high and caught
+it; and this ball was her favorite plaything.], 
+                                    font: "New Computer Modern"), 
+                               parbreak(), 
+                               parbreak() }, 
+                       fill: rgb(5%,5%,5%,100%), 
+                       inset: 0.0pt, 
+                       width: 132.0pt), 
+                  rect(body: { text(body: [
+], 
+                                    font: "New Computer Modern"), 
+                               text(body: [
+], 
+                                    font: "New Computer Modern"), 
+                               text(body: [
+], 
+                                    font: "New Computer Modern", 
+                                    hyphenate: true), 
+                               strong(body: text(body: [Optimized with hyphens], 
+                                                 font: "New Computer Modern")), 
+                               text(body: [ ], 
+                                    font: "New Computer Modern", 
+                                    hyphenate: true), 
+                               linebreak(), 
+                               text(body: [
+In olden times when wishing still helped one, there lived a king whose
+daughters were all beautiful; and the youngest was so beautiful that the sun
+itself, which has seen so much, was astonished whenever it shone in her face.
+Close by the king’s castle lay a great dark red, and under an old lime-tree
+in the red was a well, and when the day was very warm, the king’s child
+went out into the red and sat down by the side of the cool fountain; and
+when she was bored she took a golden ball, and threw it up on high and caught
+it; and this ball was her favorite plaything.], 
+                                    font: "New Computer Modern"), 
+                               parbreak(), 
+                               parbreak() }, 
+                       fill: rgb(5%,5%,5%,100%), 
+                       inset: 0.0pt, 
+                       width: 132.0pt)), 
+       columns: 3, 
+       gutter: 10.0pt), 
+  parbreak() }
diff --git a/test/out/layout/par-simple-00.out b/test/out/layout/par-simple-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/par-simple-00.out
@@ -0,0 +1,488 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/par-simple-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/par-simple-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/par-simple-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/par-simple-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 250.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 120.0 Pt))
+       ])
+, ParBreak
+, Text "But,"
+, Space
+, Text "soft!"
+, Space
+, Text "what"
+, Space
+, Text "light"
+, Space
+, Text "through"
+, Space
+, Text "yonder"
+, Space
+, Text "window"
+, Space
+, Text "breaks?"
+, Space
+, Text "It"
+, Space
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "east,"
+, Space
+, Text "and"
+, Space
+, Text "Juliet"
+, SoftBreak
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "sun"
+, Text "."
+, Space
+, Text "Arise,"
+, Space
+, Text "fair"
+, Space
+, Text "sun,"
+, Space
+, Text "and"
+, Space
+, Text "kill"
+, Space
+, Text "the"
+, Space
+, Text "envious"
+, Space
+, Text "moon,"
+, Space
+, Text "Who"
+, Space
+, Text "is"
+, Space
+, Text "already"
+, Space
+, Text "sick"
+, Space
+, Text "and"
+, SoftBreak
+, Text "pale"
+, Space
+, Text "with"
+, Space
+, Text "grief,"
+, Space
+, Text "That"
+, Space
+, Text "thou"
+, Space
+, Text "her"
+, Space
+, Text "maid"
+, Space
+, Text "art"
+, Space
+, Text "far"
+, Space
+, Text "more"
+, Space
+, Text "fair"
+, Space
+, Text "than"
+, Space
+, Text "she"
+, Text ":"
+, Space
+, Text "Be"
+, Space
+, Text "not"
+, Space
+, Text "her"
+, Space
+, Text "maid,"
+, SoftBreak
+, Text "since"
+, Space
+, Text "she"
+, Space
+, Text "is"
+, Space
+, Text "envious;"
+, Space
+, Text "Her"
+, Space
+, Text "vestal"
+, Space
+, Text "livery"
+, Space
+, Text "is"
+, Space
+, Text "but"
+, Space
+, Text "sick"
+, Space
+, Text "and"
+, Space
+, Text "green"
+, Space
+, Text "And"
+, Space
+, Text "none"
+, Space
+, Text "but"
+, Space
+, Text "fools"
+, SoftBreak
+, Text "do"
+, Space
+, Text "wear"
+, Space
+, Text "it;"
+, Space
+, Text "cast"
+, Space
+, Text "it"
+, Space
+, Text "off"
+, Text "."
+, Space
+, Text "It"
+, Space
+, Text "is"
+, Space
+, Text "my"
+, Space
+, Text "lady,"
+, Space
+, Text "O,"
+, Space
+, Text "it"
+, Space
+, Text "is"
+, Space
+, Text "my"
+, Space
+, Text "love!"
+, Space
+, Text "O,"
+, Space
+, Text "that"
+, Space
+, Text "she"
+, Space
+, Text "knew"
+, Space
+, Text "she"
+, SoftBreak
+, Text "were!"
+, Space
+, Text "She"
+, Space
+, Text "speaks"
+, Space
+, Text "yet"
+, Space
+, Text "she"
+, Space
+, Text "says"
+, Space
+, Text "nothing"
+, Text ":"
+, Space
+, Text "what"
+, Space
+, Text "of"
+, Space
+, Text "that?"
+, Space
+, Text "Her"
+, Space
+, Text "eye"
+, Space
+, Text "discourses;"
+, Space
+, Text "I"
+, Space
+, Text "will"
+, SoftBreak
+, Text "answer"
+, Space
+, Text "it"
+, Text "."
+, ParBreak
+, Text "I"
+, Space
+, Text "am"
+, Space
+, Text "too"
+, Space
+, Text "bold,"
+, Space
+, Quote '\''
+, Text "tis"
+, Space
+, Text "not"
+, Space
+, Text "to"
+, Space
+, Text "me"
+, Space
+, Text "she"
+, Space
+, Text "speaks"
+, Text ":"
+, Space
+, Text "Two"
+, Space
+, Text "of"
+, Space
+, Text "the"
+, Space
+, Text "fairest"
+, Space
+, Text "stars"
+, Space
+, Text "in"
+, Space
+, Text "all"
+, Space
+, Text "the"
+, SoftBreak
+, Text "heaven,"
+, Space
+, Text "Having"
+, Space
+, Text "some"
+, Space
+, Text "business,"
+, Space
+, Text "do"
+, Space
+, Text "entreat"
+, Space
+, Text "her"
+, Space
+, Text "eyes"
+, Space
+, Text "To"
+, Space
+, Text "twinkle"
+, Space
+, Text "in"
+, Space
+, Text "their"
+, Space
+, Text "spheres"
+, SoftBreak
+, Text "till"
+, Space
+, Text "they"
+, Space
+, Text "return"
+, Text "."
+, Space
+, Text "What"
+, Space
+, Text "if"
+, Space
+, Text "her"
+, Space
+, Text "eyes"
+, Space
+, Text "were"
+, Space
+, Text "there,"
+, Space
+, Text "they"
+, Space
+, Text "in"
+, Space
+, Text "her"
+, Space
+, Text "head?"
+, Space
+, Text "The"
+, Space
+, Text "brightness"
+, SoftBreak
+, Text "of"
+, Space
+, Text "her"
+, Space
+, Text "cheek"
+, Space
+, Text "would"
+, Space
+, Text "shame"
+, Space
+, Text "those"
+, Space
+, Text "stars,"
+, Space
+, Text "As"
+, Space
+, Text "daylight"
+, Space
+, Text "doth"
+, Space
+, Text "a"
+, Space
+, Text "lamp;"
+, Space
+, Text "her"
+, Space
+, Text "eyes"
+, Space
+, Text "in"
+, SoftBreak
+, Text "heaven"
+, Space
+, Text "Would"
+, Space
+, Text "through"
+, Space
+, Text "the"
+, Space
+, Text "airy"
+, Space
+, Text "region"
+, Space
+, Text "stream"
+, Space
+, Text "so"
+, Space
+, Text "bright"
+, Space
+, Text "That"
+, Space
+, Text "birds"
+, Space
+, Text "would"
+, Space
+, Text "sing"
+, Space
+, Text "and"
+, SoftBreak
+, Text "think"
+, Space
+, Text "it"
+, Space
+, Text "were"
+, Space
+, Text "not"
+, Space
+, Text "night"
+, Text "."
+, Space
+, Text "See,"
+, Space
+, Text "how"
+, Space
+, Text "she"
+, Space
+, Text "leans"
+, Space
+, Text "her"
+, Space
+, Text "cheek"
+, Space
+, Text "upon"
+, Space
+, Text "her"
+, Space
+, Text "hand!"
+, Space
+, Text "O,"
+, Space
+, Text "that"
+, Space
+, Text "I"
+, SoftBreak
+, Text "were"
+, Space
+, Text "a"
+, Space
+, Text "glove"
+, Space
+, Text "upon"
+, Space
+, Text "that"
+, Space
+, Text "hand,"
+, Space
+, Text "That"
+, Space
+, Text "I"
+, Space
+, Text "might"
+, Space
+, Text "touch"
+, Space
+, Text "that"
+, Space
+, Text "cheek!"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [But, soft! what light through yonder window breaks? It is the east, and Juliet
+is the sun. Arise, fair sun, and kill the envious moon, Who is already sick and
+pale with grief, That thou her maid art far more fair than she: Be not her maid,
+since she is envious; Her vestal livery is but sick and green And none but fools
+do wear it; cast it off. It is my lady, O, it is my love! O, that she knew she
+were! She speaks yet she says nothing: what of that? Her eye discourses; I will
+answer it.]), 
+  parbreak(), 
+  text(body: [I am too bold, ‘tis not to me she speaks: Two of the fairest stars in all the
+heaven, Having some business, do entreat her eyes To twinkle in their spheres
+till they return. What if her eyes were there, they in her head? The brightness
+of her cheek would shame those stars, As daylight doth a lamp; her eyes in
+heaven Would through the airy region stream so bright That birds would sing and
+think it were not night. See, how she leans her cheek upon her hand! O, that I
+were a glove upon that hand, That I might touch that cheek!]), 
+  parbreak() }
diff --git a/test/out/layout/place-00.out b/test/out/layout/place-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/place-00.out
@@ -0,0 +1,241 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/place-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/place-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/place-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/place-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page")) [ NormalArg (Literal (String "a8")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/place-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "place"))
+       [ NormalArg
+           (Plus (Ident (Identifier "bottom")) (Ident (Identifier "center")))
+       , BlockArg [ Text "\169" , Space , Text "Typst" ]
+       ])
+, ParBreak
+, Heading 1 [ Text "Placement" ]
+, Code
+    "test/typ/layout/place-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "place"))
+       [ NormalArg (Ident (Identifier "right"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 1.8 Cm))
+              ])
+       ])
+, SoftBreak
+, Text "Hi"
+, Space
+, Text "there"
+, Text "."
+, Space
+, Text "This"
+, Space
+, Text "is"
+, Space
+, HardBreak
+, Text "a"
+, Space
+, Text "placed"
+, Space
+, Text "element"
+, Text "."
+, Space
+, HardBreak
+, Text "Unfortunately,"
+, Space
+, HardBreak
+, Text "the"
+, Space
+, Text "line"
+, Space
+, Text "breaks"
+, Space
+, Text "still"
+, Space
+, Text "had"
+, Space
+, Text "to"
+, Space
+, Text "be"
+, Space
+, Text "inserted"
+, Space
+, Text "manually"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/layout/place-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "place"))
+              [ NormalArg (Ident (Identifier "right"))
+              , KeyValArg (Identifier "dy") (Literal (Numeric 1.5 Pt))
+              , BlockArg [ Text "ABC" ]
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+              , KeyValArg (Identifier "width") (Literal (Numeric 80.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              ])
+       , NormalArg (Literal (Numeric 10.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "block"))
+              [ BlockArg
+                  [ SoftBreak
+                  , Code
+                      "test/typ/layout/place-00.typ"
+                      ( line 19 , column 6 )
+                      (FuncCall
+                         (Ident (Identifier "place"))
+                         [ NormalArg (Ident (Identifier "center"))
+                         , KeyValArg (Identifier "dx") (Negated (Literal (Numeric 7.0 Pt)))
+                         , KeyValArg (Identifier "dy") (Negated (Literal (Numeric 5.0 Pt)))
+                         , BlockArg [ Text "Hello" ]
+                         ])
+                  , SoftBreak
+                  , Code
+                      "test/typ/layout/place-00.typ"
+                      ( line 20 , column 6 )
+                      (FuncCall
+                         (Ident (Identifier "place"))
+                         [ NormalArg (Ident (Identifier "center"))
+                         , KeyValArg (Identifier "dx") (Literal (Numeric 7.0 Pt))
+                         , KeyValArg (Identifier "dy") (Literal (Numeric 5.0 Pt))
+                         , BlockArg [ Text "Hello" ]
+                         ])
+                  , SoftBreak
+                  , Text "Hello"
+                  , Space
+                  , Code
+                      "test/typ/layout/place-00.typ"
+                      ( line 21 , column 12 )
+                      (FuncCall
+                         (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+                  , Space
+                  , Text "Hello"
+                  , ParBreak
+                  ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  place(alignment: Axes(center, bottom), 
+        body: text(body: [© Typst])), 
+  parbreak(), 
+  heading(body: text(body: [Placement]), 
+          level: 1), 
+  place(alignment: right, 
+        body: image(path: "test/assets/files/tiger.jpg", 
+                    width: 1.8cm)), 
+  text(body: [
+Hi there. This is ]), 
+  linebreak(), 
+  text(body: [a placed element. ]), 
+  linebreak(), 
+  text(body: [Unfortunately, ]), 
+  linebreak(), 
+  text(body: [the line breaks still had to be inserted manually.]), 
+  parbreak(), 
+  stack(children: (rect(fill: rgb(13%,61%,67%,100%), 
+                        height: 10.0pt, 
+                        width: 100%), 
+                   place(alignment: right, 
+                         body: text(body: [ABC]), 
+                         dy: 1.5pt), 
+                   rect(fill: rgb(18%,80%,25%,100%), 
+                        height: 10.0pt, 
+                        width: 80%), 
+                   rect(fill: rgb(100%,25%,21%,100%), 
+                        height: 10.0pt, 
+                        width: 100%), 
+                   10.0pt, 
+                   block(body: { text(body: [
+]), 
+                                 place(alignment: center, 
+                                       body: text(body: [Hello]), 
+                                       dx: -7.0pt, 
+                                       dy: -5.0pt), 
+                                 text(body: [
+]), 
+                                 place(alignment: center, 
+                                       body: text(body: [Hello]), 
+                                       dx: 7.0pt, 
+                                       dy: 5.0pt), 
+                                 text(body: [
+Hello ]), 
+                                 h(amount: 1.0fr), 
+                                 text(body: [ Hello]), 
+                                 parbreak() }))), 
+  parbreak() }
diff --git a/test/out/layout/place-01.out b/test/out/layout/place-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/place-01.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/place-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/place-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/place-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/place-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ NormalArg (Literal (String "a8"))
+       , KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt))
+       ])
+, ParBreak
+, Text "First"
+, ParBreak
+, Code
+    "test/typ/layout/place-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "place"))
+       [ NormalArg
+           (Plus (Ident (Identifier "bottom")) (Ident (Identifier "right")))
+       , BlockArg [ Text "Placed" ]
+       ])
+, ParBreak
+, Text "Second"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [First]), 
+  parbreak(), 
+  place(alignment: Axes(right, bottom), 
+        body: text(body: [Placed])), 
+  parbreak(), 
+  text(body: [Second]), 
+  parbreak() }
diff --git a/test/out/layout/place-background-00.out b/test/out/layout/place-background-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/place-background-00.out
@@ -0,0 +1,131 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/place-background-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/place-background-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/place-background-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/place-background-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "paper") (Literal (String "a10"))
+       , KeyValArg (Identifier "flipped") (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/place-background-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "white")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/place-background-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "place"))
+       [ KeyValArg (Identifier "dx") (Negated (Literal (Numeric 10.0 Pt)))
+       , KeyValArg (Identifier "dy") (Negated (Literal (Numeric 10.0 Pt)))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "/tiger.jpg"))
+              , KeyValArg (Identifier "fit") (Literal (String "cover"))
+              , KeyValArg
+                  (Identifier "width")
+                  (Plus
+                     (Literal (Numeric 100.0 Percent)) (Literal (Numeric 20.0 Pt)))
+              , KeyValArg
+                  (Identifier "height")
+                  (Plus
+                     (Literal (Numeric 100.0 Percent)) (Literal (Numeric 20.0 Pt)))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/place-background-00.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg
+           (Plus (Ident (Identifier "bottom")) (Ident (Identifier "right")))
+       , BlockArg
+           [ SoftBreak
+           , Emph [ Text "Welcome" , Space , Text "to" ]
+           , Space
+           , Code
+               "test/typ/layout/place-background-00.typ"
+               ( line 15 , column 17 )
+               (FuncCall
+                  (Ident (Identifier "underline"))
+                  [ BlockArg [ Strong [ Text "Tigerland" ] ] ])
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       fill: rgb(100%,100%,100%,100%)), 
+  place(body: image(fit: "cover", 
+                    height: 20.0pt + 100%, 
+                    path: "/tiger.jpg", 
+                    width: 20.0pt + 100%), 
+        dx: -10.0pt, 
+        dy: -10.0pt), 
+  text(body: [
+], 
+       fill: rgb(100%,100%,100%,100%)), 
+  align(alignment: Axes(right, bottom), 
+        body: { text(body: [
+], 
+                     fill: rgb(100%,100%,100%,100%)), 
+                emph(body: text(body: [Welcome to], 
+                                fill: rgb(100%,100%,100%,100%))), 
+                text(body: [ ], 
+                     fill: rgb(100%,100%,100%,100%)), 
+                underline(body: strong(body: text(body: [Tigerland], 
+                                                  fill: rgb(100%,100%,100%,100%)))), 
+                parbreak() }), 
+  parbreak() }
diff --git a/test/out/layout/repeat-00.out b/test/out/layout/repeat-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/repeat-00.out
@@ -0,0 +1,160 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/repeat-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/repeat-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/repeat-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/repeat-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "sections")))
+       (Array
+          [ Array [ Literal (String "Introduction") , Literal (Int 1) ]
+          , Array [ Literal (String "Approach") , Literal (Int 1) ]
+          , Array [ Literal (String "Evaluation") , Literal (Int 3) ]
+          , Array [ Literal (String "Discussion") , Literal (Int 15) ]
+          , Array [ Literal (String "Related Work") , Literal (Int 16) ]
+          , Array [ Literal (String "Conclusion") , Literal (Int 253) ]
+          ]))
+, ParBreak
+, Code
+    "test/typ/layout/repeat-00.typ"
+    ( line 12 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "section")))
+       (Ident (Identifier "sections"))
+       (Block
+          (Content
+             [ SoftBreak
+             , Code
+                 "test/typ/layout/repeat-00.typ"
+                 ( line 13 , column 4 )
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "at")) (Ident (Identifier "section")))
+                    [ NormalArg (Literal (Int 0)) ])
+             , Space
+             , Code
+                 "test/typ/layout/repeat-00.typ"
+                 ( line 13 , column 19 )
+                 (FuncCall
+                    (Ident (Identifier "box"))
+                    [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+                    , NormalArg
+                        (FuncCall (Ident (Identifier "repeat")) [ BlockArg [ Text "." ] ])
+                    ])
+             , Space
+             , Code
+                 "test/typ/layout/repeat-00.typ"
+                 ( line 13 , column 47 )
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "at")) (Ident (Identifier "section")))
+                    [ NormalArg (Literal (Int 1)) ])
+             , Space
+             , HardBreak
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [Introduction]), 
+  text(body: [ ]), 
+  box(body: repeat(body: text(body: [.])), 
+      width: 1.0fr), 
+  text(body: [ ]), 
+  text(body: [1]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+]), 
+  text(body: [Approach]), 
+  text(body: [ ]), 
+  box(body: repeat(body: text(body: [.])), 
+      width: 1.0fr), 
+  text(body: [ ]), 
+  text(body: [1]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+]), 
+  text(body: [Evaluation]), 
+  text(body: [ ]), 
+  box(body: repeat(body: text(body: [.])), 
+      width: 1.0fr), 
+  text(body: [ ]), 
+  text(body: [3]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+]), 
+  text(body: [Discussion]), 
+  text(body: [ ]), 
+  box(body: repeat(body: text(body: [.])), 
+      width: 1.0fr), 
+  text(body: [ ]), 
+  text(body: [15]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+]), 
+  text(body: [Related Work]), 
+  text(body: [ ]), 
+  box(body: repeat(body: text(body: [.])), 
+      width: 1.0fr), 
+  text(body: [ ]), 
+  text(body: [16]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+]), 
+  text(body: [Conclusion]), 
+  text(body: [ ]), 
+  box(body: repeat(body: text(body: [.])), 
+      width: 1.0fr), 
+  text(body: [ ]), 
+  text(body: [253]), 
+  text(body: [ ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/layout/repeat-01.out b/test/out/layout/repeat-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/repeat-01.out
@@ -0,0 +1,76 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/repeat-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/repeat-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/repeat-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/repeat-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ar")) ])
+, SoftBreak
+, Text "\1605\1602\1583\1605\1577"
+, Space
+, Code
+    "test/typ/layout/repeat-01.typ"
+    ( line 4 , column 8 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall (Ident (Identifier "repeat")) [ BlockArg [ Text "." ] ])
+       ])
+, Space
+, Text "15"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+مقدمة ], 
+       lang: "ar"), 
+  box(body: repeat(body: text(body: [.], 
+                              lang: "ar")), 
+      width: 1.0fr), 
+  text(body: [ 15], 
+       lang: "ar"), 
+  parbreak() }
diff --git a/test/out/layout/repeat-02.out b/test/out/layout/repeat-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/repeat-02.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/repeat-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/repeat-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/repeat-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Space
+, Code
+    "test/typ/layout/repeat-02.typ"
+    ( line 3 , column 4 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall (Ident (Identifier "repeat")) [ BlockArg [] ])
+       ])
+, Space
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A ]), 
+  box(body: repeat(body: {  }), 
+      width: 1.0fr), 
+  text(body: [ B]), 
+  parbreak() }
diff --git a/test/out/layout/repeat-03.out b/test/out/layout/repeat-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/repeat-03.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/repeat-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/repeat-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/repeat-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/repeat-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "repeat"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 2.0 Em))
+              , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  repeat(body: rect(height: 1.0em, 
+                    width: 2.0em)), 
+  parbreak() }
diff --git a/test/out/layout/repeat-04.out b/test/out/layout/repeat-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/repeat-04.out
@@ -0,0 +1,141 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/repeat-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/repeat-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/repeat-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Code
+    "test/typ/layout/repeat-04.typ"
+    ( line 3 , column 3 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "repeat"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "width") (Literal (Numeric 6.0 Em))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 0.7 Em))
+                     ])
+              ])
+       ])
+, Text "B"
+, ParBreak
+, Code
+    "test/typ/layout/repeat-04.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center")) ])
+, SoftBreak
+, Text "A"
+, Code
+    "test/typ/layout/repeat-04.typ"
+    ( line 6 , column 3 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "repeat"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "width") (Literal (Numeric 6.0 Em))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 0.7 Em))
+                     ])
+              ])
+       ])
+, Text "B"
+, ParBreak
+, Code
+    "test/typ/layout/repeat-04.typ"
+    ( line 8 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl")) ])
+, SoftBreak
+, Text "\1585\1610\1580\1610\1606"
+, Code
+    "test/typ/layout/repeat-04.typ"
+    ( line 9 , column 7 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "repeat"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "width") (Literal (Numeric 4.0 Em))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 0.7 Em))
+                     ])
+              ])
+       ])
+, Text "\1587\1608\1606"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A]), 
+  box(body: repeat(body: rect(height: 0.7em, 
+                              width: 6.0em)), 
+      width: 1.0fr), 
+  text(body: [B]), 
+  parbreak(), 
+  text(body: [
+A]), 
+  box(body: repeat(body: rect(height: 0.7em, 
+                              width: 6.0em)), 
+      width: 1.0fr), 
+  text(body: [B]), 
+  parbreak(), 
+  text(body: [
+ريجين], 
+       dir: rtl), 
+  box(body: repeat(body: rect(height: 0.7em, 
+                              width: 4.0em)), 
+      width: 1.0fr), 
+  text(body: [سون], dir: rtl), 
+  parbreak() }
diff --git a/test/out/layout/repeat-05.out b/test/out/layout/repeat-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/repeat-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/spacing-00.out b/test/out/layout/spacing-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/spacing-00.out
@@ -0,0 +1,200 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/spacing-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/spacing-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ BlockArg [ Text "A" , Space , HardBreak , Text "B" ] ])
+, Space
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 3 , column 14 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ BlockArg
+           [ Text "A"
+           , Space
+           , Code
+               "test/typ/layout/spacing-00.typ"
+               ( line 3 , column 21 )
+               (FuncCall
+                  (Ident (Identifier "v"))
+                  [ NormalArg (Literal (Numeric 0.65 Em))
+                  , KeyValArg (Identifier "weak") (Literal (Boolean True))
+                  ])
+           , Space
+           , Text "B"
+           ]
+       ])
+, ParBreak
+, Comment
+, Text "Inv"
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 6 , column 5 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 0.0 Pt)) ])
+, Text "isible"
+, ParBreak
+, Comment
+, Text "Add"
+, Space
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 9 , column 6 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 10.0 Pt)) ])
+, Space
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 9 , column 15 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 10.0 Pt)) ])
+, Space
+, Text "up"
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 12 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "x")))
+       (Minus
+          (Literal (Numeric 25.0 Percent)) (Literal (Numeric 4.0 Pt))))
+, SoftBreak
+, Text "|"
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 13 , column 3 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Ident (Identifier "x")) ])
+, Text "|"
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 13 , column 9 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Ident (Identifier "x")) ])
+, Text "|"
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 13 , column 15 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Ident (Identifier "x")) ])
+, Text "|"
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 13 , column 21 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Ident (Identifier "x")) ])
+, Text "|"
+, ParBreak
+, Comment
+, Text "|"
+, Space
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 16 , column 4 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "|"
+, Space
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 16 , column 14 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 2.0 Fr)) ])
+, Space
+, Text "|"
+, Space
+, Code
+    "test/typ/layout/spacing-00.typ"
+    ( line 16 , column 24 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "|"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  box(body: { text(body: [A ]), 
+              linebreak(), 
+              text(body: [B]) }), 
+  text(body: [ ]), 
+  box(body: { text(body: [A ]), 
+              v(amount: 0.65em, 
+                weak: true), 
+              text(body: [ B]) }), 
+  parbreak(), 
+  text(body: [Inv]), 
+  h(amount: 0.0pt), 
+  text(body: [isible]), 
+  parbreak(), 
+  text(body: [Add ]), 
+  h(amount: 10.0pt), 
+  text(body: [ ]), 
+  h(amount: 10.0pt), 
+  text(body: [ up]), 
+  parbreak(), 
+  text(body: [
+|]), 
+  h(amount: -4.0pt + 25%), 
+  text(body: [|]), 
+  h(amount: -4.0pt + 25%), 
+  text(body: [|]), 
+  h(amount: -4.0pt + 25%), 
+  text(body: [|]), 
+  h(amount: -4.0pt + 25%), 
+  text(body: [|]), 
+  parbreak(), 
+  text(body: [| ]), 
+  h(amount: 1.0fr), 
+  text(body: [ | ]), 
+  h(amount: 2.0fr), 
+  text(body: [ | ]), 
+  h(amount: 1.0fr), 
+  text(body: [ |]), 
+  parbreak() }
diff --git a/test/out/layout/spacing-01.out b/test/out/layout/spacing-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/spacing-01.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/spacing-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/spacing-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/spacing-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/spacing-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "right")) ])
+, SoftBreak
+, Text "A"
+, Space
+, Code
+    "test/typ/layout/spacing-01.typ"
+    ( line 4 , column 4 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 0.0 Pt)) ])
+, Space
+, Text "B"
+, Space
+, Code
+    "test/typ/layout/spacing-01.typ"
+    ( line 4 , column 14 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 0.0 Pt)) ])
+, Space
+, HardBreak
+, Text "A"
+, Space
+, Text "B"
+, Space
+, HardBreak
+, Text "A"
+, Space
+, Code
+    "test/typ/layout/spacing-01.typ"
+    ( line 6 , column 4 )
+    (FuncCall
+       (Ident (Identifier "h"))
+       [ NormalArg (Negated (Literal (Numeric 1.0 Fr))) ])
+, Space
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+A ]), 
+  h(amount: 0.0pt), 
+  text(body: [ B ]), 
+  h(amount: 0.0pt), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [A B ]), 
+  linebreak(), 
+  text(body: [A ]), 
+  h(amount: -1.0fr), 
+  text(body: [ B]), 
+  parbreak() }
diff --git a/test/out/layout/spacing-02.out b/test/out/layout/spacing-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/spacing-02.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/spacing-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/spacing-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/spacing-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/spacing-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl")) ])
+, SoftBreak
+, Text "A"
+, Space
+, Code
+    "test/typ/layout/spacing-02.typ"
+    ( line 4 , column 4 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 10.0 Pt)) ])
+, Space
+, Text "B"
+, Space
+, HardBreak
+, Text "A"
+, Space
+, Code
+    "test/typ/layout/spacing-02.typ"
+    ( line 5 , column 4 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+A ], dir: rtl), 
+  h(amount: 10.0pt), 
+  text(body: [ B ], dir: rtl), 
+  linebreak(), 
+  text(body: [A ], dir: rtl), 
+  h(amount: 1.0fr), 
+  text(body: [ B], dir: rtl), 
+  parbreak() }
diff --git a/test/out/layout/spacing-03.out b/test/out/layout/spacing-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/spacing-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/stack-1-00.out b/test/out/layout/stack-1-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/stack-1-00.out
@@ -0,0 +1,177 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/stack-1-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/stack-1-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/stack-1-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/stack-1-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "widths")))
+       (Array
+          [ Literal (Numeric 30.0 Pt)
+          , Literal (Numeric 20.0 Pt)
+          , Literal (Numeric 40.0 Pt)
+          , Literal (Numeric 15.0 Pt)
+          , Literal (Numeric 30.0 Pt)
+          , Literal (Numeric 50.0 Percent)
+          , Literal (Numeric 20.0 Pt)
+          , Literal (Numeric 100.0 Percent)
+          ]))
+, ParBreak
+, Code
+    "test/typ/layout/stack-1-00.typ"
+    ( line 8 , column 2 )
+    (LetFunc
+       (Identifier "shaded")
+       [ NormalParam (Identifier "i") , NormalParam (Identifier "w") ]
+       (Block
+          (CodeBlock
+             [ Let
+                 (BasicBind (Just (Identifier "v")))
+                 (Times
+                    (Plus (Ident (Identifier "i")) (Literal (Int 1)))
+                    (Literal (Numeric 10.0 Percent)))
+             , FuncCall
+                 (Ident (Identifier "rect"))
+                 [ KeyValArg (Identifier "width") (Ident (Identifier "w"))
+                 , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+                 , KeyValArg
+                     (Identifier "fill")
+                     (FuncCall
+                        (Ident (Identifier "rgb"))
+                        [ NormalArg (Ident (Identifier "v"))
+                        , NormalArg (Ident (Identifier "v"))
+                        , NormalArg (Ident (Identifier "v"))
+                        ])
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/layout/stack-1-00.typ"
+    ( line 13 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "items")))
+       (For
+          (DestructuringBind
+             [ Simple (Just (Identifier "i"))
+             , Simple (Just (Identifier "w"))
+             ])
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "enumerate")) (Ident (Identifier "widths")))
+             [])
+          (Block
+             (CodeBlock
+                [ Array
+                    [ FuncCall
+                        (Ident (Identifier "align"))
+                        [ NormalArg (Ident (Identifier "right"))
+                        , NormalArg
+                            (FuncCall
+                               (Ident (Identifier "shaded"))
+                               [ NormalArg (Ident (Identifier "i"))
+                               , NormalArg (Ident (Identifier "w"))
+                               ])
+                        ]
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/layout/stack-1-00.typ"
+    ( line 17 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-1-00.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "btt"))
+       , SpreadArg (Ident (Identifier "items"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [
+]), 
+  stack(children: (align(alignment: right, 
+                         body: rect(fill: rgb(10%,10%,10%,100%), 
+                                    height: 10.0pt, 
+                                    width: 30.0pt)), 
+                   align(alignment: right, 
+                         body: rect(fill: rgb(20%,20%,20%,100%), 
+                                    height: 10.0pt, 
+                                    width: 20.0pt)), 
+                   align(alignment: right, 
+                         body: rect(fill: rgb(30%,30%,30%,100%), 
+                                    height: 10.0pt, 
+                                    width: 40.0pt)), 
+                   align(alignment: right, 
+                         body: rect(fill: rgb(40%,40%,40%,100%), 
+                                    height: 10.0pt, 
+                                    width: 15.0pt)), 
+                   align(alignment: right, 
+                         body: rect(fill: rgb(50%,50%,50%,100%), 
+                                    height: 10.0pt, 
+                                    width: 30.0pt)), 
+                   align(alignment: right, 
+                         body: rect(fill: rgb(60%,60%,60%,100%), 
+                                    height: 10.0pt, 
+                                    width: 50%)), 
+                   align(alignment: right, 
+                         body: rect(fill: rgb(70%,70%,70%,100%), 
+                                    height: 10.0pt, 
+                                    width: 20.0pt)), 
+                   align(alignment: right, 
+                         body: rect(fill: rgb(80%,80%,80%,100%), 
+                                    height: 10.0pt, 
+                                    width: 100%))), 
+        dir: btt), 
+  parbreak() }
diff --git a/test/out/layout/stack-1-01.out b/test/out/layout/stack-1-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/stack-1-01.out
@@ -0,0 +1,136 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/stack-1-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/stack-1-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/stack-1-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/stack-1-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt))
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/stack-1-01.typ"
+    ( line 5 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "x")))
+       (FuncCall
+          (Ident (Identifier "square"))
+          [ KeyValArg (Identifier "size") (Literal (Numeric 10.0 Pt))
+          , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/stack-1-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 5.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "stack"))
+              [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl"))
+              , KeyValArg (Identifier "spacing") (Literal (Numeric 5.0 Pt))
+              , NormalArg (Ident (Identifier "x"))
+              , NormalArg (Ident (Identifier "x"))
+              , NormalArg (Ident (Identifier "x"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "stack"))
+              [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+              , NormalArg (Ident (Identifier "x"))
+              , NormalArg (Literal (Numeric 20.0 Percent))
+              , NormalArg (Ident (Identifier "x"))
+              , NormalArg (Literal (Numeric 20.0 Percent))
+              , NormalArg (Ident (Identifier "x"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "stack"))
+              [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+              , KeyValArg (Identifier "spacing") (Literal (Numeric 5.0 Pt))
+              , NormalArg (Ident (Identifier "x"))
+              , NormalArg (Ident (Identifier "x"))
+              , NormalArg (Literal (Numeric 7.0 Pt))
+              , NormalArg (Literal (Numeric 3.0 Pt))
+              , NormalArg (Ident (Identifier "x"))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+]), 
+  stack(children: (stack(children: (square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt), 
+                                    square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt), 
+                                    square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt)), 
+                         dir: rtl, 
+                         spacing: 5.0pt), 
+                   stack(children: (square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt), 
+                                    20%, 
+                                    square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt), 
+                                    20%, 
+                                    square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt)), 
+                         dir: ltr), 
+                   stack(children: (square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt), 
+                                    square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt), 
+                                    7.0pt, 
+                                    3.0pt, 
+                                    square(fill: rgb(13%,61%,67%,100%), 
+                                           size: 10.0pt)), 
+                         dir: ltr, 
+                         spacing: 5.0pt)), 
+        spacing: 5.0pt), 
+  parbreak() }
diff --git a/test/out/layout/stack-1-02.out b/test/out/layout/stack-1-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/stack-1-02.out
@@ -0,0 +1,90 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/stack-1-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/stack-1-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/stack-1-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/stack-1-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 30.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-1-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "stack"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "width") (Literal (Numeric 40.0 Pt))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+                     , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "width") (Literal (Numeric 30.0 Pt))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 13.0 Pt))
+                     , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                     ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  box(body: stack(children: (rect(fill: rgb(18%,80%,25%,100%), 
+                                  height: 20.0pt, 
+                                  width: 40.0pt), 
+                             rect(fill: rgb(100%,25%,21%,100%), 
+                                  height: 13.0pt, 
+                                  width: 30.0pt)))), 
+  parbreak() }
diff --git a/test/out/layout/stack-1-03.out b/test/out/layout/stack-1-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/stack-1-03.out
@@ -0,0 +1,128 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/stack-1-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/stack-1-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/stack-1-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/stack-1-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 5.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-1-03.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "block"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 5.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-1-03.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-1-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl"))
+       , NormalArg (Literal (Numeric 1.0 Fr))
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Literal (Numeric 1.0 Fr))
+       , NormalArg (Block (Content [ Text "B" ]))
+       , NormalArg (Block (Content [ Text "C" ]))
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-1-03.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "center"))
+              , NormalArg (Block (Content [ Text "A" ]))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "left"))
+              , NormalArg (Block (Content [ Text "B" ]))
+              ])
+       , NormalArg (Block (Content [ Text "C" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], size: 8.0pt), 
+  stack(children: (1.0fr, 
+                   text(body: [A], size: 8.0pt), 
+                   1.0fr, 
+                   text(body: [B], size: 8.0pt), 
+                   text(body: [C], 
+                        size: 8.0pt)), 
+        dir: rtl), 
+  text(body: [
+], size: 8.0pt), 
+  stack(children: (align(alignment: center, 
+                         body: text(body: [A], 
+                                    size: 8.0pt)), 
+                   align(alignment: left, 
+                         body: text(body: [B], 
+                                    size: 8.0pt)), 
+                   text(body: [C], 
+                        size: 8.0pt)), 
+        dir: rtl), 
+  parbreak() }
diff --git a/test/out/layout/stack-2-00.out b/test/out/layout/stack-2-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/stack-2-00.out
@@ -0,0 +1,141 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/stack-2-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/stack-2-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/stack-2-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/stack-2-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 3.5 Cm)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-2-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Fr))
+       , SpreadArg
+           (For
+              (BasicBind (Just (Identifier "c")))
+              (Literal (String "ABCDEFGHI"))
+              (Block
+                 (CodeBlock
+                    [ Array
+                        [ Block
+                            (Content
+                               [ Code
+                                   "test/typ/layout/stack-2-00.typ"
+                                   ( line 6 , column 30 )
+                                   (Ident (Identifier "c"))
+                               ])
+                        ]
+                    ])))
+       ])
+, ParBreak
+, Text "Hello"
+, SoftBreak
+, Code
+    "test/typ/layout/stack-2-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 2.0 Fr)) ])
+, SoftBreak
+, Text "from"
+, Space
+, Code
+    "test/typ/layout/stack-2-00.typ"
+    ( line 11 , column 7 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "the"
+, Space
+, Code
+    "test/typ/layout/stack-2-00.typ"
+    ( line 11 , column 19 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, Space
+, Text "wonderful"
+, SoftBreak
+, Code
+    "test/typ/layout/stack-2-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+, SoftBreak
+, Text "World!"
+, Space
+, Text "\127757"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  stack(children: (text(body: [A]), 
+                   text(body: [B]), 
+                   text(body: [C]), 
+                   text(body: [D]), 
+                   text(body: [E]), 
+                   text(body: [F]), 
+                   text(body: [G]), 
+                   text(body: [H]), 
+                   text(body: [I])), 
+        dir: ltr, 
+        spacing: 1.0fr), 
+  parbreak(), 
+  text(body: [Hello
+]), 
+  v(amount: 2.0fr), 
+  text(body: [
+from ]), 
+  h(amount: 1.0fr), 
+  text(body: [ the ]), 
+  h(amount: 1.0fr), 
+  text(body: [ wonderful
+]), 
+  v(amount: 1.0fr), 
+  text(body: [
+World! 🌍]), 
+  parbreak() }
diff --git a/test/out/layout/stack-2-01.out b/test/out/layout/stack-2-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/stack-2-01.out
@@ -0,0 +1,104 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/stack-2-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/stack-2-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/stack-2-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/stack-2-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-2-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Ident (Identifier "white")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/stack-2-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/layout/stack-2-01.typ"
+               ( line 5 , column 12 )
+               (FuncCall
+                  (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+           , SoftBreak
+           , Code
+               "test/typ/layout/stack-2-01.typ"
+               ( line 6 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ])
+           , Space
+           , Text "Hi"
+           , Space
+           , Text "you!"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       color: rgb(100%,100%,100%,100%)), 
+  rect(body: { text(body: [
+], 
+                    color: rgb(100%,100%,100%,100%)), 
+               v(amount: 1.0fr), 
+               text(body: [
+], 
+                    color: rgb(100%,100%,100%,100%)), 
+               h(amount: 1.0fr), 
+               text(body: [ Hi you!], 
+                    color: rgb(100%,100%,100%,100%)), 
+               parbreak() }, 
+       fill: rgb(100%,25%,21%,100%)), 
+  parbreak() }
diff --git a/test/out/layout/table-00.out b/test/out/layout/table-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/table-00.out
@@ -0,0 +1,140 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/table-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/table-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/table-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/table-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 70.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/table-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "fill")
+           (FuncExpr
+              [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+              (If
+                 [ ( FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "even")) (Ident (Identifier "calc")))
+                       [ NormalArg
+                           (Plus (Ident (Identifier "x")) (Ident (Identifier "y")))
+                       ]
+                   , Block
+                       (CodeBlock
+                          [ FuncCall
+                              (Ident (Identifier "rgb")) [ NormalArg (Literal (String "aaa")) ]
+                          ])
+                   )
+                 ]))
+       ])
+, ParBreak
+, Code
+    "test/typ/layout/table-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Times (Array [ Literal (Numeric 1.0 Fr) ]) (Literal (Int 3)))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus
+              (Literal (Numeric 2.0 Pt))
+              (FuncCall
+                 (Ident (Identifier "rgb")) [ NormalArg (Literal (String "333")) ]))
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Block (Content [ Text "B" ]))
+       , NormalArg (Block (Content [ Text "C" ]))
+       , NormalArg (Block (Content []))
+       , NormalArg (Block (Content []))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "D"
+                 , Space
+                 , HardBreak
+                 , Text "E"
+                 , Space
+                 , HardBreak
+                 , Text "F"
+                 , Space
+                 , HardBreak
+                 , HardBreak
+                 , HardBreak
+                 , Text "G"
+                 ]))
+       , NormalArg (Block (Content [ Text "H" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  table(children: (text(body: [A]), 
+                   text(body: [B]), 
+                   text(body: [C]), 
+                   {  }, 
+                   {  }, 
+                   { text(body: [D ]), 
+                     linebreak(), 
+                     text(body: [E ]), 
+                     linebreak(), 
+                     text(body: [F ]), 
+                     linebreak(), 
+                     linebreak(), 
+                     linebreak(), 
+                     text(body: [G]) }, 
+                   text(body: [H])), 
+        columns: (1.0fr, 
+                  1.0fr, 
+                  1.0fr), 
+        fill: , 
+        stroke: (thickness: 2.0pt,
+                 color: rgb(1%,1%,1%,100%))), 
+  parbreak() }
diff --git a/test/out/layout/table-01.out b/test/out/layout/table-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/table-01.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/table-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/table-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/table-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/layout/table-01.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 3))
+       , KeyValArg (Identifier "stroke") (Literal None)
+       , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Block (Content [ Text "B" ]))
+       , NormalArg (Block (Content [ Text "C" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  table(children: (text(body: [A]), 
+                   text(body: [B]), 
+                   text(body: [C])), 
+        columns: 3, 
+        fill: rgb(18%,80%,25%,100%), 
+        stroke: none), 
+  parbreak() }
diff --git a/test/out/layout/table-02.out b/test/out/layout/table-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/table-02.out
@@ -0,0 +1,116 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/table-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/table-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/table-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/table-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array
+              [ Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              ])
+       , KeyValArg
+           (Identifier "align")
+           (Array
+              [ Ident (Identifier "left")
+              , Ident (Identifier "center")
+              , Ident (Identifier "right")
+              ])
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Block (Content [ Text "B" ]))
+       , NormalArg (Block (Content [ Text "C" ]))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/layout/table-02.typ"
+    ( line 10 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center")) ])
+, SoftBreak
+, Code
+    "test/typ/layout/table-02.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array
+              [ Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              ])
+       , KeyValArg (Identifier "align") (Array [])
+       , NormalArg (Block (Content [ Text "A" ]))
+       , NormalArg (Block (Content [ Text "B" ]))
+       , NormalArg (Block (Content [ Text "C" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  table(align: (left, 
+                center, 
+                right), 
+        children: (text(body: [A]), 
+                   text(body: [B]), 
+                   text(body: [C])), 
+        columns: (1.0fr, 
+                  1.0fr, 
+                  1.0fr)), 
+  parbreak(), 
+  text(body: [
+]), 
+  table(align: (), 
+        children: (text(body: [A]), 
+                   text(body: [B]), 
+                   text(body: [C])), 
+        columns: (1.0fr, 
+                  1.0fr, 
+                  1.0fr)), 
+  parbreak() }
diff --git a/test/out/layout/table-03.out b/test/out/layout/table-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/table-03.out
@@ -0,0 +1,53 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/table-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/table-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/table-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/table-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall (Ident (Identifier "table")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  table(children: ()), 
+  parbreak() }
diff --git a/test/out/layout/table-04.out b/test/out/layout/table-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/table-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/terms-00.out b/test/out/layout/terms-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/terms-00.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/terms-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/terms-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/terms-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/terms-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "terms"))
+       [ NormalArg
+           (Array
+              [ Block (Content [ Text "One" ])
+              , Block (Content [ Text "First" ])
+              ])
+       , NormalArg
+           (Array
+              [ Block (Content [ Text "Two" ])
+              , Block (Content [ Text "Second" ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  terms(children: ((text(body: [One]), 
+                    text(body: [First])), 
+                   (text(body: [Two]), 
+                    text(body: [Second])))), 
+  parbreak() }
diff --git a/test/out/layout/terms-01.out b/test/out/layout/terms-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/terms-01.out
@@ -0,0 +1,100 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/terms-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/terms-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/terms-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/terms-01.typ"
+    ( line 3 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "word")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "map"))
+             (FuncCall
+                (FieldAccess
+                   (Ident (Identifier "split"))
+                   (FuncCall
+                      (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 4)) ]))
+                []))
+          [ NormalArg
+              (FuncExpr
+                 [ NormalParam (Identifier "s") ]
+                 (FuncCall
+                    (FieldAccess (Ident (Identifier "trim")) (Ident (Identifier "s")))
+                    [ NormalArg (Literal (String ".")) ]))
+          ])
+       (Block
+          (Content
+             [ SoftBreak
+             , DescListItem
+                 [ Code
+                     "test/typ/layout/terms-01.typ"
+                     ( line 4 , column 6 )
+                     (Ident (Identifier "word"))
+                 ]
+                 [ Text "Latin" , Space , Text "stuff" , Text "." , ParBreak ]
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  terms(children: ((text(body: [Lorem]), 
+                    { text(body: [Latin stuff.]), 
+                      parbreak() }))), 
+  text(body: [
+]), 
+  terms(children: ((text(body: [ipsum]), 
+                    { text(body: [Latin stuff.]), 
+                      parbreak() }))), 
+  text(body: [
+]), 
+  terms(children: ((text(body: [dolor]), 
+                    { text(body: [Latin stuff.]), 
+                      parbreak() }))), 
+  text(body: [
+]), 
+  terms(children: ((text(body: [sit]), 
+                    { text(body: [Latin stuff.]), 
+                      parbreak() }))), 
+  parbreak() }
diff --git a/test/out/layout/terms-02.out b/test/out/layout/terms-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/terms-02.out
@@ -0,0 +1,94 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/terms-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/terms-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/terms-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/terms-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+, ParBreak
+, DescListItem
+    [ Text "Fruit" ]
+    [ Text "A"
+    , Space
+    , Text "tasty,"
+    , Space
+    , Text "edible"
+    , Space
+    , Text "thing"
+    , Text "."
+    ]
+, SoftBreak
+, DescListItem
+    [ Text "Veggie" ]
+    [ SoftBreak
+    , Text "An"
+    , Space
+    , Text "important"
+    , Space
+    , Text "energy"
+    , Space
+    , Text "source"
+    , SoftBreak
+    , Text "for"
+    , Space
+    , Text "vegetarians"
+    , Text "."
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  terms(children: ((text(body: [Fruit], 
+                         size: 8.0pt), 
+                    text(body: [A tasty, edible thing.], 
+                         size: 8.0pt)), 
+                   (text(body: [Veggie], 
+                         size: 8.0pt), 
+                    { text(body: [
+An important energy source
+for vegetarians.], 
+                           size: 8.0pt), 
+                      parbreak() }))) }
diff --git a/test/out/layout/terms-03.out b/test/out/layout/terms-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/terms-03.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/terms-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/terms-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/terms-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/terms-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+, SoftBreak
+, DescListItem
+    [ Text "First" , Space , Text "list" ]
+    [ Code
+        "test/typ/layout/terms-03.typ"
+        ( line 4 , column 16 )
+        (FuncCall
+           (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 6)) ])
+    , SoftBreak
+    ]
+, SoftBreak
+, Code
+    "test/typ/layout/terms-03.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "terms"))
+       [ KeyValArg
+           (Identifier "hanging-indent") (Literal (Numeric 30.0 Pt))
+       ])
+, SoftBreak
+, DescListItem
+    [ Text "Second" , Space , Text "list" ]
+    [ Code
+        "test/typ/layout/terms-03.typ"
+        ( line 7 , column 17 )
+        (FuncCall
+           (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 5)) ])
+    , ParBreak
+    ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], size: 8.0pt), 
+  terms(children: ((text(body: [First list], 
+                         size: 8.0pt), 
+                    { text(body: [Lorem ipsum dolor sit amet, consectetur], 
+                           size: 8.0pt), 
+                      text(body: [
+], 
+                           size: 8.0pt) }))), 
+  text(body: [
+], size: 8.0pt), 
+  terms(children: ((text(body: [Second list], 
+                         size: 8.0pt), 
+                    { text(body: [Lorem ipsum dolor sit amet,], 
+                           size: 8.0pt), 
+                      parbreak() })), 
+        hanging-indent: 30.0pt) }
diff --git a/test/out/layout/terms-04.out b/test/out/layout/terms-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/terms-04.out
@@ -0,0 +1,100 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/terms-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/terms-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/terms-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/terms-04.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "terms")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (FuncCall
+             (Ident (Identifier "table"))
+             [ KeyValArg (Identifier "columns") (Literal (Int 2))
+             , KeyValArg (Identifier "inset") (Literal (Numeric 3.0 Pt))
+             , SpreadArg
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "flatten"))
+                       (FuncCall
+                          (FieldAccess
+                             (Ident (Identifier "map"))
+                             (FieldAccess
+                                (Ident (Identifier "children")) (Ident (Identifier "it"))))
+                          [ NormalArg
+                              (FuncExpr
+                                 [ NormalParam (Identifier "v") ]
+                                 (Array
+                                    [ FuncCall
+                                        (Ident (Identifier "emph"))
+                                        [ NormalArg
+                                            (FieldAccess
+                                               (Ident (Identifier "term")) (Ident (Identifier "v")))
+                                        ]
+                                    , FieldAccess
+                                        (Ident (Identifier "description")) (Ident (Identifier "v"))
+                                    ]))
+                          ]))
+                    [])
+             ])))
+, ParBreak
+, DescListItem [ Text "A" ] [ Text "One" , Space , Text "letter" ]
+, SoftBreak
+, DescListItem
+    [ Text "BB" ] [ Text "Two" , Space , Text "letters" ]
+, SoftBreak
+, DescListItem
+    [ Text "CCC" ] [ Text "Three" , Space , Text "letters" , ParBreak ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  table(children: (emph(body: text(body: [A])), 
+                   text(body: [One letter]), 
+                   emph(body: text(body: [BB])), 
+                   text(body: [Two letters]), 
+                   emph(body: text(body: [CCC])), 
+                   { text(body: [Three letters]), 
+                     parbreak() }), 
+        columns: 2, 
+        inset: 3.0pt) }
diff --git a/test/out/layout/terms-05.out b/test/out/layout/terms-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/terms-05.out
@@ -0,0 +1,61 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/terms-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/terms-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/terms-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, DescListItem [ Text "Term" ] []
+, SoftBreak
+, Text "Not"
+, Space
+, Text "in"
+, Space
+, Text "list"
+, SoftBreak
+, Text "/"
+, Text "Nope"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  terms(children: ((text(body: [Term]), 
+                    {  }))), 
+  text(body: [Not in list
+/Nope]), 
+  parbreak() }
diff --git a/test/out/layout/terms-06.out b/test/out/layout/terms-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/terms-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/layout/transform-00.out b/test/out/layout/transform-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/transform-00.out
@@ -0,0 +1,214 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/transform-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/transform-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/transform-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/transform-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "size"))) (Literal (Numeric 11.0 Pt)))
+, SoftBreak
+, Code
+    "test/typ/layout/transform-00.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "tex")))
+       (Block
+          (CodeBlock
+             [ Block (Content [ Text "T" ])
+             , FuncCall
+                 (Ident (Identifier "h"))
+                 [ NormalArg
+                     (Times
+                        (Negated (Literal (Float 0.14))) (Ident (Identifier "size")))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "box"))
+                 [ NormalArg
+                     (FuncCall
+                        (Ident (Identifier "move"))
+                        [ KeyValArg
+                            (Identifier "dy")
+                            (Times (Literal (Float 0.22)) (Ident (Identifier "size")))
+                        , BlockArg [ Text "E" ]
+                        ])
+                 ]
+             , FuncCall
+                 (Ident (Identifier "h"))
+                 [ NormalArg
+                     (Times
+                        (Negated (Literal (Float 0.12))) (Ident (Identifier "size")))
+                 ]
+             , Block (Content [ Text "X" ])
+             ])))
+, ParBreak
+, Code
+    "test/typ/layout/transform-00.typ"
+    ( line 12 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "xetex")))
+       (Block
+          (CodeBlock
+             [ Block (Content [ Text "X" ])
+             , FuncCall
+                 (Ident (Identifier "h"))
+                 [ NormalArg
+                     (Times
+                        (Negated (Literal (Float 0.14))) (Ident (Identifier "size")))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "box"))
+                 [ NormalArg
+                     (FuncCall
+                        (Ident (Identifier "scale"))
+                        [ KeyValArg
+                            (Identifier "x") (Negated (Literal (Numeric 100.0 Percent)))
+                        , NormalArg
+                            (FuncCall
+                               (Ident (Identifier "move"))
+                               [ KeyValArg
+                                   (Identifier "dy")
+                                   (Times (Literal (Float 0.26)) (Ident (Identifier "size")))
+                               , BlockArg [ Text "E" ]
+                               ])
+                        ])
+                 ]
+             , FuncCall
+                 (Ident (Identifier "h"))
+                 [ NormalArg
+                     (Times
+                        (Negated (Literal (Float 0.14))) (Ident (Identifier "size")))
+                 ]
+             , Block (Content [ Text "T" ])
+             , FuncCall
+                 (Ident (Identifier "h"))
+                 [ NormalArg
+                     (Times
+                        (Negated (Literal (Float 0.14))) (Ident (Identifier "size")))
+                 ]
+             , FuncCall
+                 (Ident (Identifier "box"))
+                 [ NormalArg
+                     (FuncCall
+                        (Ident (Identifier "move"))
+                        [ KeyValArg
+                            (Identifier "dy")
+                            (Times (Literal (Float 0.26)) (Ident (Identifier "size")))
+                        , BlockArg [ Text "E" ]
+                        ])
+                 ]
+             , FuncCall
+                 (Ident (Identifier "h"))
+                 [ NormalArg
+                     (Times
+                        (Negated (Literal (Float 0.12))) (Ident (Identifier "size")))
+                 ]
+             , Block (Content [ Text "X" ])
+             ])))
+, ParBreak
+, Code
+    "test/typ/layout/transform-00.typ"
+    ( line 24 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "New Computer Modern"))
+       , NormalArg (Ident (Identifier "size"))
+       ])
+, SoftBreak
+, Text "Neither"
+, Space
+, Code
+    "test/typ/layout/transform-00.typ"
+    ( line 25 , column 10 )
+    (Ident (Identifier "tex"))
+, Text ","
+, Space
+, HardBreak
+, Text "nor"
+, Space
+, Code
+    "test/typ/layout/transform-00.typ"
+    ( line 26 , column 6 )
+    (Ident (Identifier "xetex"))
+, Text "!"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [
+Neither ], 
+       font: "New Computer Modern", 
+       size: 11.0pt), 
+  text(body: [T]), 
+  h(amount: -1.54pt), 
+  box(body: move(body: text(body: [E]), 
+                 dy: 2.42pt)), 
+  h(amount: -1.3199999999999998pt), 
+  text(body: [X]), 
+  text(body: [, ], 
+       font: "New Computer Modern", 
+       size: 11.0pt), 
+  linebreak(), 
+  text(body: [nor ], 
+       font: "New Computer Modern", 
+       size: 11.0pt), 
+  text(body: [X]), 
+  h(amount: -1.54pt), 
+  box(body: scale(body: move(body: text(body: [E]), 
+                             dy: 2.8600000000000003pt), 
+                  x: -100%)), 
+  h(amount: -1.54pt), 
+  text(body: [T]), 
+  h(amount: -1.54pt), 
+  box(body: move(body: text(body: [E]), 
+                 dy: 2.8600000000000003pt)), 
+  h(amount: -1.3199999999999998pt), 
+  text(body: [X]), 
+  text(body: [!], 
+       font: "New Computer Modern", 
+       size: 11.0pt), 
+  parbreak() }
diff --git a/test/out/layout/transform-01.out b/test/out/layout/transform-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/transform-01.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/transform-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/transform-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/transform-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/transform-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 80.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/transform-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg
+           (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rotate"))
+              [ NormalArg (Literal (Numeric 20.0 Deg))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "scale"))
+                     [ NormalArg (Literal (Numeric 70.0 Percent))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "image"))
+                            [ NormalArg (Literal (String "test/assets/files/tiger.jpg")) ])
+                     ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  align(alignment: Axes(center, horizon), 
+        body: rotate(angle: 20.0deg, 
+                     body: scale(body: image(path: "test/assets/files/tiger.jpg"), 
+                                 factor: 70%))), 
+  parbreak() }
diff --git a/test/out/layout/transform-02.out b/test/out/layout/transform-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/transform-02.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/transform-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/transform-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/transform-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/transform-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rotate"))
+       [ NormalArg (Literal (Numeric 10.0 Deg))
+       , KeyValArg
+           (Identifier "origin")
+           (Plus (Ident (Identifier "top")) (Ident (Identifier "left")))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  rotate(angle: 10.0deg, 
+         body: image(path: "test/assets/files/tiger.jpg", 
+                     width: 50%), 
+         origin: Axes(left, top)), 
+  parbreak() }
diff --git a/test/out/layout/transform-03.out b/test/out/layout/transform-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/layout/transform-03.out
@@ -0,0 +1,139 @@
+--- parse tree ---
+[ Code
+    "test/typ/layout/transform-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/layout/transform-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/layout/transform-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/layout/transform-03.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "r")))
+       (FuncCall
+          (Ident (Identifier "rect"))
+          [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Pt))
+          , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+          , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/layout/transform-03.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 65.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/layout/transform-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "scale"))
+              [ NormalArg (Ident (Identifier "r"))
+              , KeyValArg (Identifier "x") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "y") (Literal (Numeric 200.0 Percent))
+              , KeyValArg
+                  (Identifier "origin")
+                  (Plus (Ident (Identifier "left")) (Ident (Identifier "top")))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/transform-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "scale"))
+              [ NormalArg (Ident (Identifier "r"))
+              , KeyValArg (Identifier "x") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "origin") (Ident (Identifier "center"))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/layout/transform-03.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "scale"))
+              [ NormalArg (Ident (Identifier "r"))
+              , KeyValArg (Identifier "x") (Literal (Numeric 50.0 Percent))
+              , KeyValArg (Identifier "y") (Literal (Numeric 200.0 Percent))
+              , KeyValArg
+                  (Identifier "origin")
+                  (Plus (Ident (Identifier "right")) (Ident (Identifier "bottom")))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  box(body: scale(body: rect(fill: rgb(100%,25%,21%,100%), 
+                             height: 10.0pt, 
+                             width: 100.0pt), 
+                  origin: Axes(left, top), 
+                  x: 50%, 
+                  y: 200%)), 
+  text(body: [
+]), 
+  box(body: scale(body: rect(fill: rgb(100%,25%,21%,100%), 
+                             height: 10.0pt, 
+                             width: 100.0pt), 
+                  origin: center, 
+                  x: 50%)), 
+  text(body: [
+]), 
+  box(body: scale(body: rect(fill: rgb(100%,25%,21%,100%), 
+                             height: 10.0pt, 
+                             width: 100.0pt), 
+                  origin: Axes(right, bottom), 
+                  x: 50%, 
+                  y: 200%)), 
+  parbreak() }
diff --git a/test/out/math/accent-00.out b/test/out/math/accent-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/accent-00.out
@@ -0,0 +1,155 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/accent-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/accent-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/accent-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Code
+        "test/typ/math/accent-00.typ"
+        ( line 3 , column 2 )
+        (FuncCall (Ident (Identifier "grave")) [ BlockArg [ Text "a" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 3 , column 12 )
+        (FuncCall (Ident (Identifier "acute")) [ BlockArg [ Text "b" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 3 , column 22 )
+        (FuncCall (Ident (Identifier "hat")) [ BlockArg [ Text "f" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 3 , column 30 )
+        (FuncCall
+           (Ident (Identifier "tilde")) [ BlockArg [ Text "\167" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 3 , column 40 )
+        (FuncCall
+           (Ident (Identifier "macron")) [ BlockArg [ Text "\228" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 3 , column 51 )
+        (FuncCall (Ident (Identifier "diaer")) [ BlockArg [ Text "a" ] ])
+    , Text ","
+    , Text "\228"
+    , HardBreak
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 4 , column 2 )
+        (FuncCall (Ident (Identifier "breve")) [ BlockArg [ Text "&" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 4 , column 13 )
+        (FuncCall (Ident (Identifier "dot")) [ BlockArg [ Text "!" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 4 , column 21 )
+        (FuncCall (Ident (Identifier "circle")) [ BlockArg [ Text "a" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 4 , column 32 )
+        (FuncCall (Ident (Identifier "caron")) [ BlockArg [ Text "@" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 4 , column 42 )
+        (FuncCall (Ident (Identifier "arrow")) [ BlockArg [ Text "Z" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-00.typ"
+        ( line 4 , column 52 )
+        (FuncCall
+           (FieldAccess (Ident (Identifier "l")) (Ident (Identifier "arrow")))
+           [ BlockArg [ Text "Z" ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.accent(accent: `, 
+                                    base: text(body: [a])), 
+                        text(body: [,]), 
+                        math.accent(accent: ´, 
+                                    base: text(body: [b])), 
+                        text(body: [,]), 
+                        math.accent(accent: ^, 
+                                    base: text(body: [f])), 
+                        text(body: [,]), 
+                        math.accent(accent: ∼, 
+                                    base: text(body: [§])), 
+                        text(body: [,]), 
+                        math.accent(accent: ¯, 
+                                    base: text(body: [ä])), 
+                        text(body: [,]), 
+                        math.accent(accent: ¨, 
+                                    base: text(body: [a])), 
+                        text(body: [,]), 
+                        text(body: [ä]), 
+                        linebreak(), 
+                        math.accent(accent: ˘, 
+                                    base: text(body: [&])), 
+                        text(body: [,]), 
+                        math.accent(accent: ⋅, 
+                                    base: text(body: [!])), 
+                        text(body: [,]), 
+                        math.accent(accent: ○, 
+                                    base: text(body: [a])), 
+                        text(body: [,]), 
+                        math.accent(accent: ˇ, 
+                                    base: text(body: [@])), 
+                        text(body: [,]), 
+                        math.accent(accent: →, 
+                                    base: text(body: [Z])), 
+                        text(body: [,]), 
+                        math.accent(accent: ←, 
+                                    base: text(body: [Z])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/accent-01.out b/test/out/math/accent-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/accent-01.out
@@ -0,0 +1,125 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/accent-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/accent-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/accent-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Equation
+    True
+    [ Text "x"
+    , MAlignPoint
+    , Text "="
+    , Text "p"
+    , HardBreak
+    , Code
+        "test/typ/math/accent-01.typ"
+        ( line 2 , column 12 )
+        (FuncCall (Ident (Identifier "dot")) [ BlockArg [ Text "x" ] ])
+    , MAlignPoint
+    , Text "="
+    , Text "v"
+    , HardBreak
+    , Code
+        "test/typ/math/accent-01.typ"
+        ( line 2 , column 26 )
+        (FuncCall
+           (FieldAccess
+              (Ident (Identifier "double")) (Ident (Identifier "dot")))
+           [ BlockArg [ Text "x" ] ])
+    , MAlignPoint
+    , Text "="
+    , Text "a"
+    , HardBreak
+    , Code
+        "test/typ/math/accent-01.typ"
+        ( line 2 , column 47 )
+        (FuncCall
+           (FieldAccess
+              (Ident (Identifier "triple")) (Ident (Identifier "dot")))
+           [ BlockArg [ Text "x" ] ])
+    , MAlignPoint
+    , Text "="
+    , Text "j"
+    , HardBreak
+    , Code
+        "test/typ/math/accent-01.typ"
+        ( line 2 , column 68 )
+        (FuncCall
+           (FieldAccess
+              (Ident (Identifier "quad")) (Ident (Identifier "dot")))
+           [ BlockArg [ Text "x" ] ])
+    , MAlignPoint
+    , Text "="
+    , Text "s"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [p]), 
+                        linebreak(), 
+                        math.accent(accent: ⋅, 
+                                    base: text(body: [x])), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [v]), 
+                        linebreak(), 
+                        math.accent(accent: ¨, 
+                                    base: text(body: [x])), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [a]), 
+                        linebreak(), 
+                        math.accent(accent: ⃛, 
+                                    base: text(body: [x])), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [j]), 
+                        linebreak(), 
+                        math.accent(accent: ⃜, 
+                                    base: text(body: [x])), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [s]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/accent-02.out b/test/out/math/accent-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/accent-02.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/accent-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/accent-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/accent-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Code
+        "test/typ/math/accent-02.typ"
+        ( line 3 , column 2 )
+        (FuncCall
+           (Ident (Identifier "accent"))
+           [ BlockArg [ Text "\246" ] , BlockArg [ Text "." ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-02.typ"
+        ( line 3 , column 16 )
+        (FuncCall
+           (Ident (Identifier "accent"))
+           [ BlockArg [ Text "v" ] , BlockArg [ Text "\8592" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-02.typ"
+        ( line 3 , column 31 )
+        (FuncCall
+           (Ident (Identifier "accent"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/accent-02.typ"
+                   ( line 3 , column 38 )
+                   (Ident (Identifier "ZZ"))
+               ]
+           , BlockArg [ Text "\771" ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.accent(accent: text(body: [.]), 
+                                    base: text(body: [ö])), 
+                        text(body: [,]), 
+                        math.accent(accent: text(body: [←]), 
+                                    base: text(body: [v])), 
+                        text(body: [,]), 
+                        math.accent(accent: text(body: [̃]), 
+                                    base: text(body: [ℤ])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/accent-03.out b/test/out/math/accent-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/accent-03.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/accent-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/accent-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/accent-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Code
+        "test/typ/math/accent-03.typ"
+        ( line 3 , column 2 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/accent-03.typ"
+                   ( line 3 , column 7 )
+                   (FuncCall (Ident (Identifier "tilde")) [ BlockArg [ Text "T" ] ])
+               ]
+           ])
+    , Text "+"
+    , MFrac
+        (Code
+           "test/typ/math/accent-03.typ"
+           ( line 3 , column 19 )
+           (FuncCall (Ident (Identifier "hat")) [ BlockArg [ Text "f" ] ]))
+        (Code
+           "test/typ/math/accent-03.typ"
+           ( line 3 , column 26 )
+           (FuncCall (Ident (Identifier "hat")) [ BlockArg [ Text "g" ] ]))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.sqrt(radicand: math.accent(accent: ∼, 
+                                                        base: text(body: [T]))), 
+                        text(body: [+]), 
+                        math.frac(denom: math.accent(accent: ^, 
+                                                     base: text(body: [g])), 
+                                  num: math.accent(accent: ^, 
+                                                   base: text(body: [f]))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/accent-04.out b/test/out/math/accent-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/accent-04.out
@@ -0,0 +1,79 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/accent-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/accent-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/accent-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Code
+        "test/typ/math/accent-04.typ"
+        ( line 3 , column 2 )
+        (FuncCall
+           (Ident (Identifier "arrow"))
+           [ BlockArg [ Text "ABC " , Text "+" , Text "d" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/accent-04.typ"
+        ( line 3 , column 20 )
+        (FuncCall
+           (Ident (Identifier "tilde"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/accent-04.typ"
+                   ( line 3 , column 26 )
+                   (Ident (Identifier "sum"))
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.accent(accent: →, 
+                                    base: { text(body: [ABC ]), 
+                                            text(body: [+]), 
+                                            text(body: [d]) }), 
+                        text(body: [,]), 
+                        math.accent(accent: ∼, 
+                                    base: text(body: [∑])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/accent-05.out b/test/out/math/accent-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/accent-05.out
@@ -0,0 +1,92 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/accent-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/accent-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/accent-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ MAttach Nothing (Just (Text "x")) (Text "A")
+    , Text "\8800"
+    , MAttach
+        Nothing
+        (Just (Text "x"))
+        (Code
+           "test/typ/math/accent-05.typ"
+           ( line 3 , column 9 )
+           (FuncCall (Ident (Identifier "hat")) [ BlockArg [ Text "A" ] ]))
+    , Text "\8800"
+    , MAttach
+        Nothing
+        (Just (Text "x"))
+        (Code
+           "test/typ/math/accent-05.typ"
+           ( line 3 , column 21 )
+           (FuncCall
+              (Ident (Identifier "hat"))
+              [ BlockArg
+                  [ Code
+                      "test/typ/math/accent-05.typ"
+                      ( line 3 , column 25 )
+                      (FuncCall (Ident (Identifier "hat")) [ BlockArg [ Text "A" ] ])
+                  ]
+              ]))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.attach(b: none, 
+                                    base: text(body: [A]), 
+                                    t: text(body: [x])), 
+                        text(body: [≠]), 
+                        math.attach(b: none, 
+                                    base: math.accent(accent: ^, 
+                                                      base: text(body: [A])), 
+                                    t: text(body: [x])), 
+                        text(body: [≠]), 
+                        math.attach(b: none, 
+                                    base: math.accent(accent: ^, 
+                                                      base: math.accent(accent: ^, 
+                                                                        base: text(body: [A]))), 
+                                    t: text(body: [x])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/accent-06.out b/test/out/math/accent-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/accent-06.out
@@ -0,0 +1,109 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/accent-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/accent-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/accent-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/accent-06.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "tilde"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/accent-06.typ"
+                   ( line 3 , column 9 )
+                   (Ident (Identifier "integral"))
+               ]
+           ])
+    , Text ","
+    , MAttach
+        (Just (Text "a"))
+        (Just (Text "b"))
+        (Code
+           "test/typ/math/accent-06.typ"
+           ( line 3 , column 20 )
+           (FuncCall
+              (Ident (Identifier "tilde"))
+              [ BlockArg
+                  [ Code
+                      "test/typ/math/accent-06.typ"
+                      ( line 3 , column 26 )
+                      (Ident (Identifier "integral"))
+                  ]
+              ]))
+    , Text ","
+    , Code
+        "test/typ/math/accent-06.typ"
+        ( line 3 , column 41 )
+        (FuncCall
+           (Ident (Identifier "tilde"))
+           [ BlockArg
+               [ MAttach
+                   (Just (Text "a"))
+                   (Just (Text "b"))
+                   (Code
+                      "test/typ/math/accent-06.typ"
+                      ( line 3 , column 47 )
+                      (Ident (Identifier "integral")))
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.accent(accent: ∼, 
+                                    base: text(body: [∫])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [a]), 
+                                    base: math.accent(accent: ∼, 
+                                                      base: text(body: [∫])), 
+                                    t: text(body: [b])), 
+                        text(body: [,]), 
+                        math.accent(accent: ∼, 
+                                    base: math.attach(b: text(body: [a]), 
+                                                      base: text(body: [∫]), 
+                                                      t: text(body: [b]))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/alignment-00.out b/test/out/math/alignment-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/alignment-00.out
@@ -0,0 +1,118 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/alignment-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/alignment-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/alignment-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/alignment-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 225.0 Pt)) ])
+, SoftBreak
+, Equation
+    True
+    [ Text " a "
+    , MAlignPoint
+    , Text "="
+    , Text "c"
+    , HardBreak
+    , MAlignPoint
+    , Text "="
+    , Text "c"
+    , Text "+"
+    , Text "1"
+    , MAlignPoint
+    , Text " By definition "
+    , HardBreak
+    , MAlignPoint
+    , Text "="
+    , Text "d"
+    , Text "+"
+    , Text "100"
+    , Text "+"
+    , Text "1000"
+    , HardBreak
+    , MAlignPoint
+    , Text "="
+    , Text "x"
+    , MAlignPoint
+    , MAlignPoint
+    , Text " Even longer "
+    , HardBreak
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [ a ]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [c]), 
+                        linebreak(), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [c]), 
+                        text(body: [+]), 
+                        text(body: [1]), 
+                        math.alignpoint(), 
+                        text(body: [ By definition ]), 
+                        linebreak(), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [d]), 
+                        text(body: [+]), 
+                        text(body: [100]), 
+                        text(body: [+]), 
+                        text(body: [1000]), 
+                        linebreak(), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [x]), 
+                        math.alignpoint(), 
+                        math.alignpoint(), 
+                        text(body: [ Even longer ]), 
+                        linebreak() }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/alignment-01.out b/test/out/math/alignment-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/alignment-01.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/alignment-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/alignment-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/alignment-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAlignPoint
+    , Text " right "
+    , HardBreak
+    , Text "a very long line "
+    , HardBreak
+    , Text "left "
+    , HardBreak
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.alignpoint(), 
+                        text(body: [ right ]), 
+                        linebreak(), 
+                        text(body: [a very long line ]), 
+                        linebreak(), 
+                        text(body: [left ]), 
+                        linebreak() }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/alignment-02.out b/test/out/math/alignment-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/alignment-02.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/alignment-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/alignment-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/alignment-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text " right "
+    , HardBreak
+    , Text "a very long line "
+    , HardBreak
+    , Text "left "
+    , HardBreak
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [ right ]), 
+                        linebreak(), 
+                        text(body: [a very long line ]), 
+                        linebreak(), 
+                        text(body: [left ]), 
+                        linebreak() }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/alignment-03.out b/test/out/math/alignment-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/alignment-03.out
@@ -0,0 +1,96 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/alignment-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/alignment-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/alignment-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "a"
+    , MAlignPoint
+    , Text "="
+    , Text "b"
+    , MAlignPoint
+    , Code
+        "test/typ/math/alignment-03.typ"
+        ( line 4 , column 9 )
+        (Ident (Identifier "quad"))
+    , Text "c"
+    , MAlignPoint
+    , Text "="
+    , Text "d"
+    , HardBreak
+    , Text "e"
+    , MAlignPoint
+    , Text "="
+    , Text "f"
+    , MAlignPoint
+    , Text "g"
+    , MAlignPoint
+    , Text "="
+    , Text "h"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [a]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [b]), 
+                        math.alignpoint(), 
+                        text(body: [ ]), 
+                        text(body: [c]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [d]), 
+                        linebreak(), 
+                        text(body: [e]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [f]), 
+                        math.alignpoint(), 
+                        text(body: [g]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [h]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-00.out b/test/out/math/attach-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-00.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ MAttach (Just (Text "x")) Nothing (Text "f")
+    , Text "+"
+    , MAttach Nothing (Just (Text "b")) (Text "t")
+    , Text "+"
+    , MAttach (Just (Text "1")) (Just (Text "2")) (Text "V")
+    , Text "+"
+    , Code
+        "test/typ/math/attach-00.typ"
+        ( line 3 , column 22 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "A" ]
+           , KeyValArg
+               (Identifier "t")
+               (Block
+                  (Content
+                     [ Code
+                         "test/typ/math/attach-00.typ"
+                         ( line 3 , column 35 )
+                         (Ident (Identifier "alpha"))
+                     ]))
+           , KeyValArg
+               (Identifier "b")
+               (Block
+                  (Content
+                     [ Code
+                         "test/typ/math/attach-00.typ"
+                         ( line 3 , column 45 )
+                         (Ident (Identifier "beta"))
+                     ]))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.attach(b: text(body: [x]), 
+                                    base: text(body: [f]), 
+                                    t: none), 
+                        text(body: [+]), 
+                        math.attach(b: none, 
+                                    base: text(body: [t]), 
+                                    t: text(body: [b])), 
+                        text(body: [+]), 
+                        math.attach(b: text(body: [1]), 
+                                    base: text(body: [V]), 
+                                    t: text(body: [2])), 
+                        text(body: [+]), 
+                        math.attach(b: text(body: [β]), 
+                                    base: text(body: [A]), 
+                                    t: text(body: [α])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-01.out b/test/out/math/attach-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-01.out
@@ -0,0 +1,127 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/attach-01.typ"
+        ( line 5 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-01.typ"
+                   ( line 5 , column 8 )
+                   (FuncCall (Ident (Identifier "upright")) [ BlockArg [ Text "O" ] ])
+               ]
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "8" ]))
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "16" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "2" ]))
+           , KeyValArg
+               (Identifier "tr") (Block (Content [ Text "2" , Text "-" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-01.typ"
+        ( line 6 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "Pb" ]
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "82" ]))
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "207" ]))
+           ])
+    , Text "+"
+    , Code
+        "test/typ/math/attach-01.typ"
+        ( line 6 , column 33 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-01.typ"
+                   ( line 6 , column 40 )
+                   (FuncCall (Ident (Identifier "upright")) [ BlockArg [ Text "e" ] ])
+               ]
+           , KeyValArg
+               (Identifier "bl") (Block (Content [ Text "-" , Text "1" ]))
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "0" ]))
+           ])
+    , Text "+"
+    , MAttach
+        (Just (Text "e"))
+        Nothing
+        (Code
+           "test/typ/math/attach-01.typ"
+           ( line 6 , column 69 )
+           (FuncCall (Ident (Identifier "macron")) [ BlockArg [ Text "v" ] ]))
+    , HardBreak
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(base: math.upright(body: text(body: [O])), 
+                                    bl: text(body: [8]), 
+                                    br: text(body: [2]), 
+                                    tl: text(body: [16]), 
+                                    tr: { text(body: [2]), 
+                                          text(body: [-]) }), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [Pb]), 
+                                    bl: text(body: [82]), 
+                                    tl: text(body: [207])), 
+                        text(body: [+]), 
+                        math.attach(base: math.upright(body: text(body: [e])), 
+                                    bl: { text(body: [-]), 
+                                          text(body: [1]) }, 
+                                    tl: text(body: [0])), 
+                        text(body: [+]), 
+                        math.attach(b: text(body: [e]), 
+                                    base: math.accent(accent: ¯, 
+                                                      base: text(body: [v])), 
+                                    t: none), 
+                        linebreak() }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-02.out b/test/out/math/attach-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-02.out
@@ -0,0 +1,471 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/attach-02.typ"
+        ( line 4 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 4 , column 21 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 4 , column 41 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 5 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           ])
+    , Text ","
+    , MAttach
+        Nothing
+        (Just (Text "t"))
+        (Code
+           "test/typ/math/attach-02.typ"
+           ( line 5 , column 21 )
+           (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ]))
+    , Text ","
+    , MAttach
+        (Just (Text "b"))
+        Nothing
+        (Code
+           "test/typ/math/attach-02.typ"
+           ( line 5 , column 41 )
+           (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ]))
+    , HardBreak
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 7 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 8 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 9 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 10 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 10 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 11 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 12 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 12 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           ])
+    , HardBreak
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 14 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 15 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 15 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 16 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 16 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 17 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 18 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 18 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 19 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 19 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "u" ]))
+           ])
+    , Text ","
+    , MAttach
+        (Just (Text "b"))
+        Nothing
+        (MAttach
+           Nothing
+           (Just (Text "t"))
+           (Code
+              "test/typ/math/attach-02.typ"
+              ( line 20 , column 1 )
+              (FuncCall
+                 (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])))
+    , HardBreak
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 22 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 23 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 23 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 24 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 24 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 25 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 25 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 26 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-02.typ"
+                   ( line 26 , column 8 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "a" ] ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-02.typ"
+        ( line 27 , column 1 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "a" ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "u" ]))
+           , KeyValArg (Identifier "t") (Block (Content [ Text "t" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "v" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "x" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "y" ]))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(base: text(body: [a]), 
+                                    tl: text(body: [u])), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [a]), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [a]), 
+                                    bl: text(body: [x])), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [a]), 
+                                    br: text(body: [y])), 
+                        text(body: [,]), 
+                        math.attach(b: none, 
+                                    base: math.limits(body: text(body: [a])), 
+                                    t: text(body: [t])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    t: none), 
+                        linebreak(), 
+                        math.attach(base: text(body: [a]), 
+                                    t: text(body: [t]), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [a]), 
+                                    br: text(body: [y]), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: text(body: [a]), 
+                                    br: text(body: [y])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    bl: text(body: [x])), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [a]), 
+                                    bl: text(body: [x]), 
+                                    tl: text(body: [u])), 
+                        text(body: [,]), 
+                        math.attach(base: math.limits(body: text(body: [a])), 
+                                    t: text(body: [t]), 
+                                    tl: text(body: [u])), 
+                        linebreak(), 
+                        math.attach(base: text(body: [a]), 
+                                    tl: text(body: [u]), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(base: math.limits(body: text(body: [a])), 
+                                    br: text(body: [y]), 
+                                    t: text(body: [t])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [a]), 
+                                    bl: text(body: [x]), 
+                                    br: text(body: [y])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    tl: text(body: [u])), 
+                        text(body: [,]), 
+                        math.attach(base: math.limits(body: text(body: [a])), 
+                                    bl: text(body: [u]), 
+                                    t: text(body: [t])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.attach(b: none, 
+                                                      base: math.limits(body: text(body: [a])), 
+                                                      t: text(body: [t])), 
+                                    t: none), 
+                        linebreak(), 
+                        math.attach(base: text(body: [a]), 
+                                    bl: text(body: [x]), 
+                                    br: text(body: [y]), 
+                                    tl: text(body: [u]), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    bl: text(body: [x]), 
+                                    br: text(body: [y]), 
+                                    t: text(body: [t])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    t: text(body: [t]), 
+                                    tl: text(body: [u]), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    bl: text(body: [x]), 
+                                    t: text(body: [t]), 
+                                    tl: text(body: [u])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [a])), 
+                                    br: text(body: [y]), 
+                                    t: text(body: [t]), 
+                                    tr: text(body: [v])), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: text(body: [a]), 
+                                    bl: text(body: [x]), 
+                                    br: text(body: [y]), 
+                                    t: text(body: [t]), 
+                                    tl: text(body: [u]), 
+                                    tr: text(body: [v])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-03.out b/test/out/math/attach-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-03.out
@@ -0,0 +1,163 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ MGroup
+        Nothing
+        Nothing
+        [ MAttach
+            (Just (Text "1"))
+            Nothing
+            (Code
+               "test/typ/math/attach-03.typ"
+               ( line 3 , column 2 )
+               (Ident (Identifier "pi")))
+        , MGroup (Just "(") (Just ")") [ Text "Y" ]
+        ]
+    , Text ","
+    , MGroup
+        Nothing
+        Nothing
+        [ MAttach (Just (Text "f")) Nothing (Text "a")
+        , MGroup (Just "(") (Just ")") [ Text "x" ]
+        ]
+    , Text ","
+    , MAttach
+        Nothing
+        (Just
+           (Code
+              "test/typ/math/attach-03.typ"
+              ( line 3 , column 21 )
+              (FuncCall (Ident (Identifier "zeta")) [ BlockArg [ Text "x" ] ])))
+        (Text "a")
+    , HardBreak
+    , MAttach
+        Nothing
+        (Just
+           (Code
+              "test/typ/math/attach-03.typ"
+              ( line 4 , column 4 )
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "eq")) (Ident (Identifier "subset")))
+                 [ BlockArg [ Text "x" ] ])))
+        (Text "a")
+    , Text ","
+    , MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Code
+                  "test/typ/math/attach-03.typ"
+                  ( line 4 , column 21 )
+                  (FuncCall (Ident (Identifier "zeta")) [ BlockArg [ Text "x" ] ])
+              ]))
+        Nothing
+        (Text "a")
+    , Text ","
+    , MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ MGroup
+                  Nothing
+                  Nothing
+                  [ Text "1" , MGroup (Just "(") (Just ")") [ Text "Y" ] ]
+              ]))
+        Nothing
+        (Code
+           "test/typ/math/attach-03.typ"
+           ( line 4 , column 31 )
+           (Ident (Identifier "pi")))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.attach(b: text(body: [1]), 
+                                    base: text(body: [π]), 
+                                    t: none), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [Y]), 
+                                         [)] })), 
+                        text(body: [,]), 
+                        math.attach(b: text(body: [f]), 
+                                    base: text(body: [a]), 
+                                    t: none), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         [)] })), 
+                        text(body: [,]), 
+                        math.attach(b: none, 
+                                    base: text(body: [a]), 
+                                    t: { text(body: [ζ]), 
+                                         text(body: [(]), 
+                                         text(body: [x]), 
+                                         text(body: [)]) }), 
+                        linebreak(), 
+                        math.attach(b: none, 
+                                    base: text(body: [a]), 
+                                    t: { text(body: [⊆]), 
+                                         text(body: [(]), 
+                                         text(body: [x]), 
+                                         text(body: [)]) }), 
+                        text(body: [,]), 
+                        math.attach(b: { text(body: [ζ]), 
+                                         text(body: [(]), 
+                                         text(body: [x]), 
+                                         text(body: [)]) }, 
+                                    base: text(body: [a]), 
+                                    t: none), 
+                        text(body: [,]), 
+                        math.attach(b: { text(body: [1]), 
+                                         math.lr(body: ({ [(], 
+                                                          text(body: [Y]), 
+                                                          [)] })) }, 
+                                    base: text(body: [π]), 
+                                    t: none) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-04.out b/test/out/math/attach-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-04.out
@@ -0,0 +1,322 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MFrac
+        (Text "1")
+        (MGroup
+           Nothing
+           Nothing
+           [ MAttach
+               Nothing
+               (Just (Text "5"))
+               (MAttach
+                  Nothing
+                  (Just (Text "4"))
+                  (MAttach
+                     Nothing
+                     (Just (Text "3"))
+                     (MAttach Nothing (Just (Text "2")) (Text "V"))))
+           ])
+    , Text ","
+    , MFrac
+        (Text "1")
+        (Code
+           "test/typ/math/attach-04.typ"
+           ( line 4 , column 5 )
+           (FuncCall
+              (Ident (Identifier "attach"))
+              [ BlockArg [ Text "V" ]
+              , KeyValArg
+                  (Identifier "tl")
+                  (Block
+                     (Content
+                        [ Code
+                            "test/typ/math/attach-04.typ"
+                            ( line 4 , column 19 )
+                            (FuncCall
+                               (Ident (Identifier "attach"))
+                               [ BlockArg [ Text "2" ]
+                               , KeyValArg
+                                   (Identifier "tl")
+                                   (Block
+                                      (Content
+                                         [ Code
+                                             "test/typ/math/attach-04.typ"
+                                             ( line 4 , column 33 )
+                                             (FuncCall
+                                                (Ident (Identifier "attach"))
+                                                [ BlockArg [ Text "3" ]
+                                                , KeyValArg
+                                                    (Identifier "tl")
+                                                    (Block
+                                                       (Content
+                                                          [ Code
+                                                              "test/typ/math/attach-04.typ"
+                                                              ( line 4 , column 47 )
+                                                              (FuncCall
+                                                                 (Ident (Identifier "attach"))
+                                                                 [ BlockArg [ Text "4" ]
+                                                                 , KeyValArg
+                                                                     (Identifier "tl")
+                                                                     (Block (Content [ Text "5" ]))
+                                                                 ])
+                                                          ]))
+                                                ])
+                                         ]))
+                               ])
+                        ]))
+              ]))
+    , Text ","
+    , Code
+        "test/typ/math/attach-04.typ"
+        ( line 5 , column 3 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-04.typ"
+                   ( line 5 , column 10 )
+                   (Ident (Identifier "Omega"))
+               ]
+           , KeyValArg
+               (Identifier "tl")
+               (Block
+                  (Content
+                     [ Code
+                         "test/typ/math/attach-04.typ"
+                         ( line 6 , column 9 )
+                         (FuncCall
+                            (Ident (Identifier "attach"))
+                            [ BlockArg [ Text "2" ]
+                            , KeyValArg
+                                (Identifier "tl")
+                                (Block
+                                   (Content
+                                      [ Code
+                                          "test/typ/math/attach-04.typ"
+                                          ( line 6 , column 23 )
+                                          (FuncCall
+                                             (Ident (Identifier "attach"))
+                                             [ BlockArg [ Text "3" ]
+                                             , KeyValArg
+                                                 (Identifier "tl")
+                                                 (Block
+                                                    (Content
+                                                       [ Code
+                                                           "test/typ/math/attach-04.typ"
+                                                           ( line 6 , column 37 )
+                                                           (FuncCall
+                                                              (Ident (Identifier "attach"))
+                                                              [ BlockArg [ Text "4" ]
+                                                              , KeyValArg
+                                                                  (Identifier "tl")
+                                                                  (Block (Content [ Text "5" ]))
+                                                              ])
+                                                       ]))
+                                             ])
+                                      ]))
+                            ])
+                     ]))
+           , KeyValArg
+               (Identifier "tr")
+               (Block
+                  (Content
+                     [ Code
+                         "test/typ/math/attach-04.typ"
+                         ( line 7 , column 9 )
+                         (FuncCall
+                            (Ident (Identifier "attach"))
+                            [ BlockArg [ Text "2" ]
+                            , KeyValArg
+                                (Identifier "tr")
+                                (Block
+                                   (Content
+                                      [ Code
+                                          "test/typ/math/attach-04.typ"
+                                          ( line 7 , column 23 )
+                                          (FuncCall
+                                             (Ident (Identifier "attach"))
+                                             [ BlockArg [ Text "3" ]
+                                             , KeyValArg
+                                                 (Identifier "tr")
+                                                 (Block
+                                                    (Content
+                                                       [ Code
+                                                           "test/typ/math/attach-04.typ"
+                                                           ( line 7 , column 37 )
+                                                           (FuncCall
+                                                              (Ident (Identifier "attach"))
+                                                              [ BlockArg [ Text "4" ]
+                                                              , KeyValArg
+                                                                  (Identifier "tr")
+                                                                  (Block (Content [ Text "5" ]))
+                                                              ])
+                                                       ]))
+                                             ])
+                                      ]))
+                            ])
+                     ]))
+           , KeyValArg
+               (Identifier "bl")
+               (Block
+                  (Content
+                     [ Code
+                         "test/typ/math/attach-04.typ"
+                         ( line 8 , column 9 )
+                         (FuncCall
+                            (Ident (Identifier "attach"))
+                            [ BlockArg [ Text "2" ]
+                            , KeyValArg
+                                (Identifier "bl")
+                                (Block
+                                   (Content
+                                      [ Code
+                                          "test/typ/math/attach-04.typ"
+                                          ( line 8 , column 23 )
+                                          (FuncCall
+                                             (Ident (Identifier "attach"))
+                                             [ BlockArg [ Text "3" ]
+                                             , KeyValArg
+                                                 (Identifier "bl")
+                                                 (Block
+                                                    (Content
+                                                       [ Code
+                                                           "test/typ/math/attach-04.typ"
+                                                           ( line 8 , column 37 )
+                                                           (FuncCall
+                                                              (Ident (Identifier "attach"))
+                                                              [ BlockArg [ Text "4" ]
+                                                              , KeyValArg
+                                                                  (Identifier "bl")
+                                                                  (Block (Content [ Text "5" ]))
+                                                              ])
+                                                       ]))
+                                             ])
+                                      ]))
+                            ])
+                     ]))
+           , KeyValArg
+               (Identifier "br")
+               (Block
+                  (Content
+                     [ Code
+                         "test/typ/math/attach-04.typ"
+                         ( line 9 , column 9 )
+                         (FuncCall
+                            (Ident (Identifier "attach"))
+                            [ BlockArg [ Text "2" ]
+                            , KeyValArg
+                                (Identifier "br")
+                                (Block
+                                   (Content
+                                      [ Code
+                                          "test/typ/math/attach-04.typ"
+                                          ( line 9 , column 23 )
+                                          (FuncCall
+                                             (Ident (Identifier "attach"))
+                                             [ BlockArg [ Text "3" ]
+                                             , KeyValArg
+                                                 (Identifier "br")
+                                                 (Block
+                                                    (Content
+                                                       [ Code
+                                                           "test/typ/math/attach-04.typ"
+                                                           ( line 9 , column 37 )
+                                                           (FuncCall
+                                                              (Ident (Identifier "attach"))
+                                                              [ BlockArg [ Text "4" ]
+                                                              , KeyValArg
+                                                                  (Identifier "br")
+                                                                  (Block (Content [ Text "5" ]))
+                                                              ])
+                                                       ]))
+                                             ])
+                                      ]))
+                            ])
+                     ]))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.frac(denom: math.attach(b: none, 
+                                                     base: math.attach(b: none, 
+                                                                       base: math.attach(b: none, 
+                                                                                         base: math.attach(b: none, 
+                                                                                                           base: text(body: [V]), 
+                                                                                                           t: text(body: [2])), 
+                                                                                         t: text(body: [3])), 
+                                                                       t: text(body: [4])), 
+                                                     t: text(body: [5])), 
+                                  num: text(body: [1])), 
+                        text(body: [,]), 
+                        math.frac(denom: math.attach(base: text(body: [V]), 
+                                                     tl: math.attach(base: text(body: [2]), 
+                                                                     tl: math.attach(base: text(body: [3]), 
+                                                                                     tl: math.attach(base: text(body: [4]), 
+                                                                                                     tl: text(body: [5]))))), 
+                                  num: text(body: [1])), 
+                        text(body: [,]), 
+                        math.attach(base: text(body: [Ω]), 
+                                    bl: math.attach(base: text(body: [2]), 
+                                                    bl: math.attach(base: text(body: [3]), 
+                                                                    bl: math.attach(base: text(body: [4]), 
+                                                                                    bl: text(body: [5])))), 
+                                    br: math.attach(base: text(body: [2]), 
+                                                    br: math.attach(base: text(body: [3]), 
+                                                                    br: math.attach(base: text(body: [4]), 
+                                                                                    br: text(body: [5])))), 
+                                    tl: math.attach(base: text(body: [2]), 
+                                                    tl: math.attach(base: text(body: [3]), 
+                                                                    tl: math.attach(base: text(body: [4]), 
+                                                                                    tl: text(body: [5])))), 
+                                    tr: math.attach(base: text(body: [2]), 
+                                                    tr: math.attach(base: text(body: [3]), 
+                                                                    tr: math.attach(base: text(body: [4]), 
+                                                                                    tr: text(body: [5]))))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-05.out b/test/out/math/attach-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-05.out
@@ -0,0 +1,174 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/attach-05.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ MAttach
+                   (Just (MGroup Nothing Nothing [ MFrac (Text "1") (Text "2") ]))
+                   (Just
+                      (Code
+                         "test/typ/math/attach-05.typ"
+                         ( line 3 , column 16 )
+                         (Ident (Identifier "zeta"))))
+                   (Text "a")
+               ]
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-05.typ"
+        ( line 3 , column 23 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ MAttach
+                   (Just
+                      (Code
+                         "test/typ/math/attach-05.typ"
+                         ( line 3 , column 30 )
+                         (Ident (Identifier "alpha"))))
+                   (Just (MGroup Nothing Nothing [ MFrac (Text "1") (Text "2") ]))
+                   (Text "a")
+               ]
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-05.typ"
+        ( line 3 , column 44 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ MAttach
+                   (Just (MGroup Nothing Nothing [ MFrac (Text "1") (Text "2") ]))
+                   (Just (MGroup Nothing Nothing [ MFrac (Text "3") (Text "4") ]))
+                   (Text "a")
+               ]
+           ])
+    , HardBreak
+    , Code
+        "test/typ/math/attach-05.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-05.typ"
+                   ( line 4 , column 8 )
+                   (FuncCall
+                      (Ident (Identifier "attach"))
+                      [ BlockArg [ Text "a" ]
+                      , KeyValArg
+                          (Identifier "tl") (Block (Content [ MFrac (Text "1") (Text "2") ]))
+                      , KeyValArg
+                          (Identifier "bl") (Block (Content [ MFrac (Text "3") (Text "4") ]))
+                      ])
+               ]
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/attach-05.typ"
+        ( line 5 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/attach-05.typ"
+                   ( line 5 , column 8 )
+                   (FuncCall
+                      (Ident (Identifier "attach"))
+                      [ BlockArg [ Text "a" ]
+                      , KeyValArg
+                          (Identifier "tl") (Block (Content [ MFrac (Text "1") (Text "2") ]))
+                      , KeyValArg
+                          (Identifier "bl") (Block (Content [ MFrac (Text "3") (Text "4") ]))
+                      , KeyValArg
+                          (Identifier "tr") (Block (Content [ MFrac (Text "1") (Text "2") ]))
+                      , KeyValArg
+                          (Identifier "br") (Block (Content [ MFrac (Text "3") (Text "4") ]))
+                      ])
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.sqrt(radicand: math.attach(b: math.frac(denom: text(body: [2]), 
+                                                                     num: text(body: [1])), 
+                                                        base: text(body: [a]), 
+                                                        t: text(body: [ζ]))), 
+                        text(body: [,]), 
+                        math.sqrt(radicand: math.attach(b: text(body: [α]), 
+                                                        base: text(body: [a]), 
+                                                        t: math.frac(denom: text(body: [2]), 
+                                                                     num: text(body: [1])))), 
+                        text(body: [,]), 
+                        math.sqrt(radicand: math.attach(b: math.frac(denom: text(body: [2]), 
+                                                                     num: text(body: [1])), 
+                                                        base: text(body: [a]), 
+                                                        t: math.frac(denom: text(body: [4]), 
+                                                                     num: text(body: [3])))), 
+                        linebreak(), 
+                        math.sqrt(radicand: math.attach(base: text(body: [a]), 
+                                                        bl: math.frac(denom: text(body: [4]), 
+                                                                      num: text(body: [3])), 
+                                                        tl: math.frac(denom: text(body: [2]), 
+                                                                      num: text(body: [1])))), 
+                        text(body: [,]), 
+                        math.sqrt(radicand: math.attach(base: text(body: [a]), 
+                                                        bl: math.frac(denom: text(body: [4]), 
+                                                                      num: text(body: [3])), 
+                                                        br: math.frac(denom: text(body: [4]), 
+                                                                      num: text(body: [3])), 
+                                                        tl: math.frac(denom: text(body: [2]), 
+                                                                      num: text(body: [1])), 
+                                                        tr: math.frac(denom: text(body: [2]), 
+                                                                      num: text(body: [1])))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-06.out b/test/out/math/attach-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-06.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        Nothing
+        (Just (Text "n"))
+        (MGroup (Just "(") (Just ")") [ Text "-" , Text "1" ])
+    , Text "+"
+    , MAttach
+        Nothing
+        (Just
+           (MGroup
+              Nothing Nothing [ Text "-" , MFrac (Text "1") (Text "2") ]))
+        (MGroup
+           (Just "(")
+           (Just ")")
+           [ MFrac (Text "1") (Text "2") , Text "+" , Text "3" ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: none, 
+                                    base: math.lr(body: ({ [(], 
+                                                           text(body: [-]), 
+                                                           text(body: [1]), 
+                                                           [)] })), 
+                                    t: text(body: [n])), 
+                        text(body: [+]), 
+                        math.attach(b: none, 
+                                    base: math.lr(body: ({ [(], 
+                                                           math.frac(denom: text(body: [2]), 
+                                                                     num: text(body: [1])), 
+                                                           text(body: [+]), 
+                                                           text(body: [3]), 
+                                                           [)] })), 
+                                    t: { text(body: [-]), 
+                                         math.frac(denom: text(body: [2]), 
+                                                   num: text(body: [1])) }) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-07.out b/test/out/math/attach-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-07.out
@@ -0,0 +1,432 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/math/attach-07.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "size") (Literal (Numeric 8.0 Pt)) ])
+, ParBreak
+, Comment
+, Equation
+    True
+    [ MAttach (Just (Text "1")) Nothing (Text "x")
+    , MAttach (Just (Text "1")) Nothing (Text "p")
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 5 , column 11 )
+           (FuncCall (Ident (Identifier "frak")) [ BlockArg [ Text "p" ] ]))
+    , MAttach (Just (Text "1")) Nothing (Text "2")
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 5 , column 25 )
+           (Ident (Identifier "dot")))
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 5 , column 31 )
+           (Ident (Identifier "lg")))
+    , MAttach (Just (Text "1")) Nothing (Text "!")
+    , MAttach (Just (Text "1")) Nothing (Text "\\")
+    , MAttach (Just (Text "1")) Nothing (Text "]")
+    , MAttach (Just (Text "1")) Nothing (Text " ip")
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 5 , column 56 )
+           (FuncCall (Ident (Identifier "op")) [ BlockArg [ Text "iq" ] ]))
+    , HardBreak
+    , MAttach Nothing (Just (Text "1")) (Text "x")
+    , MAttach Nothing (Just (Text "1")) (Text "b")
+    , MAttach
+        Nothing
+        (Just (Text "1"))
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 6 , column 11 )
+           (FuncCall (Ident (Identifier "frak")) [ BlockArg [ Text "b" ] ]))
+    , MAttach Nothing (Just (Text "1")) (Text "2")
+    , MAttach
+        Nothing
+        (Just (Text "1"))
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 6 , column 25 )
+           (Ident (Identifier "dot")))
+    , MAttach
+        Nothing
+        (Just (Text "1"))
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 6 , column 31 )
+           (Ident (Identifier "lg")))
+    , MAttach Nothing (Just (Text "1")) (Text "!")
+    , MAttach Nothing (Just (Text "1")) (Text "\\")
+    , MAttach Nothing (Just (Text "1")) (Text "]")
+    , MAttach Nothing (Just (Text "1")) (Text " ib")
+    , MAttach
+        Nothing
+        (Just (Text "1"))
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 6 , column 56 )
+           (FuncCall (Ident (Identifier "op")) [ BlockArg [ Text "id" ] ]))
+    , HardBreak
+    , MAttach (Just (Text "1")) Nothing (Text "x")
+    , MAttach (Just (Text "1")) Nothing (Text "y")
+    , MAttach (Just (Text "1")) Nothing (Text " _")
+    , MAttach Nothing (Just (Text "1")) (Text "x")
+    , MAttach Nothing (Just (Text "1")) (Text "l")
+    , MAttach Nothing (Just (Text "1")) (Text " `")
+    , Code
+        "test/typ/math/attach-07.typ"
+        ( line 7 , column 31 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg [ Text "I" ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "1" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "1" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "1" ]))
+           , KeyValArg (Identifier "br") (Block (Content [ Text "1" ]))
+           ])
+    , MAttach
+        (Just (Text "1"))
+        (Just (Text "1"))
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 8 , column 3 )
+           (FuncCall
+              (Ident (Identifier "scripts"))
+              [ BlockArg
+                  [ Code
+                      "test/typ/math/attach-07.typ"
+                      ( line 8 , column 11 )
+                      (Ident (Identifier "sum"))
+                  ]
+              ]))
+    , MAttach
+        (Just (Text "1"))
+        (Just (Text "1"))
+        (Code
+           "test/typ/math/attach-07.typ"
+           ( line 8 , column 20 )
+           (Ident (Identifier "integral")))
+    , MAttach
+        (Just (Text "1"))
+        (Just (Text "1"))
+        (MGroup (Just "|") (Just "|") [ MFrac (Text "1") (Text "2") ])
+    , HardBreak
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (MAttach Nothing (Just (Text "1")) (Text "x"))
+    , Text ","
+    , Text " ("
+    , Text "b"
+    , Text "y"
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (MAttach Nothing (Just (Text "1")) (Text ")"))
+    , Text "\8800"
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (MAttach
+           Nothing
+           (Just (Text "1"))
+           (MGroup (Just "(") (Just ")") [ Text "b" , Text "y" ]))
+    , Text ","
+    , MAttach (Just (Text "1")) Nothing (Text " [\8747]")
+    , MAttach
+        (Just (Text "1"))
+        Nothing
+        (MGroup
+           (Just "[")
+           (Just "]")
+           [ Code
+               "test/typ/math/attach-07.typ"
+               ( line 9 , column 47 )
+               (Ident (Identifier "integral"))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  math.equation(block: true, 
+                body: { math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [x], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [p], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.frak(body: text(body: [p], 
+                                                               size: 8.0pt)), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [2], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [⋅], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.op(limits: false, 
+                                                  text: "lg"), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [!], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [\], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: []], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [ ip], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.op(text: text(body: [iq], 
+                                                             size: 8.0pt)), 
+                                    t: none), 
+                        linebreak(), 
+                        math.attach(b: none, 
+                                    base: text(body: [x], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [b], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: math.frak(body: text(body: [b], 
+                                                               size: 8.0pt)), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [2], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [⋅], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: math.op(limits: false, 
+                                                  text: "lg"), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [!], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [\], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: []], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [ ib], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: math.op(text: text(body: [id], 
+                                                             size: 8.0pt)), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        linebreak(), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [x], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [y], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [ _], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: none, 
+                                    base: text(body: [x], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [l], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: none, 
+                                    base: text(body: [ `], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(base: text(body: [I], 
+                                               size: 8.0pt), 
+                                    bl: text(body: [1], 
+                                             size: 8.0pt), 
+                                    br: text(body: [1], 
+                                             size: 8.0pt), 
+                                    tl: text(body: [1], 
+                                             size: 8.0pt), 
+                                    tr: text(body: [1], 
+                                             size: 8.0pt)), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.scripts(body: text(body: [∑], 
+                                                                  size: 8.0pt)), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [∫], 
+                                               size: 8.0pt), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.lr(body: ({ [|], 
+                                                           math.frac(denom: text(body: [2], 
+                                                                                 size: 8.0pt), 
+                                                                     num: text(body: [1], 
+                                                                               size: 8.0pt)), 
+                                                           [|] })), 
+                                    t: text(body: [1], 
+                                            size: 8.0pt)), 
+                        linebreak(), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.attach(b: none, 
+                                                      base: text(body: [x], 
+                                                                 size: 8.0pt), 
+                                                      t: text(body: [1], 
+                                                              size: 8.0pt)), 
+                                    t: none), 
+                        text(body: [,], size: 8.0pt), 
+                        text(body: [ (], 
+                             size: 8.0pt), 
+                        text(body: [b], size: 8.0pt), 
+                        text(body: [y], size: 8.0pt), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.attach(b: none, 
+                                                      base: text(body: [)], 
+                                                                 size: 8.0pt), 
+                                                      t: text(body: [1], 
+                                                              size: 8.0pt)), 
+                                    t: none), 
+                        text(body: [≠], size: 8.0pt), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.attach(b: none, 
+                                                      base: math.lr(body: ({ [(], 
+                                                                             text(body: [b], 
+                                                                                  size: 8.0pt), 
+                                                                             text(body: [y], 
+                                                                                  size: 8.0pt), 
+                                                                             [)] })), 
+                                                      t: text(body: [1], 
+                                                              size: 8.0pt)), 
+                                    t: none), 
+                        text(body: [,], size: 8.0pt), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: text(body: [ [∫]], 
+                                               size: 8.0pt), 
+                                    t: none), 
+                        math.attach(b: text(body: [1], 
+                                            size: 8.0pt), 
+                                    base: math.lr(body: ({ [[], 
+                                                           text(body: [∫], 
+                                                                size: 8.0pt), 
+                                                           []] })), 
+                                    t: none) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-08.out b/test/out/math/attach-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-08.out
@@ -0,0 +1,117 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Text "n"
+              , Text "\8594"
+              , Code
+                  "test/typ/math/attach-08.typ"
+                  ( line 3 , column 11 )
+                  (Ident (Identifier "oo"))
+              , HardBreak
+              , Text "n"
+              , Text " grows"
+              ]))
+        Nothing
+        (Code
+           "test/typ/math/attach-08.typ"
+           ( line 3 , column 3 )
+           (Ident (Identifier "lim")))
+    , MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Text "k"
+              , Text "="
+              , Text "0"
+              , HardBreak
+              , Text "k"
+              , Code
+                  "test/typ/math/attach-08.typ"
+                  ( line 3 , column 40 )
+                  (Ident (Identifier "in"))
+              , Code
+                  "test/typ/math/attach-08.typ"
+                  ( line 3 , column 43 )
+                  (Ident (Identifier "NN"))
+              ]))
+        (Just (Text "n"))
+        (Code
+           "test/typ/math/attach-08.typ"
+           ( line 3 , column 27 )
+           (Ident (Identifier "sum")))
+    , Text "k"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: { text(body: [n]), 
+                                         text(body: [→]), 
+                                         text(body: [∞]), 
+                                         linebreak(), 
+                                         text(body: [n]), 
+                                         text(body: [ grows]) }, 
+                                    base: math.op(limits: true, 
+                                                  text: "lim"), 
+                                    t: none), 
+                        math.attach(b: { text(body: [k]), 
+                                         text(body: [=]), 
+                                         text(body: [0]), 
+                                         linebreak(), 
+                                         text(body: [k]), 
+                                         text(body: [∈]), 
+                                         text(body: [ℕ]) }, 
+                                    base: text(body: [∑]), 
+                                    t: text(body: [n])), 
+                        text(body: [k]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/attach-09.out b/test/out/math/attach-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/attach-09.out
@@ -0,0 +1,145 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/attach-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/attach-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/attach-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        (Just (Text "1"))
+        (Just (Text "2"))
+        (Code
+           "test/typ/math/attach-09.typ"
+           ( line 3 , column 3 )
+           (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "A" ] ]))
+    , Text "\8800"
+    , MAttach (Just (Text "1")) (Just (Text "2")) (Text "A")
+    ]
+, SoftBreak
+, Equation
+    True
+    [ MAttach
+        (Just (Text "1"))
+        (Just (Text "2"))
+        (Code
+           "test/typ/math/attach-09.typ"
+           ( line 4 , column 3 )
+           (FuncCall
+              (Ident (Identifier "scripts"))
+              [ BlockArg
+                  [ Code
+                      "test/typ/math/attach-09.typ"
+                      ( line 4 , column 11 )
+                      (Ident (Identifier "sum"))
+                  ]
+              ]))
+    , Text "\8800"
+    , MAttach
+        (Just (Text "1"))
+        (Just (Text "2"))
+        (Code
+           "test/typ/math/attach-09.typ"
+           ( line 4 , column 23 )
+           (Ident (Identifier "sum")))
+    ]
+, SoftBreak
+, Equation
+    True
+    [ MAttach
+        (Just (Text "a"))
+        (Just (Text "b"))
+        (Code
+           "test/typ/math/attach-09.typ"
+           ( line 5 , column 3 )
+           (FuncCall
+              (Ident (Identifier "limits"))
+              [ BlockArg
+                  [ Code
+                      "test/typ/math/attach-09.typ"
+                      ( line 5 , column 10 )
+                      (Ident (Identifier "integral"))
+                  ]
+              ]))
+    , Text "\8800"
+    , MAttach
+        (Just (Text "a"))
+        (Just (Text "b"))
+        (Code
+           "test/typ/math/attach-09.typ"
+           ( line 5 , column 27 )
+           (Ident (Identifier "integral")))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: text(body: [1]), 
+                                    base: math.limits(body: text(body: [A])), 
+                                    t: text(body: [2])), 
+                        text(body: [≠]), 
+                        math.attach(b: text(body: [1]), 
+                                    base: text(body: [A]), 
+                                    t: text(body: [2])) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: text(body: [1]), 
+                                    base: math.scripts(body: text(body: [∑])), 
+                                    t: text(body: [2])), 
+                        text(body: [≠]), 
+                        math.attach(b: text(body: [1]), 
+                                    base: text(body: [∑]), 
+                                    t: text(body: [2])) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: text(body: [a]), 
+                                    base: math.limits(body: text(body: [∫])), 
+                                    t: text(body: [b])), 
+                        text(body: [≠]), 
+                        math.attach(b: text(body: [a]), 
+                                    base: text(body: [∫]), 
+                                    t: text(body: [b])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/cancel-00.out b/test/out/math/cancel-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/cancel-00.out
@@ -0,0 +1,138 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/cancel-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/cancel-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/cancel-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "a"
+    , Text "+"
+    , Text "5"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-00.typ"
+        ( line 3 , column 10 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "x" ] ])
+    , Text "+"
+    , Text "b"
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-00.typ"
+        ( line 3 , column 26 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "x" ] ])
+    ]
+, ParBreak
+, Equation
+    False
+    [ Text "c"
+    , Text "+"
+    , MFrac
+        (MGroup
+           (Just "(")
+           (Just ")")
+           [ Text "a"
+           , Code
+               "test/typ/math/cancel-00.typ"
+               ( line 5 , column 9 )
+               (FieldAccess (Ident (Identifier "c")) (Ident (Identifier "dot")))
+           , Code
+               "test/typ/math/cancel-00.typ"
+               ( line 5 , column 15 )
+               (FuncCall
+                  (Ident (Identifier "cancel"))
+                  [ BlockArg
+                      [ Text "b"
+                      , Code
+                          "test/typ/math/cancel-00.typ"
+                          ( line 5 , column 24 )
+                          (FieldAccess (Ident (Identifier "c")) (Ident (Identifier "dot")))
+                      , Text "c"
+                      ]
+                  ])
+           ])
+        (MGroup
+           Nothing
+           Nothing
+           [ Code
+               "test/typ/math/cancel-00.typ"
+               ( line 5 , column 35 )
+               (FuncCall
+                  (Ident (Identifier "cancel"))
+                  [ BlockArg
+                      [ Text "b"
+                      , Code
+                          "test/typ/math/cancel-00.typ"
+                          ( line 5 , column 44 )
+                          (FieldAccess (Ident (Identifier "c")) (Ident (Identifier "dot")))
+                      , Text "c"
+                      ]
+                  ])
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        text(body: [5]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [x])), 
+                        text(body: [+]), 
+                        text(body: [b]), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [x])) }, 
+                numbering: none), 
+  parbreak(), 
+  math.equation(block: false, 
+                body: { text(body: [c]), 
+                        text(body: [+]), 
+                        math.frac(denom: math.cancel(body: { text(body: [b]), 
+                                                             text(body: [·]), 
+                                                             text(body: [c]) }), 
+                                  num: { text(body: [a]), 
+                                         text(body: [·]), 
+                                         math.cancel(body: { text(body: [b]), 
+                                                             text(body: [·]), 
+                                                             text(body: [c]) }) }) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/cancel-01.out b/test/out/math/cancel-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/cancel-01.out
@@ -0,0 +1,170 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/cancel-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/cancel-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/cancel-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/cancel-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Equation
+    True
+    [ Text "a"
+    , Text "+"
+    , Text "b"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-01.typ"
+        ( line 4 , column 11 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "b" , Text "+" , Text "c" ] ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-01.typ"
+        ( line 4 , column 27 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "b" ] ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-01.typ"
+        ( line 4 , column 39 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "c" ] ])
+    , Text "-"
+    , Text "5"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-01.typ"
+        ( line 4 , column 55 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "6" ] ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-01.typ"
+        ( line 4 , column 67 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "6" ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "e"
+    , Text "+"
+    , MFrac
+        (MGroup
+           (Just "(")
+           (Just ")")
+           [ Text "a"
+           , Code
+               "test/typ/math/cancel-01.typ"
+               ( line 5 , column 10 )
+               (FieldAccess (Ident (Identifier "c")) (Ident (Identifier "dot")))
+           , Code
+               "test/typ/math/cancel-01.typ"
+               ( line 5 , column 16 )
+               (FuncCall
+                  (Ident (Identifier "cancel"))
+                  [ BlockArg
+                      [ MGroup
+                          (Just "(")
+                          (Just ")")
+                          [ Text "b" , Text "+" , Text "c" , Text "+" , Text "d" ]
+                      ]
+                  ])
+           ])
+        (MGroup
+           Nothing
+           Nothing
+           [ Code
+               "test/typ/math/cancel-01.typ"
+               ( line 5 , column 38 )
+               (FuncCall
+                  (Ident (Identifier "cancel"))
+                  [ BlockArg [ Text "b" , Text "+" , Text "c" , Text "+" , Text "d" ]
+                  ])
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        text(body: [b]), 
+                        text(body: [+]), 
+                        math.cancel(body: { text(body: [b]), 
+                                            text(body: [+]), 
+                                            text(body: [c]) }), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [b])), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [c])), 
+                        text(body: [-]), 
+                        text(body: [5]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [6])), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [6])) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [e]), 
+                        text(body: [+]), 
+                        math.frac(denom: math.cancel(body: { text(body: [b]), 
+                                                             text(body: [+]), 
+                                                             text(body: [c]), 
+                                                             text(body: [+]), 
+                                                             text(body: [d]) }), 
+                                  num: { text(body: [a]), 
+                                         text(body: [·]), 
+                                         math.cancel(body: math.lr(body: ({ [(], 
+                                                                            text(body: [b]), 
+                                                                            text(body: [+]), 
+                                                                            text(body: [c]), 
+                                                                            text(body: [+]), 
+                                                                            text(body: [d]), 
+                                                                            [)] }))) }) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/cancel-02.out b/test/out/math/cancel-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/cancel-02.out
@@ -0,0 +1,119 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/cancel-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/cancel-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/cancel-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "a"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-02.typ"
+        ( line 3 , column 6 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "x" ]
+           , KeyValArg (Identifier "inverted") (Literal (Boolean True))
+           ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-02.typ"
+        ( line 3 , column 35 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "x" ]
+           , KeyValArg (Identifier "inverted") (Literal (Boolean True))
+           ])
+    , Text "+"
+    , Text "10"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-02.typ"
+        ( line 3 , column 69 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "y" ] ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-02.typ"
+        ( line 3 , column 81 )
+        (FuncCall (Ident (Identifier "cancel")) [ BlockArg [ Text "y" ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "x"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-02.typ"
+        ( line 4 , column 7 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "abcdefg" ]
+           , KeyValArg (Identifier "inverted") (Literal (Boolean True))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [x]), 
+                                    inverted: true), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [x]), 
+                                    inverted: true), 
+                        text(body: [+]), 
+                        text(body: [10]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [y])), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [y])) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [abcdefg]), 
+                                    inverted: true) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/cancel-03.out b/test/out/math/cancel-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/cancel-03.out
@@ -0,0 +1,107 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/cancel-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/cancel-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/cancel-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "a"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-03.typ"
+        ( line 3 , column 6 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "b" , Text "+" , Text "c" , Text "+" , Text "d" ]
+           , KeyValArg (Identifier "cross") (Literal (Boolean True))
+           , KeyValArg (Identifier "stroke") (Ident (Identifier "red"))
+           ])
+    , Text "+"
+    , Text "e"
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "a"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-03.typ"
+        ( line 4 , column 7 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "b" , Text "+" , Text "c" , Text "+" , Text "d" ]
+           , KeyValArg (Identifier "cross") (Literal (Boolean True))
+           ])
+    , Text "+"
+    , Text "e"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        math.cancel(body: { text(body: [b]), 
+                                            text(body: [+]), 
+                                            text(body: [c]), 
+                                            text(body: [+]), 
+                                            text(body: [d]) }, 
+                                    cross: true, 
+                                    stroke: rgb(100%,25%,21%,100%)), 
+                        text(body: [+]), 
+                        text(body: [e]) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        math.cancel(body: { text(body: [b]), 
+                                            text(body: [+]), 
+                                            text(body: [c]), 
+                                            text(body: [+]), 
+                                            text(body: [d]) }, 
+                                    cross: true), 
+                        text(body: [+]), 
+                        text(body: [e]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/cancel-04.out b/test/out/math/cancel-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/cancel-04.out
@@ -0,0 +1,142 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/cancel-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/cancel-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/cancel-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/cancel-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt))
+       , KeyValArg (Identifier "height") (Literal Auto)
+       ])
+, SoftBreak
+, Equation
+    False
+    [ Text "a"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-04.typ"
+        ( line 4 , column 6 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "x" ]
+           , KeyValArg (Identifier "length") (Literal (Numeric 200.0 Percent))
+           ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-04.typ"
+        ( line 4 , column 33 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "x" ]
+           , KeyValArg (Identifier "length") (Literal (Numeric 50.0 Percent))
+           , KeyValArg
+               (Identifier "stroke")
+               (Block
+                  (CodeBlock
+                     [ Plus (Ident (Identifier "red")) (Literal (Numeric 1.1 Pt)) ]))
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "b"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-04.typ"
+        ( line 5 , column 7 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "x" ]
+           , KeyValArg (Identifier "length") (Literal (Numeric 150.0 Percent))
+           ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-04.typ"
+        ( line 5 , column 34 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "a" , Text "+" , Text "b" , Text "+" , Text "c" ]
+           , KeyValArg (Identifier "length") (Literal (Numeric 50.0 Percent))
+           , KeyValArg
+               (Identifier "stroke")
+               (Block
+                  (CodeBlock
+                     [ Plus (Ident (Identifier "blue")) (Literal (Numeric 1.2 Pt)) ]))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [x]), 
+                                    length: 200%), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [x]), 
+                                    length: 50%, 
+                                    stroke: (thickness: 1.1pt,
+                                             color: rgb(100%,25%,21%,100%))) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [b]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [x]), 
+                                    length: 150%), 
+                        text(body: [-]), 
+                        math.cancel(body: { text(body: [a]), 
+                                            text(body: [+]), 
+                                            text(body: [b]), 
+                                            text(body: [+]), 
+                                            text(body: [c]) }, 
+                                    length: 50%, 
+                                    stroke: (thickness: 1.2pt,
+                                             color: rgb(0%,45%,85%,100%))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/cancel-05.out b/test/out/math/cancel-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/cancel-05.out
@@ -0,0 +1,129 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/cancel-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/cancel-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/cancel-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "x"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-05.typ"
+        ( line 3 , column 6 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "y" ]
+           , KeyValArg (Identifier "rotation") (Literal (Numeric 90.0 Deg))
+           ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-05.typ"
+        ( line 3 , column 36 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg [ Text "z" ]
+           , KeyValArg (Identifier "rotation") (Literal (Numeric 135.0 Deg))
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "e"
+    , Text "+"
+    , Code
+        "test/typ/math/cancel-05.typ"
+        ( line 4 , column 7 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg
+               [ MFrac
+                   (MGroup (Just "(") (Just ")") [ Text "j" , Text "+" , Text "e" ])
+                   (MGroup Nothing Nothing [ Text "f" , Text "+" , Text "e" ])
+               ]
+           ])
+    , Text "-"
+    , Code
+        "test/typ/math/cancel-05.typ"
+        ( line 4 , column 33 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg
+               [ MFrac
+                   (MGroup (Just "(") (Just ")") [ Text "j" , Text "+" , Text "e" ])
+                   (MGroup Nothing Nothing [ Text "f" , Text "+" , Text "e" ])
+               ]
+           , KeyValArg (Identifier "rotation") (Literal (Numeric 30.0 Deg))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [x]), 
+                        text(body: [+]), 
+                        math.cancel(body: text(body: [y]), 
+                                    rotation: 90.0deg), 
+                        text(body: [-]), 
+                        math.cancel(body: text(body: [z]), 
+                                    rotation: 135.0deg) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [e]), 
+                        text(body: [+]), 
+                        math.cancel(body: math.frac(denom: { text(body: [f]), 
+                                                             text(body: [+]), 
+                                                             text(body: [e]) }, 
+                                                    num: { text(body: [j]), 
+                                                           text(body: [+]), 
+                                                           text(body: [e]) })), 
+                        text(body: [-]), 
+                        math.cancel(body: math.frac(denom: { text(body: [f]), 
+                                                             text(body: [+]), 
+                                                             text(body: [e]) }, 
+                                                    num: { text(body: [j]), 
+                                                           text(body: [+]), 
+                                                           text(body: [e]) }), 
+                                    rotation: 30.0deg) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/cases-00.out b/test/out/math/cases-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/cases-00.out
@@ -0,0 +1,148 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/cases-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/cases-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/cases-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Equation
+    True
+    [ MGroup
+        Nothing
+        Nothing
+        [ Text "f"
+        , MGroup (Just "(") (Just ")") [ Text "x" , Text "," , Text "y" ]
+        ]
+    , Text ":"
+    , Text "="
+    , Code
+        "test/typ/math/cases-00.typ"
+        ( line 2 , column 14 )
+        (FuncCall
+           (Ident (Identifier "cases"))
+           [ BlockArg
+               [ Text "1"
+               , Code
+                   "test/typ/math/cases-00.typ"
+                   ( line 3 , column 5 )
+                   (Ident (Identifier "quad"))
+               , MAlignPoint
+               , Text "if "
+               , MFrac
+                   (MGroup
+                      (Just "(")
+                      (Just ")")
+                      [ Text "x"
+                      , Code
+                          "test/typ/math/cases-00.typ"
+                          ( line 3 , column 19 )
+                          (Ident (Identifier "dot"))
+                      , Text "y"
+                      ])
+                   (Text "2")
+               , Text "\8804"
+               , Text "0"
+               ]
+           , BlockArg
+               [ Text "2"
+               , MAlignPoint
+               , Text "if "
+               , Text "x"
+               , Code
+                   "test/typ/math/cases-00.typ"
+                   ( line 4 , column 13 )
+                   (Ident (Identifier "divides"))
+               , Text "2"
+               ]
+           , BlockArg
+               [ Text "3"
+               , MAlignPoint
+               , Text "if "
+               , Text "x"
+               , Code
+                   "test/typ/math/cases-00.typ"
+                   ( line 5 , column 13 )
+                   (Ident (Identifier "in"))
+               , Code
+                   "test/typ/math/cases-00.typ"
+                   ( line 5 , column 16 )
+                   (Ident (Identifier "NN"))
+               ]
+           , BlockArg [ Text "4" , MAlignPoint , Text "else" ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [f]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         text(body: [,]), 
+                                         text(body: [y]), 
+                                         [)] })), 
+                        text(body: [:]), 
+                        text(body: [=]), 
+                        math.cases(children: ({ text(body: [1]), 
+                                                text(body: [ ]), 
+                                                math.alignpoint(), 
+                                                text(body: [if ]), 
+                                                math.frac(denom: text(body: [2]), 
+                                                          num: { text(body: [x]), 
+                                                                 text(body: [⋅]), 
+                                                                 text(body: [y]) }), 
+                                                text(body: [≤]), 
+                                                text(body: [0]) }, 
+                                              { text(body: [2]), 
+                                                math.alignpoint(), 
+                                                text(body: [if ]), 
+                                                text(body: [x]), 
+                                                text(body: [∣]), 
+                                                text(body: [2]) }, 
+                                              { text(body: [3]), 
+                                                math.alignpoint(), 
+                                                text(body: [if ]), 
+                                                text(body: [x]), 
+                                                text(body: [∈]), 
+                                                text(body: [ℕ]) }, 
+                                              { text(body: [4]), 
+                                                math.alignpoint(), 
+                                                text(body: [else]) })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/content-00.out b/test/out/math/content-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/content-00.out
@@ -0,0 +1,115 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/content-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/content-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/content-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/content-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "monkey")))
+       (FuncCall
+          (Ident (Identifier "move"))
+          [ KeyValArg (Identifier "dy") (Literal (Numeric 0.2 Em))
+          , NormalArg
+              (FuncCall
+                 (Ident (Identifier "image"))
+                 [ NormalArg (Literal (String "test/assets/files/monkey.svg"))
+                 , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Em))
+                 ])
+          ]))
+, SoftBreak
+, Equation
+    True
+    [ MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Text "i"
+              , Text "="
+              , Code
+                  "test/typ/math/content-00.typ"
+                  ( line 4 , column 11 )
+                  (FieldAccess
+                     (Ident (Identifier "apple")) (Ident (Identifier "emoji")))
+              ]))
+        (Just
+           (Code
+              "test/typ/math/content-00.typ"
+              ( line 4 , column 25 )
+              (FieldAccess
+                 (Ident (Identifier "red"))
+                 (FieldAccess
+                    (Ident (Identifier "apple")) (Ident (Identifier "emoji"))))))
+        (Code
+           "test/typ/math/content-00.typ"
+           ( line 4 , column 3 )
+           (Ident (Identifier "sum")))
+    , Text "i"
+    , Text "+"
+    , MFrac
+        (Code
+           "test/typ/math/content-00.typ"
+           ( line 4 , column 45 )
+           (Ident (Identifier "monkey")))
+        (Text "2")
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: { text(body: [i]), 
+                                         text(body: [=]), 
+                                         text(body: [🍏]) }, 
+                                    base: text(body: [∑]), 
+                                    t: text(body: [🍎])), 
+                        text(body: [i]), 
+                        text(body: [+]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: move(body: image(height: 1.0em, 
+                                                        path: "test/assets/files/monkey.svg"), 
+                                            dy: 0.2em)) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/content-01.out b/test/out/math/content-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/content-01.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/content-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/content-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/content-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "x"
+    , Text ":"
+    , Text "="
+    , MFrac
+        (Code
+           "test/typ/math/content-01.typ"
+           ( line 3 , column 9 )
+           (FuncCall
+              (Ident (Identifier "table"))
+              [ KeyValArg (Identifier "columns") (Literal (Int 2))
+              , BlockArg [ Text "x" ]
+              , BlockArg [ Text "y" ]
+              ]))
+        (Code
+           "test/typ/math/content-01.typ"
+           ( line 3 , column 33 )
+           (FuncCall
+              (Ident (Identifier "mat"))
+              [ BlockArg [ Text "1" ]
+              , BlockArg [ Text "2" ]
+              , BlockArg [ Text "3" ]
+              ]))
+    , Text "="
+    , Code
+        "test/typ/math/content-01.typ"
+        ( line 4 , column 9 )
+        (FuncCall
+           (Ident (Identifier "table"))
+           [ BlockArg [ Text "A" ]
+           , BlockArg [ Text "B" ]
+           , BlockArg [ Text "C" ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        text(body: [:]), 
+                        text(body: [=]), 
+                        math.frac(denom: math.mat(rows: ((text(body: [1]), 
+                                                          text(body: [2]), 
+                                                          text(body: [3])))), 
+                                  num: table(children: (text(body: [x]), 
+                                                        text(body: [y])), 
+                                             columns: 2)), 
+                        text(body: [=]), 
+                        table(children: (text(body: [A]), 
+                                         text(body: [B]), 
+                                         text(body: [C]))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/content-02.out b/test/out/math/content-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/content-02.out
@@ -0,0 +1,61 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/content-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/content-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/content-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/content-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "attach")) (Ident (Identifier "math")))
+       [ NormalArg (Block (Content [ Equation False [ Text "a" ] ]))
+       , KeyValArg (Identifier "t") (Block (Content [ Text "b" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.attach(base: math.equation(block: false, 
+                                  body: text(body: [a]), 
+                                  numbering: none), 
+              t: text(body: [b])), 
+  parbreak() }
diff --git a/test/out/math/content-03.out b/test/out/math/content-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/content-03.out
@@ -0,0 +1,87 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/content-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/content-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/content-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/content-03.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "here")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "text")))
+          [ KeyValArg (Identifier "font") (Literal (String "Noto Sans")) ]))
+, SoftBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/content-03.typ"
+        ( line 4 , column 3 )
+        (FuncCall (Ident (Identifier "here")) [ BlockArg [ Text "f" ] ])
+    , Text ":"
+    , Text "="
+    , Code
+        "test/typ/math/content-03.typ"
+        ( line 4 , column 15 )
+        (FuncCall
+           (Ident (Identifier "here"))
+           [ BlockArg [ Text "Hi" , Space , Text "there" ] ])
+    ]
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: text(body: [f]), 
+                             font: "Noto Sans"), 
+                        text(body: [:]), 
+                        text(body: [=]), 
+                        text(body: { text(body: [Hi]), 
+                                     text(body: [ ]), 
+                                     text(body: [there]) }, 
+                             font: "Noto Sans") }, 
+                numbering: none), 
+  text(body: [.]), 
+  parbreak() }
diff --git a/test/out/math/delimited-00.out b/test/out/math/delimited-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-00.out
@@ -0,0 +1,125 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MGroup (Just "(") (Just ")") [ Text "a" ]
+    , Text "+"
+    , MGroup (Just "{") (Just "}") [ MFrac (Text "b") (Text "2") ]
+    , Text "+"
+    , MFrac (MGroup (Just "|") (Just "|") [ Text "a" ]) (Text "2")
+    , Text "+"
+    , MGroup (Just "(") (Just ")") [ Text "b" ]
+    ]
+, SoftBreak
+, Equation
+    False
+    [ MGroup
+        Nothing
+        Nothing
+        [ Text "f"
+        , MGroup (Just "(") (Just ")") [ MFrac (Text "x") (Text "2") ]
+        ]
+    , Text "<"
+    , Code
+        "test/typ/math/delimited-00.typ"
+        ( line 4 , column 11 )
+        (FuncCall
+           (Ident (Identifier "zeta"))
+           [ BlockArg
+               [ MAttach Nothing (Just (Text "2")) (Text "c")
+               , Text "+"
+               , MGroup
+                   (Just "|")
+                   (Just "|")
+                   [ Text "a" , Text "+" , MFrac (Text "b") (Text "2") ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.lr(body: ({ [(], 
+                                         text(body: [a]), 
+                                         [)] })), 
+                        text(body: [+]), 
+                        math.lr(body: ({ [{], 
+                                         math.frac(denom: text(body: [2]), 
+                                                   num: text(body: [b])), 
+                                         [}] })), 
+                        text(body: [+]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [|], 
+                                                        text(body: [a]), 
+                                                        [|] }))), 
+                        text(body: [+]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [b]), 
+                                         [)] })) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [f]), 
+                        math.lr(body: ({ [(], 
+                                         math.frac(denom: text(body: [2]), 
+                                                   num: text(body: [x])), 
+                                         [)] })), 
+                        text(body: [<]), 
+                        text(body: [ζ]), 
+                        text(body: [(]), 
+                        math.attach(b: none, 
+                                    base: text(body: [c]), 
+                                    t: text(body: [2])), 
+                        text(body: [+]), 
+                        math.lr(body: ({ [|], 
+                                         text(body: [a]), 
+                                         text(body: [+]), 
+                                         math.frac(denom: text(body: [2]), 
+                                                   num: text(body: [b])), 
+                                         [|] })), 
+                        text(body: [)]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-01.out b/test/out/math/delimited-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-01.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ MGroup
+        (Just "[")
+        Nothing
+        [ Text "1"
+        , Text ","
+        , Text "2"
+        , MGroup
+            (Just "[")
+            Nothing
+            [ Text "="
+            , MGroup
+                (Just "[")
+                Nothing
+                [ Text "1"
+                , Text ","
+                , Text "2"
+                , Text ")"
+                , Text "\8800"
+                , Code
+                    "test/typ/math/delimited-01.typ"
+                    ( line 3 , column 19 )
+                    (Ident (Identifier "zeta"))
+                , Text "("
+                , MFrac (Text "x") (Text "2")
+                , Text ")"
+                ]
+            ]
+        ]
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [[]), 
+                        text(body: [1]), 
+                        text(body: [,]), 
+                        text(body: [2]), 
+                        text(body: [[]), 
+                        text(body: [=]), 
+                        text(body: [[]), 
+                        text(body: [1]), 
+                        text(body: [,]), 
+                        text(body: [2]), 
+                        text(body: [)]), 
+                        text(body: [≠]), 
+                        text(body: [ζ]), 
+                        text(body: [(]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: text(body: [x])), 
+                        text(body: [)]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-02.out b/test/out/math/delimited-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-02.out
@@ -0,0 +1,127 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MGroup
+        (Just "[")
+        (Just "]")
+        [ MGroup (Just "|") (Just "|") [ MFrac (Text "a") (Text "b") ] ]
+    , Text "\8800"
+    , Code
+        "test/typ/math/delimited-02.typ"
+        ( line 3 , column 14 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg
+               [ MGroup
+                   (Just "|") (Just "|") [ Text "]" , MFrac (Text "a") (Text "b") ]
+               , Text "]"
+               ]
+           ])
+    , Text "\8800"
+    , MGroup
+        (Just "[") Nothing [ MFrac (Text "a") (Text "b") , Text ")" ]
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/delimited-02.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg
+               [ MGroup
+                   (Just "|")
+                   (Just "|")
+                   [ Text "]"
+                   , Text "1"
+                   , Text ","
+                   , Text "2"
+                   , Text "["
+                   , Text "+"
+                   , MFrac (Text "1") (Text "2")
+                   ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.lr(body: ({ [[], 
+                                         math.lr(body: ({ [|], 
+                                                          math.frac(denom: text(body: [b]), 
+                                                                    num: text(body: [a])), 
+                                                          [|] })), 
+                                         []] })), 
+                        text(body: [≠]), 
+                        math.lr(body: ({ math.lr(body: ({ [|], 
+                                                          text(body: []]), 
+                                                          math.frac(denom: text(body: [b]), 
+                                                                    num: text(body: [a])), 
+                                                          [|] })), 
+                                         text(body: []]) })), 
+                        text(body: [≠]), 
+                        text(body: [[]), 
+                        math.frac(denom: text(body: [b]), 
+                                  num: text(body: [a])), 
+                        text(body: [)]) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.lr(body: (math.lr(body: ({ [|], 
+                                                      text(body: []]), 
+                                                      text(body: [1]), 
+                                                      text(body: [,]), 
+                                                      text(body: [2]), 
+                                                      text(body: [[]), 
+                                                      text(body: [+]), 
+                                                      math.frac(denom: text(body: [2]), 
+                                                                num: text(body: [1])), 
+                                                      [|] })))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-03.out b/test/out/math/delimited-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-03.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MGroup (Just "|") (Just "|") [ Text "x" , Text "+" ]
+    , Text "y"
+    , MGroup
+        (Just "|") (Just "|") [ Text "+" , MFrac (Text "z") (Text "a") ]
+    , HardBreak
+    , MGroup
+        (Just "|")
+        (Just "|")
+        [ Text "x"
+        , Text "+"
+        , Code
+            "test/typ/math/delimited-03.typ"
+            ( line 4 , column 8 )
+            (FuncCall
+               (Ident (Identifier "lr"))
+               [ BlockArg [ MGroup (Just "|") (Just "|") [ Text "y" ] ] ])
+        , Text "+"
+        , MFrac (Text "z") (Text "a")
+        ]
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.lr(body: ({ [|], 
+                                         text(body: [x]), 
+                                         text(body: [+]), 
+                                         [|] })), 
+                        text(body: [y]), 
+                        math.lr(body: ({ [|], 
+                                         text(body: [+]), 
+                                         math.frac(denom: text(body: [a]), 
+                                                   num: text(body: [z])), 
+                                         [|] })), 
+                        linebreak(), 
+                        math.lr(body: ({ [|], 
+                                         text(body: [x]), 
+                                         text(body: [+]), 
+                                         math.lr(body: (math.lr(body: ({ [|], 
+                                                                         text(body: [y]), 
+                                                                         [|] })))), 
+                                         text(body: [+]), 
+                                         math.frac(denom: text(body: [a]), 
+                                                   num: text(body: [z])), 
+                                         [|] })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-04.out b/test/out/math/delimited-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-04.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/delimited-04.typ"
+        ( line 3 , column 3 )
+        (FieldAccess
+           (Ident (Identifier "l")) (Ident (Identifier "bracket")))
+    , MFrac (Text "a") (Text "b")
+    , Code
+        "test/typ/math/delimited-04.typ"
+        ( line 3 , column 17 )
+        (FieldAccess
+           (Ident (Identifier "r")) (Ident (Identifier "bracket")))
+    , Text "="
+    , Code
+        "test/typ/math/delimited-04.typ"
+        ( line 4 , column 5 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/delimited-04.typ"
+                   ( line 4 , column 8 )
+                   (FieldAccess
+                      (Ident (Identifier "l")) (Ident (Identifier "bracket")))
+               , MFrac (Text "a") (Text "b")
+               , Code
+                   "test/typ/math/delimited-04.typ"
+                   ( line 4 , column 22 )
+                   (FieldAccess
+                      (Ident (Identifier "r")) (Ident (Identifier "bracket")))
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [[]), 
+                        math.frac(denom: text(body: [b]), 
+                                  num: text(body: [a])), 
+                        text(body: []]), 
+                        text(body: [=]), 
+                        math.lr(body: ({ text(body: [[]), 
+                                         math.frac(denom: text(body: [b]), 
+                                                   num: text(body: [a])), 
+                                         text(body: []]) })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-05.out b/test/out/math/delimited-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-05.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/delimited-05.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg [ MFrac (Text "a") (Text "b") , Text "]" ] ])
+    , Text "="
+    , Text "a"
+    , Text "="
+    , Code
+        "test/typ/math/delimited-05.typ"
+        ( line 3 , column 19 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg [ Text "{" , MFrac (Text "a") (Text "b") ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.lr(body: ({ math.frac(denom: text(body: [b]), 
+                                                   num: text(body: [a])), 
+                                         text(body: []]) })), 
+                        text(body: [=]), 
+                        text(body: [a]), 
+                        text(body: [=]), 
+                        math.lr(body: ({ text(body: [{]), 
+                                         math.frac(denom: text(body: [b]), 
+                                                   num: text(body: [a])) })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-06.out b/test/out/math/delimited-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-06.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/delimited-06.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg
+               [ Text "]"
+               , MAttach
+                   (Just (MGroup Nothing Nothing [ Text "x" , Text "=" , Text "1" ]))
+                   (Just (Text "n"))
+                   (Code
+                      "test/typ/math/delimited-06.typ"
+                      ( line 3 , column 7 )
+                      (Ident (Identifier "sum")))
+               , Text "x"
+               , Text "]"
+               ]
+           , KeyValArg (Identifier "size") (Literal (Numeric 70.0 Percent))
+           ])
+    , Text "<"
+    , Code
+        "test/typ/math/delimited-06.typ"
+        ( line 4 , column 5 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg
+               [ MGroup (Just "(") (Just ")") [ Text "1" , Text "," , Text "2" ] ]
+           , KeyValArg (Identifier "size") (Literal (Numeric 200.0 Percent))
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.lr(body: ({ text(body: []]), 
+                                         math.attach(b: { text(body: [x]), 
+                                                          text(body: [=]), 
+                                                          text(body: [1]) }, 
+                                                     base: text(body: [∑]), 
+                                                     t: text(body: [n])), 
+                                         text(body: [x]), 
+                                         text(body: []]) }), 
+                                size: 70%), 
+                        text(body: [<]), 
+                        math.lr(body: (math.lr(body: ({ [(], 
+                                                        text(body: [1]), 
+                                                        text(body: [,]), 
+                                                        text(body: [2]), 
+                                                        [)] }))), 
+                                size: 200%) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-07.out b/test/out/math/delimited-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-07.out
@@ -0,0 +1,85 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Code
+        "test/typ/math/delimited-07.typ"
+        ( line 3 , column 2 )
+        (FuncCall
+           (Ident (Identifier "floor"))
+           [ BlockArg [ MFrac (Text "x") (Text "2") ] ])
+    , Text ","
+    , Code
+        "test/typ/math/delimited-07.typ"
+        ( line 3 , column 14 )
+        (FuncCall
+           (Ident (Identifier "ceil"))
+           [ BlockArg [ MFrac (Text "x") (Text "2") ] ])
+    , Text ","
+    , Code
+        "test/typ/math/delimited-07.typ"
+        ( line 3 , column 25 )
+        (FuncCall (Ident (Identifier "abs")) [ BlockArg [ Text "x" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/delimited-07.typ"
+        ( line 3 , column 33 )
+        (FuncCall (Ident (Identifier "norm")) [ BlockArg [ Text "x" ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.floor(body: math.frac(denom: text(body: [2]), 
+                                                   num: text(body: [x]))), 
+                        text(body: [,]), 
+                        math.ceil(body: math.frac(denom: text(body: [2]), 
+                                                  num: text(body: [x]))), 
+                        text(body: [,]), 
+                        math.abs(body: text(body: [x])), 
+                        text(body: [,]), 
+                        math.norm(body: text(body: [x])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/delimited-08.out b/test/out/math/delimited-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/delimited-08.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/delimited-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/delimited-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/delimited-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/delimited-08.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "lr"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/delimited-08.typ"
+                   ( line 4 , column 5 )
+                   (FuncCall
+                      (Ident (Identifier "text"))
+                      [ BlockArg [ Text "(" ]
+                      , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                      ])
+               , MFrac (Text "a") (Text "b")
+               , Code
+                   "test/typ/math/delimited-08.typ"
+                   ( line 5 , column 5 )
+                   (FuncCall
+                      (Ident (Identifier "text"))
+                      [ BlockArg [ Text ")" ]
+                      , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+                      ])
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.lr(body: ({ text(body: text(body: [(]), 
+                                            fill: rgb(18%,80%,25%,100%)), 
+                                       math.frac(denom: text(body: [b]), 
+                                                 num: text(body: [a])), 
+                                       text(body: text(body: [)]), 
+                                            fill: rgb(0%,45%,85%,100%)) })), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/frac-00.out b/test/out/math/frac-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/frac-00.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/frac-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/frac-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/frac-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "x"
+    , Text "="
+    , MFrac (Text "1") (Text "2")
+    , Text "="
+    , MFrac (Text "a") (MGroup Nothing Nothing [ Text "a" , Text "h" ])
+    , Text "="
+    , MFrac (Text "a") (Text "a")
+    , Text "="
+    , MFrac
+        (Text "a") (MGroup Nothing Nothing [ MFrac (Text "1") (Text "2") ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        text(body: [=]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: text(body: [1])), 
+                        text(body: [=]), 
+                        math.frac(denom: { text(body: [a]), 
+                                           text(body: [h]) }, 
+                                  num: text(body: [a])), 
+                        text(body: [=]), 
+                        math.frac(denom: text(body: [a]), 
+                                  num: text(body: [a])), 
+                        text(body: [=]), 
+                        math.frac(denom: math.frac(denom: text(body: [2]), 
+                                                   num: text(body: [1])), 
+                                  num: text(body: [a])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/frac-01.out b/test/out/math/frac-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/frac-01.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/frac-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/frac-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/frac-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MFrac
+        (MGroup
+           (Just "(")
+           (Just ")")
+           [ MGroup (Just "|") (Just "|") [ Text "x" ]
+           , Text "+"
+           , MGroup (Just "|") (Just "|") [ Text "y" ]
+           ])
+        (Text "2")
+    , Text "<"
+    , MFrac
+        (MGroup (Just "[") (Just "]") [ Text "1" , Text "+" , Text "2" ])
+        (Text "3")
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.frac(denom: text(body: [2]), 
+                                  num: { math.lr(body: ({ [|], 
+                                                          text(body: [x]), 
+                                                          [|] })), 
+                                         text(body: [+]), 
+                                         math.lr(body: ({ [|], 
+                                                          text(body: [y]), 
+                                                          [|] })) }), 
+                        text(body: [<]), 
+                        math.frac(denom: text(body: [3]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [1]), 
+                                                        text(body: [+]), 
+                                                        text(body: [2]), 
+                                                        []] }))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/frac-02.out b/test/out/math/frac-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/frac-02.out
@@ -0,0 +1,95 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/frac-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/frac-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/frac-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "x"
+    , Text "="
+    , MFrac
+        (MGroup
+           (Just "(")
+           (Just ")")
+           [ Text "-"
+           , Text "b"
+           , Code
+               "test/typ/math/frac-02.typ"
+               ( line 3 , column 11 )
+               (FieldAccess
+                  (Ident (Identifier "minus")) (Ident (Identifier "plus")))
+           , Code
+               "test/typ/math/frac-02.typ"
+               ( line 3 , column 22 )
+               (FuncCall
+                  (Ident (Identifier "sqrt"))
+                  [ BlockArg
+                      [ MAttach Nothing (Just (Text "2")) (Text "b")
+                      , Text "-"
+                      , Text "4"
+                      , Text "a"
+                      , Text "c"
+                      ]
+                  ])
+           ])
+        (MGroup Nothing Nothing [ Text "2" , Text "a" ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        text(body: [=]), 
+                        math.frac(denom: { text(body: [2]), 
+                                           text(body: [a]) }, 
+                                  num: { text(body: [-]), 
+                                         text(body: [b]), 
+                                         text(body: [±]), 
+                                         math.sqrt(radicand: { math.attach(b: none, 
+                                                                           base: text(body: [b]), 
+                                                                           t: text(body: [2])), 
+                                                               text(body: [-]), 
+                                                               text(body: [4]), 
+                                                               text(body: [a]), 
+                                                               text(body: [c]) }) }) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/frac-03.out b/test/out/math/frac-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/frac-03.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/frac-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/frac-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/frac-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/frac-03.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "binom"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/frac-03.typ"
+                   ( line 3 , column 9 )
+                   (Ident (Identifier "circle"))
+               ]
+           , BlockArg
+               [ Code
+                   "test/typ/math/frac-03.typ"
+                   ( line 3 , column 17 )
+                   (Ident (Identifier "square"))
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.binom(lower: text(body: [□]), 
+                                 upper: text(body: [○])), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/frac-04.out b/test/out/math/frac-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/frac-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/math/frac-05.out b/test/out/math/frac-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/frac-05.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/frac-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/frac-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/frac-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MFrac (MFrac (Text "1") (Text "2")) (Text "3")
+    , Text "="
+    , MFrac
+        (MGroup (Just "(") (Just ")") [ MFrac (Text "1") (Text "2") ])
+        (Text "3")
+    , Text "="
+    , MFrac
+        (Text "1") (MGroup Nothing Nothing [ MFrac (Text "2") (Text "3") ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.frac(denom: text(body: [3]), 
+                                  num: math.frac(denom: text(body: [2]), 
+                                                 num: text(body: [1]))), 
+                        text(body: [=]), 
+                        math.frac(denom: text(body: [3]), 
+                                  num: math.frac(denom: text(body: [2]), 
+                                                 num: text(body: [1]))), 
+                        text(body: [=]), 
+                        math.frac(denom: math.frac(denom: text(body: [3]), 
+                                                   num: text(body: [2])), 
+                                  num: text(body: [1])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/frac-06.out b/test/out/math/frac-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/frac-06.out
@@ -0,0 +1,223 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/frac-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/frac-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/frac-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MFrac
+        (MAttach (Just (Text "1")) Nothing (Text "a"))
+        (MAttach (Just (Text "2")) Nothing (Text "b"))
+    , Text ","
+    , MFrac
+        (Text "1")
+        (MGroup
+           Nothing
+           Nothing
+           [ Text "f" , MGroup (Just "(") (Just ")") [ Text "x" ] ])
+    , Text ","
+    , MFrac
+        (Code
+           "test/typ/math/frac-06.typ"
+           ( line 3 , column 20 )
+           (FuncCall (Ident (Identifier "zeta")) [ BlockArg [ Text "x" ] ]))
+        (Text "2")
+    , Text ","
+    , Text " foo"
+    , MFrac
+        (MGroup
+           (Just "[")
+           (Just "]")
+           [ MGroup (Just "|") (Just "|") [ Text "x" ] ])
+        (Text "2")
+    , HardBreak
+    , MFrac (Text "1.2") (Text "3.7")
+    , Text ","
+    , MAttach Nothing (Just (Text "3.4")) (Text "2.3")
+    , HardBreak
+    , Text "\127987"
+    , Text "\65039"
+    , Text "\8205"
+    , Text "\127752"
+    , MFrac (MGroup (Just "[") (Just "]") [ Text "x" ]) (Text "2")
+    , Text ","
+    , Text "f"
+    , MFrac (MGroup (Just "[") (Just "]") [ Text "x" ]) (Text "2")
+    , Text ","
+    , Code
+        "test/typ/math/frac-06.typ"
+        ( line 5 , column 23 )
+        (Ident (Identifier "phi"))
+    , MFrac (MGroup (Just "[") (Just "]") [ Text "x" ]) (Text "2")
+    , Text ","
+    , Text "\127987"
+    , Text "\65039"
+    , Text "\8205"
+    , Text "\127752"
+    , MFrac (MGroup (Just "[") (Just "]") [ Text "x" ]) (Text "2")
+    , HardBreak
+    , Text "+"
+    , MFrac (MGroup (Just "[") (Just "]") [ Text "x" ]) (Text "2")
+    , Text ","
+    , MFrac
+        (MGroup
+           Nothing
+           Nothing
+           [ Text "1" , MGroup (Just "(") (Just ")") [ Text "x" ] ])
+        (Text "2")
+    , Text ","
+    , Text "2"
+    , MFrac (MGroup (Just "[") (Just "]") [ Text "x" ]) (Text "2")
+    , MGroup
+        Nothing
+        Nothing
+        [ HardBreak , MGroup (Just "(") (Just ")") [ Text "a" ] ]
+    , MFrac (Text "b") (Text "2")
+    , Text ","
+    , MGroup
+        Nothing
+        Nothing
+        [ Text "b" , MGroup (Just "(") (Just ")") [ Text "a" ] ]
+    , MFrac (MGroup (Just "[") (Just "]") [ Text "b" ]) (Text "2")
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.frac(denom: math.attach(b: text(body: [2]), 
+                                                     base: text(body: [b]), 
+                                                     t: none), 
+                                  num: math.attach(b: text(body: [1]), 
+                                                   base: text(body: [a]), 
+                                                   t: none)), 
+                        text(body: [,]), 
+                        math.frac(denom: { text(body: [f]), 
+                                           math.lr(body: ({ [(], 
+                                                            text(body: [x]), 
+                                                            [)] })) }, 
+                                  num: text(body: [1])), 
+                        text(body: [,]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: { text(body: [ζ]), 
+                                         text(body: [(]), 
+                                         text(body: [x]), 
+                                         text(body: [)]) }), 
+                        text(body: [,]), 
+                        text(body: [ foo]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        math.lr(body: ({ [|], 
+                                                                         text(body: [x]), 
+                                                                         [|] })), 
+                                                        []] }))), 
+                        linebreak(), 
+                        math.frac(denom: text(body: [3.7]), 
+                                  num: text(body: [1.2])), 
+                        text(body: [,]), 
+                        math.attach(b: none, 
+                                    base: text(body: [2.3]), 
+                                    t: text(body: [3.4])), 
+                        linebreak(), 
+                        text(body: [🏳]), 
+                        text(body: [️]), 
+                        text(body: [‍]), 
+                        text(body: [🌈]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [x]), 
+                                                        []] }))), 
+                        text(body: [,]), 
+                        text(body: [f]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [x]), 
+                                                        []] }))), 
+                        text(body: [,]), 
+                        text(body: [φ]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [x]), 
+                                                        []] }))), 
+                        text(body: [,]), 
+                        text(body: [🏳]), 
+                        text(body: [️]), 
+                        text(body: [‍]), 
+                        text(body: [🌈]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [x]), 
+                                                        []] }))), 
+                        linebreak(), 
+                        text(body: [+]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [x]), 
+                                                        []] }))), 
+                        text(body: [,]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: { text(body: [1]), 
+                                         math.lr(body: ({ [(], 
+                                                          text(body: [x]), 
+                                                          [)] })) }), 
+                        text(body: [,]), 
+                        text(body: [2]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [x]), 
+                                                        []] }))), 
+                        linebreak(), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [a]), 
+                                         [)] })), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: text(body: [b])), 
+                        text(body: [,]), 
+                        text(body: [b]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [a]), 
+                                         [)] })), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: math.lr(body: ({ [[], 
+                                                        text(body: [b]), 
+                                                        []] }))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-00.out b/test/out/math/matrix-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-00.out
@@ -0,0 +1,157 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/matrix-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center")) ])
+, SoftBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/matrix-00.typ"
+        ( line 4 , column 2 )
+        (FuncCall (Ident (Identifier "mat")) [])
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 4 , column 8 )
+        (Ident (Identifier "dot"))
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 5 , column 2 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg [ [ MGroup Nothing Nothing [] ] ] ])
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 5 , column 9 )
+        (Ident (Identifier "dot"))
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 6 , column 2 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ BlockArg [ Text "1" ] , BlockArg [ Text "2" ] ])
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 6 , column 12 )
+        (Ident (Identifier "dot"))
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 7 , column 2 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg [ [ Text "1" , Text "2" ] ] ])
+    , HardBreak
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 8 , column 2 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg [ [ Text "1" ] , [ Text "2" ] ] ])
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 8 , column 12 )
+        (Ident (Identifier "dot"))
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 9 , column 2 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg [ [ Text "1" , Text "2" ] , [ Text "3" , Text "4" ] ] ])
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 9 , column 18 )
+        (Ident (Identifier "dot"))
+    , Code
+        "test/typ/math/matrix-00.typ"
+        ( line 10 , column 2 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup
+                     Nothing Nothing [ Text "1" , Text "+" , MAlignPoint , Text "2" ]
+                 , MFrac (Text "1") (Text "2")
+                 ]
+               , [ MGroup Nothing Nothing [ MAlignPoint , Text "3" ] , Text "4" ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: { math.mat(rows: ()), 
+                        text(body: [⋅]), 
+                        math.mat(rows: (({  }))), 
+                        text(body: [⋅]), 
+                        math.mat(rows: ((text(body: [1]), 
+                                         text(body: [2])))), 
+                        text(body: [⋅]), 
+                        math.mat(rows: ((text(body: [1]), 
+                                         text(body: [2])))), 
+                        linebreak(), 
+                        math.mat(rows: ((text(body: [1])), 
+                                        (text(body: [2])))), 
+                        text(body: [⋅]), 
+                        math.mat(rows: ((text(body: [1]), 
+                                         text(body: [2])), 
+                                        (text(body: [3]), 
+                                         text(body: [4])))), 
+                        text(body: [⋅]), 
+                        math.mat(rows: (({ text(body: [1]), 
+                                           text(body: [+]), 
+                                           math.alignpoint(), 
+                                           text(body: [2]) }, 
+                                         math.frac(denom: text(body: [2]), 
+                                                   num: text(body: [1]))), 
+                                        ({ math.alignpoint(), 
+                                           text(body: [3]) }, 
+                                         text(body: [4])))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-01.out b/test/out/math/matrix-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-01.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-01.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ Text "1" , Text "2" , Text "\8230" , Text "10" ]
+               , [ Text "2" , Text "2" , Text "\8230" , Text "10" ]
+               , [ Code
+                     "test/typ/math/matrix-01.typ"
+                     ( line 6 , column 3 )
+                     (FieldAccess (Ident (Identifier "v")) (Ident (Identifier "dots")))
+                 , Code
+                     "test/typ/math/matrix-01.typ"
+                     ( line 6 , column 11 )
+                     (FieldAccess (Ident (Identifier "v")) (Ident (Identifier "dots")))
+                 , Code
+                     "test/typ/math/matrix-01.typ"
+                     ( line 6 , column 19 )
+                     (FieldAccess
+                        (Ident (Identifier "down")) (Ident (Identifier "dots")))
+                 , Code
+                     "test/typ/math/matrix-01.typ"
+                     ( line 6 , column 30 )
+                     (FieldAccess (Ident (Identifier "v")) (Ident (Identifier "dots")))
+                 ]
+               , [ Text "10" , Text "10" , Text "\8230" , Text "10" ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: ((text(body: [1]), 
+                                       text(body: [2]), 
+                                       text(body: […]), 
+                                       text(body: [10])), 
+                                      (text(body: [2]), 
+                                       text(body: [2]), 
+                                       text(body: […]), 
+                                       text(body: [10])), 
+                                      (text(body: [⋮]), 
+                                       text(body: [⋮]), 
+                                       text(body: [⋱]), 
+                                       text(body: [⋮])), 
+                                      (text(body: [10]), 
+                                       text(body: [10]), 
+                                       text(body: […]), 
+                                       text(body: [10])))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-02.out b/test/out/math/matrix-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-02.out
@@ -0,0 +1,104 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-02.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ Text "a" , MAttach Nothing (Just (Text "2")) (Text "b") ]
+               , [ MGroup
+                     Nothing
+                     Nothing
+                     [ MAttach
+                         (Just (MGroup Nothing Nothing [ Text "x" , HardBreak , Text "y" ]))
+                         Nothing
+                         (Code
+                            "test/typ/math/matrix-02.typ"
+                            ( line 5 , column 3 )
+                            (Ident (Identifier "sum")))
+                     , Text "x"
+                     ]
+                 , MAttach
+                     Nothing
+                     (Just (MGroup Nothing Nothing [ MFrac (Text "1") (Text "2") ]))
+                     (Text "a")
+                 ]
+               , [ Code
+                     "test/typ/math/matrix-02.typ"
+                     ( line 6 , column 3 )
+                     (Ident (Identifier "zeta"))
+                 , Code
+                     "test/typ/math/matrix-02.typ"
+                     ( line 6 , column 9 )
+                     (Ident (Identifier "alpha"))
+                 ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: ((text(body: [a]), 
+                                       math.attach(b: none, 
+                                                   base: text(body: [b]), 
+                                                   t: text(body: [2]))), 
+                                      ({ math.attach(b: { text(body: [x]), 
+                                                          linebreak(), 
+                                                          text(body: [y]) }, 
+                                                     base: text(body: [∑]), 
+                                                     t: none), 
+                                         text(body: [x]) }, 
+                                       math.attach(b: none, 
+                                                   base: text(body: [a]), 
+                                                   t: math.frac(denom: text(body: [2]), 
+                                                                num: text(body: [1])))), 
+                                      (text(body: [ζ]), 
+                                       text(body: [α])))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-03.out b/test/out/math/matrix-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-03.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/matrix-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (FieldAccess
+          (Ident (Identifier "mat")) (Ident (Identifier "math")))
+       [ KeyValArg (Identifier "delim") (Literal (String "[")) ])
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-03.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg [ [ Text "1" , Text "2" ] , [ Text "3" , Text "4" ] ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "a"
+    , Text "+"
+    , Code
+        "test/typ/math/matrix-03.typ"
+        ( line 5 , column 7 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ KeyValArg (Identifier "delim") (Literal None)
+           , ArrayArg [ [ Text "1" , Text "2" ] , [ Text "3" , Text "4" ] ]
+           ])
+    , Text "+"
+    , Text "b"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: ((text(body: [1]), 
+                                       text(body: [2])), 
+                                      (text(body: [3]), 
+                                       text(body: [4])))), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        math.mat(rows: ((text(body: [1]), 
+                                         text(body: [2])), 
+                                        (text(body: [3]), 
+                                         text(body: [4])))), 
+                        text(body: [+]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-04.out b/test/out/math/matrix-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-04.out
@@ -0,0 +1,249 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/matrix-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center")) ])
+, SoftBreak
+, Code
+    "test/typ/math/matrix-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 3))
+       , KeyValArg (Identifier "gutter") (Literal (Numeric 10.0 Pt))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 8 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ BlockArg [ Text "1" ]
+                            , BlockArg [ Text "2" ]
+                            , KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 9 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ ArrayArg [ [ Text "1" , Text "2" ] ]
+                            , KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 10 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            , BlockArg [ Text "1" ]
+                            , BlockArg [ Text "2" ]
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 12 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ ArrayArg [ [ Text "1" ] , [ Text "2" ] ]
+                            , KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 13 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ ArrayArg [ [ Text "1" ] ]
+                            , KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            , BlockArg [ Text "2" ]
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 14 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            , ArrayArg [ [ Text "1" ] , [ Text "2" ] ]
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 16 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ ArrayArg [ [ Text "1" , Text "2" ] ]
+                            , KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            , BlockArg [ Text "3" ]
+                            , BlockArg [ Text "4" ]
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 17 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            , ArrayArg [ [ Text "1" , Text "2" ] , [ Text "3" , Text "4" ] ]
+                            ])
+                     ]
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     True
+                     [ Code
+                         "test/typ/math/matrix-04.typ"
+                         ( line 18 , column 5 )
+                         (FuncCall
+                            (Ident (Identifier "mat"))
+                            [ ArrayArg [ [ Text "1" , Text "2" ] , [ Text "3" , Text "4" ] ]
+                            , KeyValArg (Identifier "delim") (Block (Content [ Text " [" ]))
+                            ])
+                     ]
+                 ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1]), 
+                                                       text(body: [2])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1]), 
+                                                       text(body: [2])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1]), 
+                                                       text(body: [2])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1])), 
+                                                      (text(body: [2])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1])), 
+                                                      (text(body: [2])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1])), 
+                                                      (text(body: [2])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1]), 
+                                                       text(body: [2])), 
+                                                      (text(body: [3]), 
+                                                       text(body: [4])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1]), 
+                                                       text(body: [2])), 
+                                                      (text(body: [3]), 
+                                                       text(body: [4])))), 
+                                numbering: none), 
+                  math.equation(block: true, 
+                                body: math.mat(rows: ((text(body: [1]), 
+                                                       text(body: [2])), 
+                                                      (text(body: [3]), 
+                                                       text(body: [4])))), 
+                                numbering: none)), 
+       columns: 3, 
+       gutter: 10.0pt), 
+  parbreak() }
diff --git a/test/out/math/matrix-05.out b/test/out/math/matrix-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/math/matrix-alignment-00.out b/test/out/math/matrix-alignment-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-alignment-00.out
@@ -0,0 +1,95 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-alignment-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-alignment-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-alignment-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-00.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "vec"))
+           [ BlockArg
+               [ Text " a "
+               , MAlignPoint
+               , Text " a a a "
+               , MAlignPoint
+               , Text " a a"
+               ]
+           , BlockArg
+               [ Text " a a "
+               , MAlignPoint
+               , Text " a a "
+               , MAlignPoint
+               , Text " a"
+               ]
+           , BlockArg
+               [ Text " a a a "
+               , MAlignPoint
+               , Text " a "
+               , MAlignPoint
+               , Text " a a a"
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.vec(children: ({ text(body: [ a ]), 
+                                            math.alignpoint(), 
+                                            text(body: [ a a a ]), 
+                                            math.alignpoint(), 
+                                            text(body: [ a a]) }, 
+                                          { text(body: [ a a ]), 
+                                            math.alignpoint(), 
+                                            text(body: [ a a ]), 
+                                            math.alignpoint(), 
+                                            text(body: [ a]) }, 
+                                          { text(body: [ a a a ]), 
+                                            math.alignpoint(), 
+                                            text(body: [ a ]), 
+                                            math.alignpoint(), 
+                                            text(body: [ a a a]) })), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-alignment-01.out b/test/out/math/matrix-alignment-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-alignment-01.out
@@ -0,0 +1,106 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-alignment-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-alignment-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-alignment-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-01.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup
+                     Nothing
+                     Nothing
+                     [ Text " a "
+                     , MAlignPoint
+                     , Text " a a a "
+                     , MAlignPoint
+                     , Text " a a"
+                     ]
+                 ]
+               , [ MGroup
+                     Nothing
+                     Nothing
+                     [ Text " a a "
+                     , MAlignPoint
+                     , Text " a a "
+                     , MAlignPoint
+                     , Text " a"
+                     ]
+                 ]
+               , [ MGroup
+                     Nothing
+                     Nothing
+                     [ Text " a a a "
+                     , MAlignPoint
+                     , Text " a "
+                     , MAlignPoint
+                     , Text " a a a"
+                     ]
+                 ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ text(body: [ a ]), 
+                                         math.alignpoint(), 
+                                         text(body: [ a a a ]), 
+                                         math.alignpoint(), 
+                                         text(body: [ a a]) }), 
+                                      ({ text(body: [ a a ]), 
+                                         math.alignpoint(), 
+                                         text(body: [ a a ]), 
+                                         math.alignpoint(), 
+                                         text(body: [ a]) }), 
+                                      ({ text(body: [ a a a ]), 
+                                         math.alignpoint(), 
+                                         text(body: [ a ]), 
+                                         math.alignpoint(), 
+                                         text(body: [ a a a]) }))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-alignment-02.out b/test/out/math/matrix-alignment-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-alignment-02.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-alignment-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-alignment-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-alignment-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-02.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ Text " a" , Text " a a a" , Text " a a" ]
+               , [ Text " a a" , Text " a a" , Text " a" ]
+               , [ Text " a a a" , Text " a" , Text " a a a" ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: ((text(body: [ a]), 
+                                       text(body: [ a a a]), 
+                                       text(body: [ a a])), 
+                                      (text(body: [ a a]), 
+                                       text(body: [ a a]), 
+                                       text(body: [ a])), 
+                                      (text(body: [ a a a]), 
+                                       text(body: [ a]), 
+                                       text(body: [ a a a])))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-alignment-03.out b/test/out/math/matrix-alignment-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-alignment-03.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-alignment-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-alignment-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-alignment-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-03.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup Nothing Nothing [ MAlignPoint , Text "a" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "a a a" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "a a" ]
+                 ]
+               , [ MGroup Nothing Nothing [ MAlignPoint , Text "a a" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "a a" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "a" ]
+                 ]
+               , [ MGroup Nothing Nothing [ MAlignPoint , Text "a a a" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "a" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "a a a" ]
+                 ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ math.alignpoint(), 
+                                         text(body: [a]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [a a a]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [a a]) }), 
+                                      ({ math.alignpoint(), 
+                                         text(body: [a a]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [a a]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [a]) }), 
+                                      ({ math.alignpoint(), 
+                                         text(body: [a a a]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [a]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [a a a]) }))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-alignment-04.out b/test/out/math/matrix-alignment-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-alignment-04.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-alignment-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-alignment-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-alignment-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-04.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup Nothing Nothing [ Text " a" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text " a a a" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text " a a" , MAlignPoint ]
+                 ]
+               , [ MGroup Nothing Nothing [ Text " a a" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text " a a" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text " a" , MAlignPoint ]
+                 ]
+               , [ MGroup Nothing Nothing [ Text " a a a" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text " a" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text " a a a" , MAlignPoint ]
+                 ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ text(body: [ a]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [ a a a]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [ a a]), 
+                                         math.alignpoint() }), 
+                                      ({ text(body: [ a a]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [ a a]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [ a]), 
+                                         math.alignpoint() }), 
+                                      ({ text(body: [ a a a]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [ a]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [ a a a]), 
+                                         math.alignpoint() }))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-alignment-05.out b/test/out/math/matrix-alignment-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-alignment-05.out
@@ -0,0 +1,217 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-alignment-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-alignment-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-alignment-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-05.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup
+                     Nothing Nothing [ MAlignPoint , Text "a" , Text "+" , Text "b" ]
+                 , Text "c"
+                 ]
+               , [ MGroup Nothing Nothing [ MAlignPoint , Text "d" ] , Text "e" ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-05.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup
+                     Nothing
+                     Nothing
+                     [ MAlignPoint , Text "a" , Text "+" , Text "b" , MAlignPoint ]
+                 , Text "c"
+                 ]
+               , [ MGroup Nothing Nothing [ MAlignPoint , Text "d" , MAlignPoint ]
+                 , Text "e"
+                 ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-05.typ"
+        ( line 5 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup
+                     Nothing
+                     Nothing
+                     [ MAlignPoint
+                     , MAlignPoint
+                     , MAlignPoint
+                     , Text "a"
+                     , Text "+"
+                     , Text "b"
+                     ]
+                 , Text "c"
+                 ]
+               , [ MGroup
+                     Nothing
+                     Nothing
+                     [ MAlignPoint , MAlignPoint , MAlignPoint , Text "d" ]
+                 , Text "e"
+                 ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-05.typ"
+        ( line 6 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup
+                     Nothing
+                     Nothing
+                     [ Text "."
+                     , MAlignPoint
+                     , Text "a"
+                     , Text "+"
+                     , Text "b"
+                     , MAlignPoint
+                     , Text "."
+                     ]
+                 , Text "c"
+                 ]
+               , [ MGroup
+                     Nothing
+                     Nothing
+                     [ Text "\8230"
+                     , Text "."
+                     , Text "."
+                     , MAlignPoint
+                     , Text "d"
+                     , MAlignPoint
+                     , Text "\8230"
+                     , Text "."
+                     , Text "."
+                     ]
+                 , Text "e"
+                 ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ math.alignpoint(), 
+                                         text(body: [a]), 
+                                         text(body: [+]), 
+                                         text(body: [b]) }, 
+                                       text(body: [c])), 
+                                      ({ math.alignpoint(), 
+                                         text(body: [d]) }, 
+                                       text(body: [e])))), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ math.alignpoint(), 
+                                         text(body: [a]), 
+                                         text(body: [+]), 
+                                         text(body: [b]), 
+                                         math.alignpoint() }, 
+                                       text(body: [c])), 
+                                      ({ math.alignpoint(), 
+                                         text(body: [d]), 
+                                         math.alignpoint() }, 
+                                       text(body: [e])))), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ math.alignpoint(), 
+                                         math.alignpoint(), 
+                                         math.alignpoint(), 
+                                         text(body: [a]), 
+                                         text(body: [+]), 
+                                         text(body: [b]) }, 
+                                       text(body: [c])), 
+                                      ({ math.alignpoint(), 
+                                         math.alignpoint(), 
+                                         math.alignpoint(), 
+                                         text(body: [d]) }, 
+                                       text(body: [e])))), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ text(body: [.]), 
+                                         math.alignpoint(), 
+                                         text(body: [a]), 
+                                         text(body: [+]), 
+                                         text(body: [b]), 
+                                         math.alignpoint(), 
+                                         text(body: [.]) }, 
+                                       text(body: [c])), 
+                                      ({ text(body: […]), 
+                                         text(body: [.]), 
+                                         text(body: [.]), 
+                                         math.alignpoint(), 
+                                         text(body: [d]), 
+                                         math.alignpoint(), 
+                                         text(body: […]), 
+                                         text(body: [.]), 
+                                         text(body: [.]) }, 
+                                       text(body: [e])))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/matrix-alignment-06.out b/test/out/math/matrix-alignment-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/matrix-alignment-06.out
@@ -0,0 +1,220 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/matrix-alignment-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/matrix-alignment-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/matrix-alignment-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-06.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup Nothing Nothing [ Text "-" , Text "1" ]
+                 , Text "1"
+                 , Text "1"
+                 ]
+               , [ Text "1"
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" ]
+                 , Text "1"
+                 ]
+               , [ Text "1"
+                 , Text "1"
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" ]
+                 ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-06.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup Nothing Nothing [ Text "-" , Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 ]
+               , [ MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 ]
+               , [ MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" , MAlignPoint ]
+                 ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-06.typ"
+        ( line 5 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup Nothing Nothing [ Text "-" , Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 , MGroup Nothing Nothing [ Text "1" , MAlignPoint ]
+                 ]
+               , [ Text "1"
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" ]
+                 , Text "1"
+                 ]
+               , [ Text "1"
+                 , Text "1"
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" ]
+                 ]
+               ]
+           ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/matrix-alignment-06.typ"
+        ( line 6 , column 3 )
+        (FuncCall
+           (Ident (Identifier "mat"))
+           [ ArrayArg
+               [ [ MGroup Nothing Nothing [ MAlignPoint , Text "-" , Text "1" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "1" ]
+                 , MGroup Nothing Nothing [ MAlignPoint , Text "1" ]
+                 ]
+               , [ Text "1"
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" ]
+                 , Text "1"
+                 ]
+               , [ Text "1"
+                 , Text "1"
+                 , MGroup Nothing Nothing [ Text "-" , Text "1" ]
+                 ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ text(body: [-]), 
+                                         text(body: [1]) }, 
+                                       text(body: [1]), 
+                                       text(body: [1])), 
+                                      (text(body: [1]), 
+                                       { text(body: [-]), 
+                                         text(body: [1]) }, 
+                                       text(body: [1])), 
+                                      (text(body: [1]), 
+                                       text(body: [1]), 
+                                       { text(body: [-]), 
+                                         text(body: [1]) }))), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ text(body: [-]), 
+                                         text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [1]), 
+                                         math.alignpoint() }), 
+                                      ({ text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [-]), 
+                                         text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [1]), 
+                                         math.alignpoint() }), 
+                                      ({ text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [-]), 
+                                         text(body: [1]), 
+                                         math.alignpoint() }))), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ text(body: [-]), 
+                                         text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [1]), 
+                                         math.alignpoint() }, 
+                                       { text(body: [1]), 
+                                         math.alignpoint() }), 
+                                      (text(body: [1]), 
+                                       { text(body: [-]), 
+                                         text(body: [1]) }, 
+                                       text(body: [1])), 
+                                      (text(body: [1]), 
+                                       text(body: [1]), 
+                                       { text(body: [-]), 
+                                         text(body: [1]) }))), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.mat(rows: (({ math.alignpoint(), 
+                                         text(body: [-]), 
+                                         text(body: [1]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [1]) }, 
+                                       { math.alignpoint(), 
+                                         text(body: [1]) }), 
+                                      (text(body: [1]), 
+                                       { text(body: [-]), 
+                                         text(body: [1]) }, 
+                                       text(body: [1])), 
+                                      (text(body: [1]), 
+                                       text(body: [1]), 
+                                       { text(body: [-]), 
+                                         text(body: [1]) }))), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/multiline-00.out b/test/out/math/multiline-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-00.out
@@ -0,0 +1,101 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "x"
+    , MAlignPoint
+    , Text "="
+    , Text "x"
+    , Text "+"
+    , Text "y"
+    , HardBreak
+    , MAlignPoint
+    , Text "="
+    , Text "x"
+    , Text "+"
+    , Text "2"
+    , Text "z"
+    , HardBreak
+    , MAlignPoint
+    , Text "="
+    , Code
+        "test/typ/math/multiline-00.typ"
+        ( line 5 , column 8 )
+        (Ident (Identifier "sum"))
+    , Text "x"
+    , Code
+        "test/typ/math/multiline-00.typ"
+        ( line 5 , column 14 )
+        (Ident (Identifier "dot"))
+    , Text "2"
+    , Text "z"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [x]), 
+                        text(body: [+]), 
+                        text(body: [y]), 
+                        linebreak(), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [x]), 
+                        text(body: [+]), 
+                        text(body: [2]), 
+                        text(body: [z]), 
+                        linebreak(), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [∑]), 
+                        text(body: [x]), 
+                        text(body: [⋅]), 
+                        text(body: [2]), 
+                        text(body: [z]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/multiline-01.out b/test/out/math/multiline-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-01.out
@@ -0,0 +1,112 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "x"
+    , Text "+"
+    , Text "1"
+    , MAlignPoint
+    , Text "="
+    , MAttach Nothing (Just (Text "2")) (Text "a")
+    , Text "+"
+    , MAttach Nothing (Just (Text "2")) (Text "b")
+    , HardBreak
+    , Text "y"
+    , MAlignPoint
+    , Text "="
+    , Text "a"
+    , Text "+"
+    , MAttach Nothing (Just (Text "2")) (Text "b")
+    , HardBreak
+    , Text "z"
+    , MAlignPoint
+    , Text "="
+    , Code
+        "test/typ/math/multiline-01.typ"
+        ( line 5 , column 12 )
+        (Ident (Identifier "alpha"))
+    , Code
+        "test/typ/math/multiline-01.typ"
+        ( line 5 , column 18 )
+        (Ident (Identifier "dot"))
+    , Code
+        "test/typ/math/multiline-01.typ"
+        ( line 5 , column 22 )
+        (Ident (Identifier "beta"))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        text(body: [+]), 
+                        text(body: [1]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        math.attach(b: none, 
+                                    base: text(body: [a]), 
+                                    t: text(body: [2])), 
+                        text(body: [+]), 
+                        math.attach(b: none, 
+                                    base: text(body: [b]), 
+                                    t: text(body: [2])), 
+                        linebreak(), 
+                        text(body: [y]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [a]), 
+                        text(body: [+]), 
+                        math.attach(b: none, 
+                                    base: text(body: [b]), 
+                                    t: text(body: [2])), 
+                        linebreak(), 
+                        text(body: [z]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [α]), 
+                        text(body: [⋅]), 
+                        text(body: [β]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/multiline-02.out b/test/out/math/multiline-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-02.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "a"
+    , Text "+"
+    , Text "b"
+    , MAlignPoint
+    , Text "="
+    , Text "2"
+    , Text "+"
+    , Text "3"
+    , MAlignPoint
+    , Text "="
+    , Text "5"
+    , HardBreak
+    , Text "b"
+    , MAlignPoint
+    , Text "="
+    , Text "c"
+    , MAlignPoint
+    , Text "="
+    , Text "3"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        text(body: [b]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [2]), 
+                        text(body: [+]), 
+                        text(body: [3]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [5]), 
+                        linebreak(), 
+                        text(body: [b]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [c]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [3]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/multiline-03.out b/test/out/math/multiline-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-03.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "f"
+    , Text ":"
+    , Text "="
+    , Code
+        "test/typ/math/multiline-03.typ"
+        ( line 3 , column 8 )
+        (FuncCall
+           (Ident (Identifier "cases"))
+           [ BlockArg
+               [ Text "1"
+               , Text "+"
+               , Text "2"
+               , MAlignPoint
+               , Text "iff "
+               , MAlignPoint
+               , Text "x"
+               ]
+           , BlockArg
+               [ Text "3" , MAlignPoint , Text "if " , MAlignPoint , Text "y" ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [f]), 
+                        text(body: [:]), 
+                        text(body: [=]), 
+                        math.cases(children: ({ text(body: [1]), 
+                                                text(body: [+]), 
+                                                text(body: [2]), 
+                                                math.alignpoint(), 
+                                                text(body: [iff ]), 
+                                                math.alignpoint(), 
+                                                text(body: [x]) }, 
+                                              { text(body: [3]), 
+                                                math.alignpoint(), 
+                                                text(body: [if ]), 
+                                                math.alignpoint(), 
+                                                text(body: [y]) })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/multiline-04.out b/test/out/math/multiline-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-04.out
@@ -0,0 +1,79 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text " abc "
+    , MAlignPoint
+    , Text "="
+    , Text "c"
+    , HardBreak
+    , MAlignPoint
+    , Text "="
+    , Text "d"
+    , Text "+"
+    , Text "1"
+    , HardBreak
+    , Text "="
+    , Text "x"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [ abc ]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [c]), 
+                        linebreak(), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [d]), 
+                        text(body: [+]), 
+                        text(body: [1]), 
+                        linebreak(), 
+                        text(body: [=]), 
+                        text(body: [x]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/multiline-05.out b/test/out/math/multiline-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-05.out
@@ -0,0 +1,113 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Text "n"
+              , Code
+                  "test/typ/math/multiline-05.typ"
+                  ( line 3 , column 10 )
+                  (Ident (Identifier "in"))
+              , Code
+                  "test/typ/math/multiline-05.typ"
+                  ( line 3 , column 13 )
+                  (Ident (Identifier "NN"))
+              , HardBreak
+              , Text "n"
+              , Text "\8804"
+              , Text "5"
+              ]))
+        Nothing
+        (Code
+           "test/typ/math/multiline-05.typ"
+           ( line 3 , column 3 )
+           (Ident (Identifier "sum")))
+    , Text "n"
+    , Text "="
+    , MFrac
+        (MGroup
+           (Just "(")
+           (Just ")")
+           [ MGroup
+               Nothing
+               Nothing
+               [ Text "5"
+               , MGroup (Just "(") (Just ")") [ Text "5" , Text "+" , Text "1" ]
+               ]
+           ])
+        (Text "2")
+    , Text "="
+    , Text "15"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: { text(body: [n]), 
+                                         text(body: [∈]), 
+                                         text(body: [ℕ]), 
+                                         linebreak(), 
+                                         text(body: [n]), 
+                                         text(body: [≤]), 
+                                         text(body: [5]) }, 
+                                    base: text(body: [∑]), 
+                                    t: none), 
+                        text(body: [n]), 
+                        text(body: [=]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: { text(body: [5]), 
+                                         math.lr(body: ({ [(], 
+                                                          text(body: [5]), 
+                                                          text(body: [+]), 
+                                                          text(body: [1]), 
+                                                          [)] })) }), 
+                        text(body: [=]), 
+                        text(body: [15]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/multiline-06.out b/test/out/math/multiline-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-06.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True [ Text " abc " , MAlignPoint , Text "=" , Text "c" ]
+, SoftBreak
+, Text "No"
+, Space
+, Text "trailing"
+, Space
+, Text "line"
+, Space
+, Text "break"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [ abc ]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [c]) }, 
+                numbering: none), 
+  text(body: [
+No trailing line break.]), 
+  parbreak() }
diff --git a/test/out/math/multiline-07.out b/test/out/math/multiline-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-07.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text " abc " , MAlignPoint , Text "=" , Text "c" , HardBreak ]
+, SoftBreak
+, Text "One"
+, Space
+, Text "trailing"
+, Space
+, Text "line"
+, Space
+, Text "break"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [ abc ]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [c]), 
+                        linebreak() }, 
+                numbering: none), 
+  text(body: [
+One trailing line break.]), 
+  parbreak() }
diff --git a/test/out/math/multiline-08.out b/test/out/math/multiline-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/multiline-08.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/multiline-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/multiline-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/multiline-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text " abc "
+    , MAlignPoint
+    , Text "="
+    , Text "c"
+    , HardBreak
+    , HardBreak
+    , HardBreak
+    ]
+, SoftBreak
+, Text "Multiple"
+, Space
+, Text "trailing"
+, Space
+, Text "line"
+, Space
+, Text "breaks"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [ abc ]), 
+                        math.alignpoint(), 
+                        text(body: [=]), 
+                        text(body: [c]), 
+                        linebreak(), 
+                        linebreak(), 
+                        linebreak() }, 
+                numbering: none), 
+  text(body: [
+Multiple trailing line breaks.]), 
+  parbreak() }
diff --git a/test/out/math/numbering-00.out b/test/out/math/numbering-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/numbering-00.out
@@ -0,0 +1,187 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/numbering-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/numbering-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/numbering-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/math/numbering-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 150.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/math/numbering-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (FieldAccess
+          (Ident (Identifier "equation")) (Ident (Identifier "math")))
+       [ KeyValArg (Identifier "numbering") (Literal (String "(I)")) ])
+, ParBreak
+, Text "We"
+, Space
+, Text "define"
+, Space
+, Equation False [ Text "x" ]
+, Space
+, Text "in"
+, Space
+, Text "preparation"
+, Space
+, Text "of"
+, Space
+, Ref "fib" (Literal Auto)
+, Text ":"
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/numbering-00.typ"
+        ( line 6 , column 3 )
+        (FieldAccess (Ident (Identifier "alt")) (Ident (Identifier "phi")))
+    , Text ":"
+    , Text "="
+    , MFrac
+        (MGroup
+           (Just "(")
+           (Just ")")
+           [ Text "1"
+           , Text "+"
+           , Code
+               "test/typ/math/numbering-00.typ"
+               ( line 6 , column 19 )
+               (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "5" ] ])
+           ])
+        (Text "2")
+    ]
+, Space
+, Code
+    "test/typ/math/numbering-00.typ"
+    ( line 6 , column 34 )
+    (Label "ratio")
+, ParBreak
+, Text "With"
+, Space
+, Ref "ratio" (Literal Auto)
+, Text ","
+, Space
+, Text "we"
+, Space
+, Text "get"
+, SoftBreak
+, Equation
+    True
+    [ MAttach (Just (Text "n")) Nothing (Text "F")
+    , Text "="
+    , Code
+        "test/typ/math/numbering-00.typ"
+        ( line 9 , column 9 )
+        (FuncCall
+           (Ident (Identifier "round"))
+           [ BlockArg
+               [ MFrac
+                   (Text "1")
+                   (Code
+                      "test/typ/math/numbering-00.typ"
+                      ( line 9 , column 19 )
+                      (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "5" ] ]))
+               , MAttach
+                   Nothing
+                   (Just (Text "n"))
+                   (Code
+                      "test/typ/math/numbering-00.typ"
+                      ( line 9 , column 27 )
+                      (FieldAccess
+                         (Ident (Identifier "alt")) (Ident (Identifier "phi"))))
+               ]
+           ])
+    ]
+, Space
+, Code
+    "test/typ/math/numbering-00.typ"
+    ( line 9 , column 40 )
+    (Label "fib")
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [We define ]), 
+  math.equation(block: false, 
+                body: text(body: [x]), 
+                numbering: none), 
+  text(body: [ in preparation of ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [:
+]), 
+  math.equation(block: true, 
+                body: { text(body: [ϕ]), 
+                        text(body: [:]), 
+                        text(body: [=]), 
+                        math.frac(denom: text(body: [2]), 
+                                  num: { text(body: [1]), 
+                                         text(body: [+]), 
+                                         math.sqrt(radicand: text(body: [5])) }) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  <ratio>, 
+  parbreak(), 
+  text(body: [With ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, we get
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: text(body: [n]), 
+                                    base: text(body: [F]), 
+                                    t: none), 
+                        text(body: [=]), 
+                        math.round(body: { math.frac(denom: math.sqrt(radicand: text(body: [5])), 
+                                                     num: text(body: [1])), 
+                                           math.attach(b: none, 
+                                                       base: text(body: [ϕ]), 
+                                                       t: text(body: [n])) }) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  <fib>, 
+  parbreak() }
diff --git a/test/out/math/op-00.out b/test/out/math/op-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/op-00.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/op-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/op-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/op-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Text "1" , Text "\8804" , Text "n" , Text "\8804" , Text "m" ]))
+        Nothing
+        (Code
+           "test/typ/math/op-00.typ"
+           ( line 3 , column 3 )
+           (Ident (Identifier "max")))
+    , Text "n"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: { text(body: [1]), 
+                                         text(body: [≤]), 
+                                         text(body: [n]), 
+                                         text(body: [≤]), 
+                                         text(body: [m]) }, 
+                                    base: math.op(limits: true, 
+                                                  text: "max"), 
+                                    t: none), 
+                        text(body: [n]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/op-01.out b/test/out/math/op-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/op-01.out
@@ -0,0 +1,114 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/op-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/op-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/op-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAlignPoint
+    , Code
+        "test/typ/math/op-01.typ"
+        ( line 3 , column 5 )
+        (Ident (Identifier "sin"))
+    , Text "x"
+    , Text "+"
+    , MAttach
+        (Just (Text "2"))
+        Nothing
+        (Code
+           "test/typ/math/op-01.typ"
+           ( line 3 , column 13 )
+           (Ident (Identifier "log")))
+    , Text "x"
+    , HardBreak
+    , Text "="
+    , MAlignPoint
+    , Code
+        "test/typ/math/op-01.typ"
+        ( line 4 , column 5 )
+        (FuncCall (Ident (Identifier "sin")) [ BlockArg [ Text "x" ] ])
+    , Text "+"
+    , MGroup
+        Nothing
+        Nothing
+        [ MAttach
+            (Just (Text "2"))
+            Nothing
+            (Code
+               "test/typ/math/op-01.typ"
+               ( line 4 , column 14 )
+               (Ident (Identifier "log")))
+        , MGroup (Just "(") (Just ")") [ Text "x" ]
+        ]
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.alignpoint(), 
+                        math.op(limits: false, 
+                                text: "sin"), 
+                        text(body: [x]), 
+                        text(body: [+]), 
+                        math.attach(b: text(body: [2]), 
+                                    base: math.op(limits: false, 
+                                                  text: "log"), 
+                                    t: none), 
+                        text(body: [x]), 
+                        linebreak(), 
+                        text(body: [=]), 
+                        math.alignpoint(), 
+                        math.op(limits: false, 
+                                text: "sin"), 
+                        text(body: [(]), 
+                        text(body: [x]), 
+                        text(body: [)]), 
+                        text(body: [+]), 
+                        math.attach(b: text(body: [2]), 
+                                    base: math.op(limits: false, 
+                                                  text: "log"), 
+                                    t: none), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         [)] })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/op-02.out b/test/out/math/op-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/op-02.out
@@ -0,0 +1,147 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/op-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/op-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/op-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/op-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "New Computer Modern"))
+       ])
+, SoftBreak
+, Text "Discuss"
+, Space
+, Equation
+    False
+    [ MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Text "n"
+              , Text "\8594"
+              , Code
+                  "test/typ/math/op-02.typ"
+                  ( line 4 , column 18 )
+                  (Ident (Identifier "oo"))
+              ]))
+        Nothing
+        (Code
+           "test/typ/math/op-02.typ"
+           ( line 4 , column 10 )
+           (Ident (Identifier "lim")))
+    , MFrac (Text "1") (Text "n")
+    ]
+, Space
+, Text "now"
+, Text "."
+, SoftBreak
+, Equation
+    True
+    [ MAttach
+        (Just
+           (MGroup
+              Nothing
+              Nothing
+              [ Text "n"
+              , Text "\8594"
+              , Code
+                  "test/typ/math/op-02.typ"
+                  ( line 5 , column 11 )
+                  (Ident (Identifier "infinity"))
+              ]))
+        Nothing
+        (Code
+           "test/typ/math/op-02.typ"
+           ( line 5 , column 3 )
+           (Ident (Identifier "lim")))
+    , MFrac (Text "1") (Text "n")
+    , Text "="
+    , Text "0"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Discuss ], 
+       font: "New Computer Modern"), 
+  math.equation(block: false, 
+                body: { math.attach(b: { text(body: [n], 
+                                              font: "New Computer Modern"), 
+                                         text(body: [→], 
+                                              font: "New Computer Modern"), 
+                                         text(body: [∞], 
+                                              font: "New Computer Modern") }, 
+                                    base: math.op(limits: true, 
+                                                  text: "lim"), 
+                                    t: none), 
+                        math.frac(denom: text(body: [n], 
+                                              font: "New Computer Modern"), 
+                                  num: text(body: [1], 
+                                            font: "New Computer Modern")) }, 
+                numbering: none), 
+  text(body: [ now.
+], 
+       font: "New Computer Modern"), 
+  math.equation(block: true, 
+                body: { math.attach(b: { text(body: [n], 
+                                              font: "New Computer Modern"), 
+                                         text(body: [→], 
+                                              font: "New Computer Modern"), 
+                                         text(body: [∞], 
+                                              font: "New Computer Modern") }, 
+                                    base: math.op(limits: true, 
+                                                  text: "lim"), 
+                                    t: none), 
+                        math.frac(denom: text(body: [n], 
+                                              font: "New Computer Modern"), 
+                                  num: text(body: [1], 
+                                            font: "New Computer Modern")), 
+                        text(body: [=], 
+                             font: "New Computer Modern"), 
+                        text(body: [0], 
+                             font: "New Computer Modern") }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/op-03.out b/test/out/math/op-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/op-03.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/op-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/op-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/op-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        (Just
+           (MGroup
+              Nothing Nothing [ Text "x" , Text ":" , Text "=" , Text "1" ]))
+        Nothing
+        (Code
+           "test/typ/math/op-03.typ"
+           ( line 3 , column 3 )
+           (FuncCall
+              (Ident (Identifier "op"))
+              [ BlockArg [ Text "myop" ]
+              , KeyValArg (Identifier "limits") (Literal (Boolean False))
+              ]))
+    , Text "x"
+    , HardBreak
+    , MAttach
+        (Just
+           (MGroup
+              Nothing Nothing [ Text "x" , Text ":" , Text "=" , Text "1" ]))
+        Nothing
+        (Code
+           "test/typ/math/op-03.typ"
+           ( line 4 , column 3 )
+           (FuncCall
+              (Ident (Identifier "op"))
+              [ BlockArg [ Text "myop" ]
+              , KeyValArg (Identifier "limits") (Literal (Boolean True))
+              ]))
+    , Text "x"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: { text(body: [x]), 
+                                         text(body: [:]), 
+                                         text(body: [=]), 
+                                         text(body: [1]) }, 
+                                    base: math.op(limits: false, 
+                                                  text: text(body: [myop])), 
+                                    t: none), 
+                        text(body: [x]), 
+                        linebreak(), 
+                        math.attach(b: { text(body: [x]), 
+                                         text(body: [:]), 
+                                         text(body: [=]), 
+                                         text(body: [1]) }, 
+                                    base: math.op(limits: true, 
+                                                  text: text(body: [myop])), 
+                                    t: none), 
+                        text(body: [x]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/op-04.out b/test/out/math/op-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/op-04.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/op-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/op-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/op-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        (Just (Text "x"))
+        Nothing
+        (Code
+           "test/typ/math/op-04.typ"
+           ( line 3 , column 3 )
+           (FuncCall
+              (Ident (Identifier "bold"))
+              [ BlockArg
+                  [ Code
+                      "test/typ/math/op-04.typ"
+                      ( line 3 , column 8 )
+                      (FuncCall
+                         (Ident (Identifier "op"))
+                         [ BlockArg [ Text "bold" ]
+                         , KeyValArg (Identifier "limits") (Literal (Boolean True))
+                         ])
+                  ]
+              ]))
+    , Text "y"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: text(body: [x]), 
+                                    base: math.bold(body: math.op(limits: true, 
+                                                                  text: text(body: [bold]))), 
+                                    t: none), 
+                        text(body: [y]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/root-00.out b/test/out/math/root-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/root-00.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/root-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/root-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/root-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "A"
+    , Text "="
+    , Code
+        "test/typ/math/root-00.typ"
+        ( line 3 , column 6 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg [ Text "x" , Text "+" , Text "y" ] ])
+    , Text "="
+    , Text "c"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [A]), 
+                        text(body: [=]), 
+                        math.sqrt(radicand: { text(body: [x]), 
+                                              text(body: [+]), 
+                                              text(body: [y]) }), 
+                        text(body: [=]), 
+                        text(body: [c]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/root-01.out b/test/out/math/root-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/root-01.out
@@ -0,0 +1,149 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/root-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/root-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/root-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/root-01.typ"
+        ( line 3 , column 3 )
+        (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "a" ] ])
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 3 , column 11 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 4 , column 3 )
+        (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "f" ] ])
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 4 , column 11 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 5 , column 3 )
+        (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "q" ] ])
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 5 , column 11 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 6 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg [ MAttach Nothing (Just (Text "2")) (Text "a") ] ])
+    , HardBreak
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 7 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg [ MAttach (Just (Text "0")) Nothing (Text "n") ] ])
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 7 , column 13 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 8 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ MAttach Nothing (Just (MGroup Nothing Nothing [])) (Text "b") ]
+           ])
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 8 , column 14 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 9 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg [ MAttach Nothing (Just (Text "2")) (Text "b") ] ])
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 9 , column 13 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-01.typ"
+        ( line 10 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ MAttach (Just (Text "1")) (Just (Text "2")) (Text "q") ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.sqrt(radicand: text(body: [a])), 
+                        text(body: [ ]), 
+                        math.sqrt(radicand: text(body: [f])), 
+                        text(body: [ ]), 
+                        math.sqrt(radicand: text(body: [q])), 
+                        text(body: [ ]), 
+                        math.sqrt(radicand: math.attach(b: none, 
+                                                        base: text(body: [a]), 
+                                                        t: text(body: [2]))), 
+                        linebreak(), 
+                        math.sqrt(radicand: math.attach(b: text(body: [0]), 
+                                                        base: text(body: [n]), 
+                                                        t: none)), 
+                        text(body: [ ]), 
+                        math.sqrt(radicand: math.attach(b: none, 
+                                                        base: text(body: [b]), 
+                                                        t: {  })), 
+                        text(body: [ ]), 
+                        math.sqrt(radicand: math.attach(b: none, 
+                                                        base: text(body: [b]), 
+                                                        t: text(body: [2]))), 
+                        text(body: [ ]), 
+                        math.sqrt(radicand: math.attach(b: text(body: [1]), 
+                                                        base: text(body: [q]), 
+                                                        t: text(body: [2]))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/root-02.out b/test/out/math/root-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/root-02.out
@@ -0,0 +1,123 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/root-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/root-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/root-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Equation
+    False
+    [ Code
+        "test/typ/math/root-02.typ"
+        ( line 4 , column 2 )
+        (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "x" ] ])
+    ]
+, SoftBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/root-02.typ"
+        ( line 5 , column 2 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ Text "2" ] , BlockArg [ Text "x" ] ])
+    ]
+, SoftBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/root-02.typ"
+        ( line 6 , column 2 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ Text "3" ] , BlockArg [ Text "x" ] ])
+    ]
+, SoftBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/root-02.typ"
+        ( line 7 , column 2 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ Text "4" ] , BlockArg [ Text "x" ] ])
+    ]
+, SoftBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/root-02.typ"
+        ( line 8 , column 2 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ Text "5" ] , BlockArg [ Text "x" ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: math.sqrt(radicand: text(body: [x])), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: math.root(index: text(body: [2]), 
+                                radicand: text(body: [x])), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: math.root(index: text(body: [3]), 
+                                radicand: text(body: [x])), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: math.root(index: text(body: [4]), 
+                                radicand: text(body: [x])), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: math.root(index: text(body: [5]), 
+                                radicand: text(body: [x])), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/root-03.out b/test/out/math/root-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/root-03.out
@@ -0,0 +1,187 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/root-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/root-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/root-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/root-03.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ MAttach
+                   Nothing
+                   (Just (Text "2"))
+                   (MGroup
+                      (Just "[")
+                      (Just "]")
+                      [ MGroup (Just "|") (Just "|") [ Text "x" ] ])
+               , Text "+"
+               , MAttach
+                   Nothing
+                   (Just (Text "2"))
+                   (MGroup
+                      (Just "[")
+                      (Just "]")
+                      [ MGroup (Just "|") (Just "|") [ Text "y" ] ])
+               ]
+           ])
+    , Text "<"
+    , MGroup
+        (Just "[") (Just "]") [ MGroup (Just "|") (Just "|") [ Text "z" ] ]
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Text "v"
+    , Text "="
+    , Code
+        "test/typ/math/root-03.typ"
+        ( line 4 , column 7 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg
+               [ MFrac
+                   (MGroup (Just "(") (Just ")") [ MFrac (Text "1") (Text "2") ])
+                   (MGroup Nothing Nothing [ MFrac (Text "4") (Text "5") ])
+               ]
+           ])
+    , Text "="
+    , Code
+        "test/typ/math/root-03.typ"
+        ( line 5 , column 6 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ Text "3" ]
+           , BlockArg
+               [ MFrac
+                   (MGroup
+                      (Just "(")
+                      (Just ")")
+                      [ MFrac (MFrac (Text "1") (Text "2")) (Text "3") ])
+                   (MGroup
+                      Nothing Nothing [ MFrac (MFrac (Text "4") (Text "5")) (Text "6") ])
+               ]
+           ])
+    , Text "="
+    , Code
+        "test/typ/math/root-03.typ"
+        ( line 6 , column 6 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ Text "4" ]
+           , BlockArg
+               [ MFrac
+                   (MGroup
+                      (Just "(")
+                      (Just ")")
+                      [ MFrac
+                          (MGroup (Just "(") (Just ")") [ MFrac (Text "1") (Text "2") ])
+                          (MGroup Nothing Nothing [ MFrac (Text "3") (Text "4") ])
+                      ])
+                   (MGroup
+                      Nothing
+                      Nothing
+                      [ MFrac
+                          (MGroup (Just "(") (Just ")") [ MFrac (Text "1") (Text "2") ])
+                          (MGroup Nothing Nothing [ MFrac (Text "3") (Text "4") ])
+                      ])
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.sqrt(radicand: { math.attach(b: none, 
+                                                          base: math.lr(body: ({ [[], 
+                                                                                 math.lr(body: ({ [|], 
+                                                                                                  text(body: [x]), 
+                                                                                                  [|] })), 
+                                                                                 []] })), 
+                                                          t: text(body: [2])), 
+                                              text(body: [+]), 
+                                              math.attach(b: none, 
+                                                          base: math.lr(body: ({ [[], 
+                                                                                 math.lr(body: ({ [|], 
+                                                                                                  text(body: [y]), 
+                                                                                                  [|] })), 
+                                                                                 []] })), 
+                                                          t: text(body: [2])) }), 
+                        text(body: [<]), 
+                        math.lr(body: ({ [[], 
+                                         math.lr(body: ({ [|], 
+                                                          text(body: [z]), 
+                                                          [|] })), 
+                                         []] })) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [v]), 
+                        text(body: [=]), 
+                        math.sqrt(radicand: math.frac(denom: math.frac(denom: text(body: [5]), 
+                                                                       num: text(body: [4])), 
+                                                      num: math.frac(denom: text(body: [2]), 
+                                                                     num: text(body: [1])))), 
+                        text(body: [=]), 
+                        math.root(index: text(body: [3]), 
+                                  radicand: math.frac(denom: math.frac(denom: text(body: [6]), 
+                                                                       num: math.frac(denom: text(body: [5]), 
+                                                                                      num: text(body: [4]))), 
+                                                      num: math.frac(denom: text(body: [3]), 
+                                                                     num: math.frac(denom: text(body: [2]), 
+                                                                                    num: text(body: [1]))))), 
+                        text(body: [=]), 
+                        math.root(index: text(body: [4]), 
+                                  radicand: math.frac(denom: math.frac(denom: math.frac(denom: text(body: [4]), 
+                                                                                        num: text(body: [3])), 
+                                                                       num: math.frac(denom: text(body: [2]), 
+                                                                                      num: text(body: [1]))), 
+                                                      num: math.frac(denom: math.frac(denom: text(body: [4]), 
+                                                                                      num: text(body: [3])), 
+                                                                     num: math.frac(denom: text(body: [2]), 
+                                                                                    num: text(body: [1]))))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/root-04.out b/test/out/math/root-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/root-04.out
@@ -0,0 +1,114 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/root-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/root-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/root-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/root-04.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ Text "2" ] , BlockArg [ Text "x" ] ])
+    , Code
+        "test/typ/math/root-04.typ"
+        ( line 3 , column 14 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-04.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg
+               [ MFrac
+                   (Text "3") (MGroup Nothing Nothing [ MFrac (Text "2") (Text "1") ])
+               ]
+           , BlockArg [ Text "x" ]
+           ])
+    , Code
+        "test/typ/math/root-04.typ"
+        ( line 4 , column 20 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-04.typ"
+        ( line 5 , column 3 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ MFrac (Text "1") (Text "11") ]
+           , BlockArg [ Text "x" ]
+           ])
+    , Code
+        "test/typ/math/root-04.typ"
+        ( line 5 , column 17 )
+        (Ident (Identifier "quad"))
+    , Code
+        "test/typ/math/root-04.typ"
+        ( line 6 , column 3 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ BlockArg [ MFrac (MFrac (Text "1") (Text "2")) (Text "3") ]
+           , BlockArg [ Text "1" ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.root(index: text(body: [2]), 
+                                  radicand: text(body: [x])), 
+                        text(body: [ ]), 
+                        math.root(index: math.frac(denom: math.frac(denom: text(body: [1]), 
+                                                                    num: text(body: [2])), 
+                                                   num: text(body: [3])), 
+                                  radicand: text(body: [x])), 
+                        text(body: [ ]), 
+                        math.root(index: math.frac(denom: text(body: [11]), 
+                                                   num: text(body: [1])), 
+                                  radicand: text(body: [x])), 
+                        text(body: [ ]), 
+                        math.root(index: math.frac(denom: text(body: [3]), 
+                                                   num: math.frac(denom: text(body: [2]), 
+                                                                  num: text(body: [1]))), 
+                                  radicand: text(body: [1])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/root-05.out b/test/out/math/root-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/root-05.out
@@ -0,0 +1,153 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/root-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/root-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/root-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/root-05.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "root"))
+           [ NormalArg
+               (Block (Content [ MAttach Nothing (Just (Text "3")) (Text "2") ]))
+           ])
+    , Text "="
+    , Code
+        "test/typ/math/root-05.typ"
+        ( line 3 , column 10 )
+        (FuncCall
+           (Ident (Identifier "sqrt"))
+           [ BlockArg [ MAttach Nothing (Just (Text "3")) (Text "2") ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/root-05.typ"
+        ( line 4 , column 3 )
+        (Ident (Identifier "root"))
+    , MGroup (Just "(") (Just ")") [ Text "x" , Text "+" , Text "y" ]
+    , Code
+        "test/typ/math/root-05.typ"
+        ( line 4 , column 10 )
+        (Ident (Identifier "quad"))
+    , Text "\8731"
+    , Text "x"
+    , Code
+        "test/typ/math/root-05.typ"
+        ( line 4 , column 18 )
+        (Ident (Identifier "quad"))
+    , Text "\8732"
+    , Text "x"
+    ]
+, SoftBreak
+, Equation
+    True
+    [ MGroup
+        (Just "(")
+        (Just ")")
+        [ Code
+            "test/typ/math/root-05.typ"
+            ( line 5 , column 4 )
+            (FuncCall
+               (Ident (Identifier "root"))
+               [ NormalArg (Block (Content [ Text "2" ])) ])
+        , Text "+"
+        , Text "3"
+        ]
+    , Text "="
+    , MGroup
+        (Just "(")
+        (Just ")")
+        [ Code
+            "test/typ/math/root-05.typ"
+            ( line 5 , column 13 )
+            (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "2" ] ])
+        , Text "+"
+        , Text "3"
+        ]
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.root(index: math.attach(b: none, 
+                                                     base: text(body: [2]), 
+                                                     t: text(body: [3]))), 
+                        text(body: [=]), 
+                        math.sqrt(radicand: math.attach(b: none, 
+                                                        base: text(body: [2]), 
+                                                        t: text(body: [3]))) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         text(body: [+]), 
+                                         text(body: [y]), 
+                                         [)] })), 
+                        text(body: [ ]), 
+                        text(body: [∛]), 
+                        text(body: [x]), 
+                        text(body: [ ]), 
+                        text(body: [∜]), 
+                        text(body: [x]) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.lr(body: ({ [(], 
+                                         math.root(index: text(body: [2])), 
+                                         text(body: [+]), 
+                                         text(body: [3]), 
+                                         [)] })), 
+                        text(body: [=]), 
+                        math.lr(body: ({ [(], 
+                                         math.sqrt(radicand: text(body: [2])), 
+                                         text(body: [+]), 
+                                         text(body: [3]), 
+                                         [)] })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/spacing-00.out b/test/out/math/spacing-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/spacing-00.out
@@ -0,0 +1,289 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/spacing-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/spacing-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/spacing-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "\228"
+    , Text ","
+    , Text "+"
+    , Text ","
+    , Text "c"
+    , Text ","
+    , MGroup (Just "(") (Just ")") [ Text "," ]
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "="
+    , Text ")"
+    , Text ","
+    , MGroup (Just "(") (Just ")") [ Text "+" ]
+    , Text ","
+    , MGroup
+        (Just "{")
+        (Just "}")
+        [ Code
+            "test/typ/math/spacing-00.typ"
+            ( line 4 , column 12 )
+            (Ident (Identifier "times"))
+        ]
+    ]
+, SoftBreak
+, Equation
+    False
+    [ Text "\10215"
+    , Text "<"
+    , Text "\10214"
+    , Text ","
+    , MGroup (Just "|") (Just "|") [ Text "-" ]
+    , Text ","
+    , MGroup (Just "[") Nothing [ Text "=" ]
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Text "="
+    , Text "b"
+    , Text ","
+    , Text "a"
+    , Text "="
+    , Text "="
+    , Text "b"
+    ]
+, Space
+, HardBreak
+, Equation
+    False [ Text "-" , Text "a" , Text "," , Text "+" , Text "a" ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Code
+        "test/typ/math/spacing-00.typ"
+        ( line 8 , column 4 )
+        (Ident (Identifier "not"))
+    , Text "b"
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Text "+"
+    , Text "b"
+    , Text ","
+    , Text "a"
+    , Text "*"
+    , Text "b"
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/spacing-00.typ"
+        ( line 10 , column 2 )
+        (Ident (Identifier "sum"))
+    , Text "x"
+    , Text ","
+    , Code
+        "test/typ/math/spacing-00.typ"
+        ( line 10 , column 9 )
+        (FuncCall (Ident (Identifier "sum")) [ BlockArg [ Text "x" ] ])
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Code
+        "test/typ/math/spacing-00.typ"
+        ( line 11 , column 2 )
+        (Ident (Identifier "sum"))
+    , Code
+        "test/typ/math/spacing-00.typ"
+        ( line 11 , column 6 )
+        (Ident (Identifier "product"))
+    , Text "x"
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ MGroup
+        Nothing
+        Nothing
+        [ Text "f" , MGroup (Just "(") (Just ")") [ Text "x" ] ]
+    , Text ","
+    , Code
+        "test/typ/math/spacing-00.typ"
+        ( line 12 , column 8 )
+        (FuncCall (Ident (Identifier "zeta")) [ BlockArg [ Text "x" ] ])
+    , Text ","
+    , MGroup
+        Nothing
+        Nothing
+        [ Text " frac" , MGroup (Just "(") (Just ")") [ Text "x" ] ]
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [ä]), 
+                        text(body: [,]), 
+                        text(body: [+]), 
+                        text(body: [,]), 
+                        text(body: [c]), 
+                        text(body: [,]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [,]), 
+                                         [)] })) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [=]), 
+                        text(body: [)]), 
+                        text(body: [,]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [+]), 
+                                         [)] })), 
+                        text(body: [,]), 
+                        math.lr(body: ({ [{], 
+                                         text(body: [×]), 
+                                         [}] })) }, 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [⟧]), 
+                        text(body: [<]), 
+                        text(body: [⟦]), 
+                        text(body: [,]), 
+                        math.lr(body: ({ [|], 
+                                         text(body: [-]), 
+                                         [|] })), 
+                        text(body: [,]), 
+                        text(body: [[]), 
+                        text(body: [=]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [=]), 
+                        text(body: [b]), 
+                        text(body: [,]), 
+                        text(body: [a]), 
+                        text(body: [=]), 
+                        text(body: [=]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [-]), 
+                        text(body: [a]), 
+                        text(body: [,]), 
+                        text(body: [+]), 
+                        text(body: [a]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [¬]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [+]), 
+                        text(body: [b]), 
+                        text(body: [,]), 
+                        text(body: [a]), 
+                        text(body: [*]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [∑]), 
+                        text(body: [x]), 
+                        text(body: [,]), 
+                        text(body: [∑]), 
+                        text(body: [(]), 
+                        text(body: [x]), 
+                        text(body: [)]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [∑]), 
+                        text(body: [∏]), 
+                        text(body: [x]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [f]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         [)] })), 
+                        text(body: [,]), 
+                        text(body: [ζ]), 
+                        text(body: [(]), 
+                        text(body: [x]), 
+                        text(body: [)]), 
+                        text(body: [,]), 
+                        text(body: [ frac]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         [)] })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/spacing-01.out b/test/out/math/spacing-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/spacing-01.out
@@ -0,0 +1,123 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/spacing-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/spacing-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/spacing-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "f"
+    , MGroup (Just "(") (Just ")") [ Text "x" ]
+    , Text ","
+    , MGroup
+        Nothing
+        Nothing
+        [ Text "f" , MGroup (Just "(") (Just ")") [ Text "x" ] ]
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ MGroup (Just "[") (Just "]") [ Text "a" , Text "|" , Text "b" ]
+    , Text ","
+    , MGroup
+        (Just "[")
+        (Just "]")
+        [ Text "a"
+        , MGroup Nothing Nothing [ Nbsp , Text "|" , Nbsp ]
+        , Text "b"
+        ]
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Text "is"
+    , Text "b"
+    , Text ","
+    , Text "a"
+    , Text " is "
+    , Text "b"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [f]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         [)] })), 
+                        text(body: [,]), 
+                        text(body: [f]), 
+                        math.lr(body: ({ [(], 
+                                         text(body: [x]), 
+                                         [)] })) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { math.lr(body: ({ [[], 
+                                         text(body: [a]), 
+                                         text(body: [|]), 
+                                         text(body: [b]), 
+                                         []] })), 
+                        text(body: [,]), 
+                        math.lr(body: ({ [[], 
+                                         text(body: [a]), 
+                                         text(body: [ ]), 
+                                         text(body: [|]), 
+                                         text(body: [ ]), 
+                                         text(body: [b]), 
+                                         []] })) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [is]), 
+                        text(body: [b]), 
+                        text(body: [,]), 
+                        text(body: [a]), 
+                        text(body: [ is ]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/spacing-02.out b/test/out/math/spacing-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/spacing-02.out
@@ -0,0 +1,156 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/spacing-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/spacing-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/spacing-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "a"
+    , Code
+        "test/typ/math/spacing-02.typ"
+        ( line 3 , column 4 )
+        (Ident (Identifier "thin"))
+    , Text "b"
+    , Text ","
+    , Text "a"
+    , Code
+        "test/typ/math/spacing-02.typ"
+        ( line 3 , column 14 )
+        (Ident (Identifier "med"))
+    , Text "b"
+    , Text ","
+    , Text "a"
+    , Code
+        "test/typ/math/spacing-02.typ"
+        ( line 3 , column 23 )
+        (Ident (Identifier "thick"))
+    , Text "b"
+    , Text ","
+    , Text "a"
+    , Code
+        "test/typ/math/spacing-02.typ"
+        ( line 3 , column 34 )
+        (Ident (Identifier "quad"))
+    , Text "b"
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Text "="
+    , Code
+        "test/typ/math/spacing-02.typ"
+        ( line 4 , column 6 )
+        (Ident (Identifier "thin"))
+    , Text "b"
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Text "-"
+    , Text "b"
+    , Code
+        "test/typ/math/spacing-02.typ"
+        ( line 5 , column 8 )
+        (Ident (Identifier "ident"))
+    , Text "c"
+    , Code
+        "test/typ/math/spacing-02.typ"
+        ( line 5 , column 16 )
+        (Ident (Identifier "quad"))
+    , MGroup
+        (Just "(")
+        (Just ")")
+        [ Code
+            "test/typ/math/spacing-02.typ"
+            ( line 5 , column 22 )
+            (Ident (Identifier "mod"))
+        , Text "2"
+        ]
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [ ]), 
+                        text(body: [b]), 
+                        text(body: [,]), 
+                        text(body: [a]), 
+                        text(body: [ ]), 
+                        text(body: [b]), 
+                        text(body: [,]), 
+                        text(body: [a]), 
+                        text(body: [ ]), 
+                        text(body: [b]), 
+                        text(body: [,]), 
+                        text(body: [a]), 
+                        text(body: [ ]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [=]), 
+                        text(body: [ ]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [-]), 
+                        text(body: [b]), 
+                        text(body: [≡]), 
+                        text(body: [c]), 
+                        text(body: [ ]), 
+                        math.lr(body: ({ [(], 
+                                         math.op(limits: false, 
+                                                 text: "mod"), 
+                                         text(body: [2]), 
+                                         [)] })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/spacing-03.out b/test/out/math/spacing-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/spacing-03.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/spacing-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/spacing-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/spacing-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/spacing-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Equation
+    True
+    [ MGroup
+        (Just "{")
+        (Just "}")
+        [ Text "x"
+        , Code
+            "test/typ/math/spacing-03.typ"
+            ( line 4 , column 7 )
+            (Ident (Identifier "in"))
+        , Code
+            "test/typ/math/spacing-03.typ"
+            ( line 4 , column 10 )
+            (Ident (Identifier "RR"))
+        , MGroup Nothing Nothing [ Nbsp , Text "|" , Nbsp ]
+        , Text "x"
+        , Text " is natural "
+        , Code
+            "test/typ/math/spacing-03.typ"
+            ( line 4 , column 30 )
+            (Ident (Identifier "and"))
+        , Text "x"
+        , Text "<"
+        , Text "10"
+        ]
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.lr(body: ({ [{], 
+                                       text(body: [x]), 
+                                       text(body: [∈]), 
+                                       text(body: [ℝ]), 
+                                       text(body: [ ]), 
+                                       text(body: [|]), 
+                                       text(body: [ ]), 
+                                       text(body: [x]), 
+                                       text(body: [ is natural ]), 
+                                       text(body: [∧]), 
+                                       text(body: [x]), 
+                                       text(body: [<]), 
+                                       text(body: [10]), 
+                                       [}] })), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/spacing-04.out b/test/out/math/spacing-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/spacing-04.out
@@ -0,0 +1,378 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/spacing-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/spacing-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/spacing-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/spacing-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Equation
+    False
+    [ Text "a"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 4 , column 4 )
+        (Ident (Identifier "ident"))
+    , Text "b"
+    , Text "+"
+    , Text "c"
+    , Text "-"
+    , Text "d"
+    , Text "\8658"
+    , Text "e"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 4 , column 25 )
+        (Ident (Identifier "log"))
+    , Text "5"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 4 , column 31 )
+        (FuncCall (Ident (Identifier "op")) [ BlockArg [ Text "ln" ] ])
+    , Text "6"
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 5 , column 4 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 5 , column 11 )
+                   (Ident (Identifier "ident"))
+               ]
+           ])
+    , Text "b"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 5 , column 20 )
+        (FuncCall
+           (Ident (Identifier "overline")) [ BlockArg [ Text "+" ] ])
+    , Text "c"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 5 , column 34 )
+        (FuncCall (Ident (Identifier "arrow")) [ BlockArg [ Text "-" ] ])
+    , Text "d"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 5 , column 45 )
+        (FuncCall (Ident (Identifier "hat")) [ BlockArg [ Text "\8658" ] ])
+    , Text "e"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 5 , column 55 )
+        (FuncCall
+           (Ident (Identifier "cancel"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 5 , column 62 )
+                   (Ident (Identifier "log"))
+               ]
+           ])
+    , Text "5"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 5 , column 69 )
+        (FuncCall
+           (Ident (Identifier "dot"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 5 , column 73 )
+                   (FuncCall (Ident (Identifier "op")) [ BlockArg [ Text "ln" ] ])
+               ]
+           ])
+    , Text "6"
+    ]
+, Space
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 6 , column 4 )
+        (FuncCall
+           (Ident (Identifier "overbrace"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 6 , column 14 )
+                   (Ident (Identifier "ident"))
+               ]
+           ])
+    , Text "b"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 6 , column 23 )
+        (FuncCall
+           (Ident (Identifier "underline")) [ BlockArg [ Text "+" ] ])
+    , Text "c"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 6 , column 38 )
+        (FuncCall (Ident (Identifier "grave")) [ BlockArg [ Text "-" ] ])
+    , Text "d"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 6 , column 49 )
+        (FuncCall
+           (Ident (Identifier "underbracket")) [ BlockArg [ Text "\8658" ] ])
+    , Text "e"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 6 , column 68 )
+        (FuncCall
+           (Ident (Identifier "circle"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 6 , column 75 )
+                   (Ident (Identifier "log"))
+               ]
+           ])
+    , Text "5"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 6 , column 82 )
+        (FuncCall
+           (Ident (Identifier "caron"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 6 , column 88 )
+                   (FuncCall (Ident (Identifier "op")) [ BlockArg [ Text "ln" ] ])
+               ]
+           ])
+    , Text "6"
+    ]
+, Space
+, HardBreak
+, HardBreak
+, Equation
+    False
+    [ Text "a"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 8 , column 4 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 8 , column 11 )
+                   (Ident (Identifier "ident"))
+               ]
+           , KeyValArg (Identifier "tl") (Block (Content [ Text "a" ]))
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "b" ]))
+           ])
+    , Text "b"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 8 , column 34 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 8 , column 41 )
+                   (FuncCall (Ident (Identifier "limits")) [ BlockArg [ Text "+" ] ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "a" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           ])
+    , Text "c"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 8 , column 66 )
+        (FuncCall (Ident (Identifier "tilde")) [ BlockArg [ Text "-" ] ])
+    , Text "d"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 8 , column 77 )
+        (FuncCall
+           (Ident (Identifier "breve")) [ BlockArg [ Text "\8658" ] ])
+    , Text "e"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 8 , column 89 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 8 , column 96 )
+                   (FuncCall
+                      (Ident (Identifier "limits"))
+                      [ BlockArg
+                          [ Code
+                              "test/typ/math/spacing-04.typ"
+                              ( line 8 , column 103 )
+                              (Ident (Identifier "log"))
+                          ]
+                      ])
+               ]
+           , KeyValArg (Identifier "t") (Block (Content [ Text "a" ]))
+           , KeyValArg (Identifier "b") (Block (Content [ Text "b" ]))
+           ])
+    , Text "5"
+    , Code
+        "test/typ/math/spacing-04.typ"
+        ( line 8 , column 123 )
+        (FuncCall
+           (Ident (Identifier "attach"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/spacing-04.typ"
+                   ( line 8 , column 130 )
+                   (FuncCall (Ident (Identifier "op")) [ BlockArg [ Text "ln" ] ])
+               ]
+           , KeyValArg (Identifier "tr") (Block (Content [ Text "a" ]))
+           , KeyValArg (Identifier "bl") (Block (Content [ Text "b" ]))
+           ])
+    , Text "6"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [≡]), 
+                        text(body: [b]), 
+                        text(body: [+]), 
+                        text(body: [c]), 
+                        text(body: [-]), 
+                        text(body: [d]), 
+                        text(body: [⇒]), 
+                        text(body: [e]), 
+                        math.op(limits: false, 
+                                text: "log"), 
+                        text(body: [5]), 
+                        math.op(text: text(body: [ln])), 
+                        text(body: [6]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        math.cancel(body: text(body: [≡])), 
+                        text(body: [b]), 
+                        math.overline(body: text(body: [+])), 
+                        text(body: [c]), 
+                        math.accent(accent: →, 
+                                    base: text(body: [-])), 
+                        text(body: [d]), 
+                        math.accent(accent: ^, 
+                                    base: text(body: [⇒])), 
+                        text(body: [e]), 
+                        math.cancel(body: math.op(limits: false, 
+                                                  text: "log")), 
+                        text(body: [5]), 
+                        math.accent(accent: ⋅, 
+                                    base: math.op(text: text(body: [ln]))), 
+                        text(body: [6]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        math.overbrace(body: text(body: [≡])), 
+                        text(body: [b]), 
+                        math.underline(body: text(body: [+])), 
+                        text(body: [c]), 
+                        math.accent(accent: `, 
+                                    base: text(body: [-])), 
+                        text(body: [d]), 
+                        math.underbracket(body: text(body: [⇒])), 
+                        text(body: [e]), 
+                        math.accent(accent: ○, 
+                                    base: math.op(limits: false, 
+                                                  text: "log")), 
+                        text(body: [5]), 
+                        math.accent(accent: ˇ, 
+                                    base: math.op(text: text(body: [ln]))), 
+                        text(body: [6]) }, 
+                numbering: none), 
+  text(body: [ ]), 
+  linebreak(), 
+  linebreak(), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        math.attach(base: text(body: [≡]), 
+                                    tl: text(body: [a]), 
+                                    tr: text(body: [b])), 
+                        text(body: [b]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: text(body: [+])), 
+                                    t: text(body: [a])), 
+                        text(body: [c]), 
+                        math.accent(accent: ∼, 
+                                    base: text(body: [-])), 
+                        text(body: [d]), 
+                        math.accent(accent: ˘, 
+                                    base: text(body: [⇒])), 
+                        text(body: [e]), 
+                        math.attach(b: text(body: [b]), 
+                                    base: math.limits(body: math.op(limits: false, 
+                                                                    text: "log")), 
+                                    t: text(body: [a])), 
+                        text(body: [5]), 
+                        math.attach(base: math.op(text: text(body: [ln])), 
+                                    bl: text(body: [b]), 
+                                    tr: text(body: [a])), 
+                        text(body: [6]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/style-00.out b/test/out/math/style-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/style-00.out
@@ -0,0 +1,88 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/style-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/style-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/style-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "a"
+    , Text ","
+    , Text "A"
+    , Text ","
+    , Code
+        "test/typ/math/style-00.typ"
+        ( line 3 , column 8 )
+        (Ident (Identifier "delta"))
+    , Text ","
+    , Text "\1013"
+    , Text ","
+    , Code
+        "test/typ/math/style-00.typ"
+        ( line 3 , column 18 )
+        (Ident (Identifier "diff"))
+    , Text ","
+    , Code
+        "test/typ/math/style-00.typ"
+        ( line 3 , column 24 )
+        (Ident (Identifier "Delta"))
+    , Text ","
+    , Text "\1012"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [a]), 
+                        text(body: [,]), 
+                        text(body: [A]), 
+                        text(body: [,]), 
+                        text(body: [δ]), 
+                        text(body: [,]), 
+                        text(body: [ϵ]), 
+                        text(body: [,]), 
+                        text(body: [∂]), 
+                        text(body: [,]), 
+                        text(body: [Δ]), 
+                        text(body: [,]), 
+                        text(body: [ϴ]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/style-01.out b/test/out/math/style-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/style-01.out
@@ -0,0 +1,219 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/style-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/style-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/style-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "A"
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 3 , column 5 )
+        (FuncCall (Ident (Identifier "italic")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 3 , column 16 )
+        (FuncCall (Ident (Identifier "upright")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 3 , column 28 )
+        (FuncCall (Ident (Identifier "bold")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 3 , column 37 )
+        (FuncCall
+           (Ident (Identifier "bold"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/style-01.typ"
+                   ( line 3 , column 42 )
+                   (FuncCall (Ident (Identifier "upright")) [ BlockArg [ Text "A" ] ])
+               ]
+           ])
+    , Text ","
+    , HardBreak
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 4 , column 2 )
+        (FuncCall (Ident (Identifier "serif")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 4 , column 12 )
+        (FuncCall (Ident (Identifier "sans")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 4 , column 21 )
+        (FuncCall (Ident (Identifier "cal")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 4 , column 29 )
+        (FuncCall (Ident (Identifier "frak")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 4 , column 38 )
+        (FuncCall (Ident (Identifier "mono")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 4 , column 47 )
+        (FuncCall (Ident (Identifier "bb")) [ BlockArg [ Text "A" ] ])
+    , Text ","
+    , HardBreak
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 5 , column 2 )
+        (FuncCall
+           (Ident (Identifier "italic"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/style-01.typ"
+                   ( line 5 , column 9 )
+                   (Ident (Identifier "diff"))
+               ]
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 5 , column 16 )
+        (FuncCall
+           (Ident (Identifier "upright"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/style-01.typ"
+                   ( line 5 , column 24 )
+                   (Ident (Identifier "diff"))
+               ]
+           ])
+    , Text ","
+    , HardBreak
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 6 , column 2 )
+        (FuncCall (Ident (Identifier "bb")) [ BlockArg [ Text "hello" ] ])
+    , Text "+"
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 6 , column 16 )
+        (FuncCall
+           (Ident (Identifier "bold"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/style-01.typ"
+                   ( line 6 , column 21 )
+                   (FuncCall (Ident (Identifier "cal")) [ BlockArg [ Text "world" ] ])
+               ]
+           ])
+    , Text ","
+    , HardBreak
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 7 , column 2 )
+        (FuncCall
+           (FuncCall (Ident (Identifier "mono")) [ BlockArg [ Text "SQRT" ] ])
+           [ BlockArg [ Text "x" ] ])
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 7 , column 18 )
+        (Ident (Identifier "wreath"))
+    , Code
+        "test/typ/math/style-01.typ"
+        ( line 7 , column 25 )
+        (FuncCall
+           (Ident (Identifier "mono"))
+           [ BlockArg [ Text "123" , Text "+" , Text "456" ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [A]), 
+                        text(body: [,]), 
+                        math.italic(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.upright(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.bold(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.bold(body: math.upright(body: text(body: [A]))), 
+                        text(body: [,]), 
+                        linebreak(), 
+                        math.serif(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.sans(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.cal(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.frak(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.mono(body: text(body: [A])), 
+                        text(body: [,]), 
+                        math.bb(body: text(body: [A])), 
+                        text(body: [,]), 
+                        linebreak(), 
+                        math.italic(body: text(body: [∂])), 
+                        text(body: [,]), 
+                        math.upright(body: text(body: [∂])), 
+                        text(body: [,]), 
+                        linebreak(), 
+                        math.bb(body: text(body: [hello])), 
+                        text(body: [+]), 
+                        math.bold(body: math.cal(body: text(body: [world]))), 
+                        text(body: [,]), 
+                        linebreak(), 
+                        math.mono(body: text(body: [SQRT])), 
+                        text(body: [(]), 
+                        text(body: [x]), 
+                        text(body: [)]), 
+                        text(body: [≀]), 
+                        math.mono(body: { text(body: [123]), 
+                                          text(body: [+]), 
+                                          text(body: [456]) }) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/style-02.out b/test/out/math/style-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/style-02.out
@@ -0,0 +1,129 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/style-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/style-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/style-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Text "h"
+    , Text ","
+    , Code
+        "test/typ/math/style-02.typ"
+        ( line 3 , column 5 )
+        (FuncCall (Ident (Identifier "bb")) [ BlockArg [ Text "N" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-02.typ"
+        ( line 3 , column 12 )
+        (FuncCall (Ident (Identifier "cal")) [ BlockArg [ Text "R" ] ])
+    , Text ","
+    , Code
+        "test/typ/math/style-02.typ"
+        ( line 3 , column 20 )
+        (Ident (Identifier "Theta"))
+    , Text ","
+    , Code
+        "test/typ/math/style-02.typ"
+        ( line 3 , column 27 )
+        (FuncCall
+           (Ident (Identifier "italic"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/style-02.typ"
+                   ( line 3 , column 34 )
+                   (Ident (Identifier "Theta"))
+               ]
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/style-02.typ"
+        ( line 3 , column 42 )
+        (FuncCall
+           (Ident (Identifier "sans"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/style-02.typ"
+                   ( line 3 , column 47 )
+                   (Ident (Identifier "Theta"))
+               ]
+           ])
+    , Text ","
+    , Code
+        "test/typ/math/style-02.typ"
+        ( line 3 , column 55 )
+        (FuncCall
+           (Ident (Identifier "sans"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/style-02.typ"
+                   ( line 3 , column 60 )
+                   (FuncCall
+                      (Ident (Identifier "italic"))
+                      [ BlockArg
+                          [ Code
+                              "test/typ/math/style-02.typ"
+                              ( line 3 , column 67 )
+                              (Ident (Identifier "Theta"))
+                          ]
+                      ])
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: [h]), 
+                        text(body: [,]), 
+                        math.bb(body: text(body: [N])), 
+                        text(body: [,]), 
+                        math.cal(body: text(body: [R])), 
+                        text(body: [,]), 
+                        text(body: [Θ]), 
+                        text(body: [,]), 
+                        math.italic(body: text(body: [Θ])), 
+                        text(body: [,]), 
+                        math.sans(body: text(body: [Θ])), 
+                        text(body: [,]), 
+                        math.sans(body: math.italic(body: text(body: [Θ]))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/style-03.out b/test/out/math/style-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/style-03.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/style-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/style-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/style-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "\12424"
+    , Code
+        "test/typ/math/style-03.typ"
+        ( line 3 , column 5 )
+        (Ident (Identifier "and"))
+    , Text "\127987"
+    , Text "\65039"
+    , Text "\8205"
+    , Text "\127752"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [よ]), 
+                        text(body: [∧]), 
+                        text(body: [🏳]), 
+                        text(body: [️]), 
+                        text(body: [‍]), 
+                        text(body: [🌈]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/style-04.out b/test/out/math/style-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/style-04.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/style-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/style-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/style-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    False
+    [ Code
+        "test/typ/math/style-04.typ"
+        ( line 3 , column 2 )
+        (FuncCall
+           (Ident (Identifier "text"))
+           [ NormalArg (Ident (Identifier "red"))
+           , BlockArg [ MAttach Nothing (Just (Text "2")) (Text " time") ]
+           ])
+    , Text "+"
+    , Code
+        "test/typ/math/style-04.typ"
+        ( line 3 , column 25 )
+        (FuncCall
+           (Ident (Identifier "sqrt")) [ BlockArg [ Text "place" ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: false, 
+                body: { text(body: math.attach(b: none, 
+                                               base: text(body: [ time]), 
+                                               t: text(body: [2])), 
+                             color: rgb(100%,25%,21%,100%)), 
+                        text(body: [+]), 
+                        math.sqrt(radicand: text(body: [place])) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/style-05.out b/test/out/math/style-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/style-05.out
@@ -0,0 +1,105 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/style-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/style-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/style-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/style-05.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FieldAccess
+             (Ident (Identifier "equation")) (Ident (Identifier "math"))))
+       (Set
+          (Ident (Identifier "text"))
+          [ KeyValArg (Identifier "font") (Literal (String "Fira Math")) ]))
+, SoftBreak
+, Equation
+    True
+    [ Text "v"
+    , Text ":"
+    , Text "="
+    , Code
+        "test/typ/math/style-05.typ"
+        ( line 4 , column 8 )
+        (FuncCall
+           (Ident (Identifier "vec"))
+           [ BlockArg [ Text "1" , Text "+" , Text "2" ]
+           , BlockArg [ Text "2" , Text "-" , Text "4" ]
+           , BlockArg
+               [ Code
+                   "test/typ/math/style-05.typ"
+                   ( line 4 , column 26 )
+                   (FuncCall (Ident (Identifier "sqrt")) [ BlockArg [ Text "3" ] ])
+               ]
+           , BlockArg
+               [ Code
+                   "test/typ/math/style-05.typ"
+                   ( line 4 , column 35 )
+                   (FuncCall (Ident (Identifier "arrow")) [ BlockArg [ Text "x" ] ])
+               ]
+           ])
+    , Text "+"
+    , Text "1"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [v]), 
+                        text(body: [:]), 
+                        text(body: [=]), 
+                        math.vec(children: ({ text(body: [1]), 
+                                              text(body: [+]), 
+                                              text(body: [2]) }, 
+                                            { text(body: [2]), 
+                                              text(body: [-]), 
+                                              text(body: [4]) }, 
+                                            math.sqrt(radicand: text(body: [3])), 
+                                            math.accent(accent: →, 
+                                                        base: text(body: [x])))), 
+                        text(body: [+]), 
+                        text(body: [1]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/style-06.out b/test/out/math/style-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/style-06.out
@@ -0,0 +1,104 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/style-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/style-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/style-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/style-06.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FieldAccess
+             (Ident (Identifier "tack")) (Ident (Identifier "sym"))))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (Content
+                [ Equation
+                    False
+                    [ Code
+                        "test/typ/math/style-06.typ"
+                        ( line 3 , column 25 )
+                        (FuncCall
+                           (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Em)) ])
+                    , Code
+                        "test/typ/math/style-06.typ"
+                        ( line 3 , column 32 )
+                        (Ident (Identifier "it"))
+                    , Code
+                        "test/typ/math/style-06.typ"
+                        ( line 3 , column 36 )
+                        (FuncCall
+                           (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Em)) ])
+                    ]
+                ]))))
+, SoftBreak
+, Equation
+    True
+    [ Text "a"
+    , Code
+        "test/typ/math/style-06.typ"
+        ( line 4 , column 5 )
+        (Ident (Identifier "tack"))
+    , Text "b"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [a]), 
+                        math.equation(block: false, 
+                                      body: { h(amount: 1.0em), 
+                                              text(body: { [], 
+                                                           math.equation(block: false, 
+                                                                         body: { h(amount: 1.0em), 
+                                                                                 text(body: [⊢]), 
+                                                                                 h(amount: 1.0em) }, 
+                                                                         numbering: none), 
+                                                           [] }), 
+                                              h(amount: 1.0em) }, 
+                                      numbering: none), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/syntax-00.out b/test/out/math/syntax-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/syntax-00.out
@@ -0,0 +1,92 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/syntax-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/syntax-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/syntax-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ MAttach
+        (Just (MGroup Nothing Nothing [ Text "i" , Text "=" , Text "0" ]))
+        (Just (Text "\8469"))
+        (Text "\8721")
+    , Text "a"
+    , Text "\8728"
+    , Text "b"
+    , Text "="
+    , MAttach
+        (Just (MGroup Nothing Nothing [ Text "i" , Text "=" , Text "0" ]))
+        (Just
+           (Code
+              "test/typ/math/syntax-00.typ"
+              ( line 3 , column 36 )
+              (Ident (Identifier "NN"))))
+        (Text "\8721")
+    , Text "a"
+    , Code
+        "test/typ/math/syntax-00.typ"
+        ( line 3 , column 41 )
+        (Ident (Identifier "compose"))
+    , Text "b"
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.attach(b: { text(body: [i]), 
+                                         text(body: [=]), 
+                                         text(body: [0]) }, 
+                                    base: text(body: [∑]), 
+                                    t: text(body: [ℕ])), 
+                        text(body: [a]), 
+                        text(body: [∘]), 
+                        text(body: [b]), 
+                        text(body: [=]), 
+                        math.attach(b: { text(body: [i]), 
+                                         text(body: [=]), 
+                                         text(body: [0]) }, 
+                                    base: text(body: [∑]), 
+                                    t: text(body: [ℕ])), 
+                        text(body: [a]), 
+                        text(body: [∘]), 
+                        text(body: [b]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/syntax-01.out b/test/out/math/syntax-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/syntax-01.out
@@ -0,0 +1,151 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/syntax-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/syntax-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/syntax-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/syntax-01.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "underline"))
+           [ BlockArg
+               [ Text "f"
+               , Text "\8242"
+               , Text ":"
+               , Code
+                   "test/typ/math/syntax-01.typ"
+                   ( line 3 , column 18 )
+                   (Ident (Identifier "NN"))
+               , Text "\8594"
+               , Code
+                   "test/typ/math/syntax-01.typ"
+                   ( line 3 , column 24 )
+                   (Ident (Identifier "RR"))
+               ]
+           ])
+    , HardBreak
+    , Text "n"
+    , Text "|"
+    , Text "\8594"
+    , Code
+        "test/typ/math/syntax-01.typ"
+        ( line 4 , column 9 )
+        (FuncCall
+           (Ident (Identifier "cases"))
+           [ BlockArg
+               [ MGroup
+                   (Just "[") (Just "]") [ MGroup (Just "|") (Just "|") [ Text "1" ] ]
+               , MAlignPoint
+               , Text "if "
+               , Text "n"
+               , Text ">"
+               , Text ">"
+               , Text ">"
+               , Text "10"
+               ]
+           , BlockArg
+               [ Text "2"
+               , Text "*"
+               , Text "3"
+               , MAlignPoint
+               , Text "if "
+               , Text "n"
+               , Text "\8800"
+               , Text "5"
+               ]
+           , BlockArg
+               [ Text "1"
+               , Text "-"
+               , Text "0"
+               , Code
+                   "test/typ/math/syntax-01.typ"
+                   ( line 7 , column 11 )
+                   (Ident (Identifier "thick"))
+               , MAlignPoint
+               , Text "\8230"
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.underline(body: { text(body: [f]), 
+                                               text(body: [′]), 
+                                               text(body: [:]), 
+                                               text(body: [ℕ]), 
+                                               text(body: [→]), 
+                                               text(body: [ℝ]) }), 
+                        linebreak(), 
+                        text(body: [n]), 
+                        text(body: [|]), 
+                        text(body: [→]), 
+                        math.cases(children: ({ math.lr(body: ({ [[], 
+                                                                 math.lr(body: ({ [|], 
+                                                                                  text(body: [1]), 
+                                                                                  [|] })), 
+                                                                 []] })), 
+                                                math.alignpoint(), 
+                                                text(body: [if ]), 
+                                                text(body: [n]), 
+                                                text(body: [>]), 
+                                                text(body: [>]), 
+                                                text(body: [>]), 
+                                                text(body: [10]) }, 
+                                              { text(body: [2]), 
+                                                text(body: [*]), 
+                                                text(body: [3]), 
+                                                math.alignpoint(), 
+                                                text(body: [if ]), 
+                                                text(body: [n]), 
+                                                text(body: [≠]), 
+                                                text(body: [5]) }, 
+                                              { text(body: [1]), 
+                                                text(body: [-]), 
+                                                text(body: [0]), 
+                                                text(body: [ ]), 
+                                                math.alignpoint(), 
+                                                text(body: […]) })) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/syntax-02.out b/test/out/math/syntax-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/syntax-02.out
@@ -0,0 +1,86 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/syntax-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/syntax-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/syntax-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/syntax-02.typ"
+        ( line 3 , column 3 )
+        (Ident (Identifier "dot"))
+    , HardBreak
+    , Code
+        "test/typ/math/syntax-02.typ"
+        ( line 3 , column 9 )
+        (Ident (Identifier "dots"))
+    , HardBreak
+    , Code
+        "test/typ/math/syntax-02.typ"
+        ( line 3 , column 16 )
+        (Ident (Identifier "ast"))
+    , HardBreak
+    , Code
+        "test/typ/math/syntax-02.typ"
+        ( line 3 , column 22 )
+        (Ident (Identifier "tilde"))
+    , HardBreak
+    , Code
+        "test/typ/math/syntax-02.typ"
+        ( line 3 , column 30 )
+        (Ident (Identifier "star"))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [⋅]), 
+                        linebreak(), 
+                        text(body: [⋯]), 
+                        linebreak(), 
+                        text(body: [∗]), 
+                        linebreak(), 
+                        text(body: [∼]), 
+                        linebreak(), 
+                        text(body: [⋆]) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/syntax-03.out b/test/out/math/syntax-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/syntax-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/math/unbalanced-00.out b/test/out/math/unbalanced-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/unbalanced-00.out
@@ -0,0 +1,132 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/unbalanced-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/unbalanced-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/unbalanced-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Equation
+    True
+    [ MFrac
+        (Text "1")
+        (MGroup
+           (Just "(")
+           Nothing
+           [ Text "2" , MGroup (Just "(") (Just ")") [ Text "x" ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ MAttach
+        (Just
+           (MGroup
+              (Just "(")
+              Nothing
+              [ Text "2"
+              , Text "y"
+              , MGroup (Just "(") (Just ")") [ Text "x" ]
+              , MGroup (Just "(") (Just ")") []
+              ]))
+        Nothing
+        (Text "1")
+    ]
+, SoftBreak
+, Equation
+    True
+    [ MFrac
+        (Text "1")
+        (MGroup
+           (Just "(")
+           Nothing
+           [ Text "2"
+           , Text "y"
+           , MGroup (Just "(") (Just ")") [ Text "x" ]
+           , MGroup
+               (Just "(")
+               (Just ")")
+               [ MGroup
+                   Nothing
+                   Nothing
+                   [ Text "2" , MGroup (Just "(") (Just ")") [ Text "3" ] ]
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.frac(denom: { text(body: [(]), 
+                                         text(body: [2]), 
+                                         math.lr(body: ({ [(], 
+                                                          text(body: [x]), 
+                                                          [)] })) }, 
+                                num: text(body: [1])), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.attach(b: { text(body: [(]), 
+                                       text(body: [2]), 
+                                       text(body: [y]), 
+                                       math.lr(body: ({ [(], 
+                                                        text(body: [x]), 
+                                                        [)] })), 
+                                       math.lr(body: ({ [(], 
+                                                        [)] })) }, 
+                                  base: text(body: [1]), 
+                                  t: none), 
+                numbering: none), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.frac(denom: { text(body: [(]), 
+                                         text(body: [2]), 
+                                         text(body: [y]), 
+                                         math.lr(body: ({ [(], 
+                                                          text(body: [x]), 
+                                                          [)] })), 
+                                         math.lr(body: ({ [(], 
+                                                          text(body: [2]), 
+                                                          math.lr(body: ({ [(], 
+                                                                           text(body: [3]), 
+                                                                           [)] })), 
+                                                          [)] })) }, 
+                                num: text(body: [1])), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/underover-00.out b/test/out/math/underover-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/underover-00.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/underover-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/underover-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/underover-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "x"
+    , Text "="
+    , Code
+        "test/typ/math/underover-00.typ"
+        ( line 3 , column 7 )
+        (FuncCall
+           (Ident (Identifier "underbrace"))
+           [ BlockArg
+               [ Text "1"
+               , Text "+"
+               , Text "2"
+               , Text "+"
+               , Text "\8230"
+               , Text "+"
+               , Text "5"
+               ]
+           , BlockArg
+               [ Code
+                   "test/typ/math/underover-00.typ"
+                   ( line 5 , column 3 )
+                   (FuncCall
+                      (Ident (Identifier "underbrace"))
+                      [ BlockArg [ Text "numbers" ]
+                      , BlockArg [ Text "x" , Text "+" , Text "y" ]
+                      ])
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        text(body: [=]), 
+                        math.underbrace(annotation: math.underbrace(annotation: { text(body: [x]), 
+                                                                                  text(body: [+]), 
+                                                                                  text(body: [y]) }, 
+                                                                    body: text(body: [numbers])), 
+                                        body: { text(body: [1]), 
+                                                text(body: [+]), 
+                                                text(body: [2]), 
+                                                text(body: [+]), 
+                                                text(body: […]), 
+                                                text(body: [+]), 
+                                                text(body: [5]) }) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/underover-01.out b/test/out/math/underover-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/underover-01.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/underover-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/underover-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/underover-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "x"
+    , Text "="
+    , Code
+        "test/typ/math/underover-01.typ"
+        ( line 3 , column 7 )
+        (FuncCall
+           (Ident (Identifier "overbracket"))
+           [ BlockArg
+               [ Code
+                   "test/typ/math/underover-01.typ"
+                   ( line 4 , column 3 )
+                   (FuncCall
+                      (Ident (Identifier "overline"))
+                      [ BlockArg
+                          [ Code
+                              "test/typ/math/underover-01.typ"
+                              ( line 4 , column 12 )
+                              (FuncCall
+                                 (Ident (Identifier "underline"))
+                                 [ BlockArg [ Text "x" , Text "+" , Text "y" ] ])
+                          ]
+                      ])
+               ]
+           , BlockArg
+               [ Text "1"
+               , Text "+"
+               , Text "2"
+               , Text "+"
+               , Text "\8230"
+               , Text "+"
+               , Text "5"
+               ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [x]), 
+                        text(body: [=]), 
+                        math.overbracket(annotation: { text(body: [1]), 
+                                                       text(body: [+]), 
+                                                       text(body: [2]), 
+                                                       text(body: [+]), 
+                                                       text(body: […]), 
+                                                       text(body: [+]), 
+                                                       text(body: [5]) }, 
+                                         body: math.overline(body: math.underline(body: { text(body: [x]), 
+                                                                                          text(body: [+]), 
+                                                                                          text(body: [y]) }))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/underover-02.out b/test/out/math/underover-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/underover-02.out
@@ -0,0 +1,105 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/underover-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/underover-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/underover-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Code
+        "test/typ/math/underover-02.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (Ident (Identifier "underbracket"))
+           [ BlockArg
+               [ MGroup
+                   (Just "[")
+                   (Just "]")
+                   [ Text "1" , Text "," , MFrac (Text "2") (Text "3") ]
+               ]
+           , BlockArg [ Text " relevant stuff" ]
+           ])
+    , Code
+        "test/typ/math/underover-02.typ"
+        ( line 4 , column 11 )
+        (FieldAccess
+           (Ident (Identifier "long"))
+           (FieldAccess
+              (Ident (Identifier "double"))
+              (FieldAccess
+                 (Ident (Identifier "r"))
+                 (FieldAccess
+                    (Ident (Identifier "l")) (Ident (Identifier "arrow"))))))
+    , Code
+        "test/typ/math/underover-02.typ"
+        ( line 5 , column 3 )
+        (FuncCall
+           (Ident (Identifier "overbracket"))
+           [ BlockArg
+               [ MGroup
+                   (Just "[")
+                   (Just "]")
+                   [ MFrac (Text "4") (Text "5") , Text "," , Text "6" ]
+               ]
+           , BlockArg [ Text " irrelevant stuff" ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { math.underbracket(annotation: text(body: [ relevant stuff]), 
+                                          body: math.lr(body: ({ [[], 
+                                                                 text(body: [1]), 
+                                                                 text(body: [,]), 
+                                                                 math.frac(denom: text(body: [3]), 
+                                                                           num: text(body: [2])), 
+                                                                 []] }))), 
+                        text(body: [⟺]), 
+                        math.overbracket(annotation: text(body: [ irrelevant stuff]), 
+                                         body: math.lr(body: ({ [[], 
+                                                                math.frac(denom: text(body: [5]), 
+                                                                          num: text(body: [4])), 
+                                                                text(body: [,]), 
+                                                                text(body: [6]), 
+                                                                []] }))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/vec-00.out b/test/out/math/vec-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/vec-00.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/vec-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/vec-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/vec-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Equation
+    True
+    [ Text "v"
+    , Text "="
+    , Code
+        "test/typ/math/vec-00.typ"
+        ( line 3 , column 7 )
+        (FuncCall
+           (Ident (Identifier "vec"))
+           [ BlockArg [ Text "1" ]
+           , BlockArg [ Text "2" , Text "+" , Text "3" ]
+           , BlockArg [ Text "4" ]
+           ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  math.equation(block: true, 
+                body: { text(body: [v]), 
+                        text(body: [=]), 
+                        math.vec(children: (text(body: [1]), 
+                                            { text(body: [2]), 
+                                              text(body: [+]), 
+                                              text(body: [3]) }, 
+                                            text(body: [4]))) }, 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/vec-01.out b/test/out/math/vec-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/vec-01.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/math/vec-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/math/vec-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/math/vec-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/math/vec-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (FieldAccess
+          (Ident (Identifier "vec")) (Ident (Identifier "math")))
+       [ KeyValArg (Identifier "delim") (Literal (String "[")) ])
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "test/typ/math/vec-01.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (Ident (Identifier "vec"))
+           [ BlockArg [ Text "1" ] , BlockArg [ Text "2" ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  math.equation(block: true, 
+                body: math.vec(children: (text(body: [1]), 
+                                          text(body: [2])), 
+                               delim: "["), 
+                numbering: none), 
+  parbreak() }
diff --git a/test/out/math/vec-02.out b/test/out/math/vec-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/math/vec-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/bibliography-00.out b/test/out/meta/bibliography-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/bibliography-00.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/bibliography-01.out b/test/out/meta/bibliography-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/bibliography-01.out
@@ -0,0 +1,106 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/bibliography-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/bibliography-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/bibliography-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt)) ])
+, SoftBreak
+, Heading 1 [ Text "Details" ]
+, Text "See"
+, Space
+, Text "also"
+, Space
+, Code
+    "test/typ/meta/bibliography-01.typ"
+    ( line 4 , column 11 )
+    (FuncCall
+       (Ident (Identifier "cite"))
+       [ NormalArg (Literal (String "arrgh"))
+       , NormalArg (Literal (String "distress"))
+       , NormalArg
+           (Block (Content [ Text "p" , Text "." , Space , Text "22" ]))
+       ])
+, Text ","
+, Space
+, Ref
+    "arrgh"
+    (Block (Content [ Text "p" , Text "." , Space , Text "4" ]))
+, Text ","
+, Space
+, Text "and"
+, Space
+, Ref
+    "distress"
+    (Block (Content [ Text "p" , Text "." , Space , Text "5" ]))
+, Text "."
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "bibliography"))
+       [ NormalArg (Literal (String "/works.bib")) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  heading(body: text(body: [Details]), 
+          level: 1), 
+  text(body: [See also ]), 
+  cite(keys: ("arrgh", 
+              "distress", 
+              text(body: [p. 22]))), 
+  text(body: [, ]), 
+  ref(supplement: text(body: [p. 4]), 
+      target: ), 
+  text(body: [, and ]), 
+  ref(supplement: text(body: [p. 5]), 
+      target: ), 
+  text(body: [.
+]), 
+  bibliography(path: "/works.bib"), 
+  parbreak() }
diff --git a/test/out/meta/bibliography-02.out b/test/out/meta/bibliography-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/bibliography-02.out
@@ -0,0 +1,166 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/bibliography-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/bibliography-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/bibliography-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/bibliography-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "bibliography"))
+       [ NormalArg (Literal (String "/works.bib"))
+       , KeyValArg
+           (Identifier "title")
+           (Block
+              (Content
+                 [ Text "Works"
+                 , Space
+                 , Text "to"
+                 , Space
+                 , Text "be"
+                 , Space
+                 , Text "cited"
+                 ]))
+       , KeyValArg
+           (Identifier "style") (Literal (String "chicago-author-date"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-02.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 100.0 Percent))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-02.typ"
+    ( line 6 , column 2 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/meta/bibliography-02.typ"
+              ( line 6 , column 4 )
+              (Set
+                 (Ident (Identifier "cite"))
+                 [ KeyValArg (Identifier "brackets") (Literal (Boolean False)) ])
+          , SoftBreak
+          , Text "As"
+          , Space
+          , Text "described"
+          , Space
+          , Text "by"
+          , Space
+          , Ref "netwok" (Literal Auto)
+          ]))
+, Text ","
+, SoftBreak
+, Text "the"
+, Space
+, Text "net"
+, Text "-"
+, Text "work"
+, Space
+, Text "is"
+, Space
+, Text "a"
+, Space
+, Text "creature"
+, Space
+, Text "of"
+, Space
+, Text "its"
+, Space
+, Text "own"
+, Text "."
+, SoftBreak
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "close"
+, Space
+, Text "to"
+, Space
+, Text "piratery!"
+, Space
+, Ref "arrgh" (Literal Auto)
+, SoftBreak
+, Text "And"
+, Space
+, Text "quark!"
+, Space
+, Ref "quark" (Literal Auto)
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  bibliography(path: "/works.bib", 
+               style: "chicago-author-date", 
+               title: text(body: [Works to be cited])), 
+  text(body: [
+]), 
+  line(length: 100%), 
+  text(body: [
+]), 
+  text(body: [
+As described by ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [,
+the net-work is a creature of its own.
+This is close to piratery! ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [
+And quark! ]), 
+  ref(supplement: auto, 
+      target: ), 
+  parbreak() }
diff --git a/test/out/meta/bibliography-03.out b/test/out/meta/bibliography-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/bibliography-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/bibliography-04.out b/test/out/meta/bibliography-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/bibliography-04.out
@@ -0,0 +1,118 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/bibliography-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/bibliography-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/bibliography-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-04.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "1.")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-04.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "bibliography")))
+       (Set
+          (Ident (Identifier "heading"))
+          [ KeyValArg (Identifier "numbering") (Literal (String "1.")) ]))
+, ParBreak
+, Heading 1 [ Text "Multiple" , Space , Text "Bibs" ]
+, Text "Now"
+, Space
+, Text "we"
+, Space
+, Text "have"
+, Space
+, Text "multiple"
+, Space
+, Text "bibliographies"
+, Space
+, Text "containing"
+, Space
+, Code
+    "test/typ/meta/bibliography-04.typ"
+    ( line 7 , column 49 )
+    (FuncCall
+       (Ident (Identifier "cite"))
+       [ NormalArg (Literal (String "glacier-melt"))
+       , NormalArg (Literal (String "keshav2007read"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-04.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "bibliography"))
+       [ NormalArg
+           (Array
+              [ Literal (String "/works.bib")
+              , Literal (String "/works_too.bib")
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Multiple Bibs]), 
+          level: 1, 
+          numbering: "1."), 
+  text(body: [Now we have multiple bibliographies containing ]), 
+  cite(keys: ("glacier-melt", 
+              "keshav2007read")), 
+  text(body: [
+]), 
+  bibliography(path: ("/works.bib", 
+                      "/works_too.bib")), 
+  parbreak() }
diff --git a/test/out/meta/bibliography-ordering-00.out b/test/out/meta/bibliography-ordering-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/bibliography-ordering-00.out
@@ -0,0 +1,134 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/bibliography-ordering-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/bibliography-ordering-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/bibliography-ordering-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/bibliography-ordering-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 300.0 Pt)) ])
+, ParBreak
+, Ref "mcintosh_anxiety" (Literal Auto)
+, Text ","
+, Space
+, Ref "psychology25" (Literal Auto)
+, SoftBreak
+, Ref "netwok" (Literal Auto)
+, Text ","
+, Space
+, Ref "issue201" (Literal Auto)
+, Text ","
+, Space
+, Ref "arrgh" (Literal Auto)
+, Text ","
+, Space
+, Ref "quark" (Literal Auto)
+, Text ","
+, Space
+, Ref "distress" (Literal Auto)
+, Text ","
+, SoftBreak
+, Ref "glacier-melt" (Literal Auto)
+, Text ","
+, Space
+, Ref "issue201" (Literal Auto)
+, Text ","
+, Space
+, Ref "tolkien54" (Literal Auto)
+, Text ","
+, Space
+, Ref "sharing" (Literal Auto)
+, Text ","
+, Space
+, Ref "restful" (Literal Auto)
+, ParBreak
+, Code
+    "test/typ/meta/bibliography-ordering-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "bibliography"))
+       [ NormalArg (Literal (String "/works.bib")) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [
+]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [,
+]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, ]), 
+  ref(supplement: auto, 
+      target: ), 
+  parbreak(), 
+  bibliography(path: "/works.bib"), 
+  parbreak() }
diff --git a/test/out/meta/cite-footnote-00.out b/test/out/meta/cite-footnote-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/cite-footnote-00.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/cite-footnote-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/cite-footnote-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/cite-footnote-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Text "Hello"
+, Space
+, Ref "netwok" (Literal Auto)
+, SoftBreak
+, Text "And"
+, Space
+, Text "again"
+, Text ":"
+, Space
+, Ref "netwok" (Literal Auto)
+, ParBreak
+, Code
+    "test/typ/meta/cite-footnote-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, SoftBreak
+, Code
+    "test/typ/meta/cite-footnote-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "bibliography"))
+       [ NormalArg (Literal (String "/works.bib"))
+       , KeyValArg (Identifier "style") (Literal (String "chicago-notes"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+Hello ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [
+And again: ]), 
+  ref(supplement: auto, 
+      target: ), 
+  parbreak(), 
+  pagebreak(), 
+  text(body: [
+]), 
+  bibliography(path: "/works.bib", 
+               style: "chicago-notes"), 
+  parbreak() }
diff --git a/test/out/meta/counter-00.out b/test/out/meta/counter-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/counter-00.out
@@ -0,0 +1,188 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/counter-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/counter-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/counter-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "mine")))
+       (FuncCall
+          (Ident (Identifier "counter"))
+          [ NormalArg (Literal (String "mine!")) ]))
+, ParBreak
+, Text "Final"
+, Text ":"
+, Space
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 5 , column 9 )
+    (FuncCall
+       (Ident (Identifier "locate"))
+       [ NormalArg
+           (FuncExpr
+              [ NormalParam (Identifier "loc") ]
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "at"))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "final")) (Ident (Identifier "mine")))
+                       [ NormalArg (Ident (Identifier "loc")) ]))
+                 [ NormalArg (Literal (Int 0)) ]))
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "step")) (Ident (Identifier "mine")))
+       [])
+, SoftBreak
+, Text "First"
+, Text ":"
+, Space
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 7 , column 9 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "display")) (Ident (Identifier "mine")))
+       [])
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "update")) (Ident (Identifier "mine")))
+       [ NormalArg (Literal (Int 7)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "display")) (Ident (Identifier "mine")))
+       [ NormalArg (Literal (String "1 of 1"))
+       , KeyValArg (Identifier "both") (Literal (Boolean True))
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "step")) (Ident (Identifier "mine")))
+       [])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "step")) (Ident (Identifier "mine")))
+       [])
+, SoftBreak
+, Text "Second"
+, Text ":"
+, Space
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 12 , column 10 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "display")) (Ident (Identifier "mine")))
+       [ NormalArg (Literal (String "I")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "update")) (Ident (Identifier "mine")))
+       [ NormalArg
+           (FuncExpr
+              [ NormalParam (Identifier "n") ]
+              (Times (Ident (Identifier "n")) (Literal (Int 2))))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-00.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "step")) (Ident (Identifier "mine")))
+       [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Final: ]), 
+  locate(func: ), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+First: ]), 
+  text(body: [1]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+]), 
+  text(body: [7]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+]), 
+  text(body: [
+Second: ]), 
+  text(body: [9]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/meta/counter-01.out b/test/out/meta/counter-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/counter-01.out
@@ -0,0 +1,134 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/counter-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/counter-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/counter-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 3 , column 2 )
+    (Let (BasicBind (Just (Identifier "label"))) (Label "heya"))
+, Space
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 3 , column 14 )
+    (Label "heya")
+, SoftBreak
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "count")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "display"))
+             (FuncCall
+                (Ident (Identifier "counter"))
+                [ NormalArg (Ident (Identifier "label")) ]))
+          []))
+, SoftBreak
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 5 , column 2 )
+    (LetFunc
+       (Identifier "elem")
+       [ NormalParam (Identifier "it") ]
+       (Block
+          (Content
+             [ Code
+                 "test/typ/meta/counter-01.typ"
+                 ( line 5 , column 19 )
+                 (FuncCall
+                    (Ident (Identifier "box")) [ NormalArg (Ident (Identifier "it")) ])
+             , Space
+             , Code
+                 "test/typ/meta/counter-01.typ"
+                 ( line 5 , column 28 )
+                 (Ident (Identifier "label"))
+             ])))
+, ParBreak
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "elem"))
+       [ BlockArg [ Text "hey," , Space , Text "there!" ] ])
+, Space
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 7 , column 21 )
+    (Ident (Identifier "count"))
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "elem"))
+       [ BlockArg [ Text "more" , Space , Text "here!" ] ])
+, Space
+, Code
+    "test/typ/meta/counter-01.typ"
+    ( line 8 , column 20 )
+    (Ident (Identifier "count"))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [ ]), 
+  <heya>, 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  box(body: text(body: [hey, there!])), 
+  text(body: [ ]), 
+  <heya>, 
+  text(body: [ ]), 
+  text(body: [0]), 
+  text(body: [ ]), 
+  linebreak(), 
+  box(body: text(body: [more here!])), 
+  text(body: [ ]), 
+  <heya>, 
+  text(body: [ ]), 
+  text(body: [0]), 
+  parbreak() }
diff --git a/test/out/meta/counter-02.out b/test/out/meta/counter-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/counter-02.out
@@ -0,0 +1,189 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/counter-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/counter-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/counter-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/counter-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "1.a.")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-02.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "heading")))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Literal (Numeric 10.0 Pt)) ]))
+, SoftBreak
+, Code
+    "test/typ/meta/counter-02.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "step"))
+          (FuncCall
+             (Ident (Identifier "counter"))
+             [ NormalArg (Ident (Identifier "heading")) ]))
+       [])
+, ParBreak
+, Heading 1 [ Text "Alpha" ]
+, Text "In"
+, Space
+, Code
+    "test/typ/meta/counter-02.typ"
+    ( line 8 , column 5 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "display"))
+          (FuncCall
+             (Ident (Identifier "counter"))
+             [ NormalArg (Ident (Identifier "heading")) ]))
+       [])
+, SoftBreak
+, Heading 2 [ Text "Beta" ]
+, Code
+    "test/typ/meta/counter-02.typ"
+    ( line 11 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal None) ])
+, SoftBreak
+, Heading 1 [ Text "Gamma" ]
+, Code
+    "test/typ/meta/counter-02.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "I."))
+       , BlockArg [ Text "Delta" ]
+       ])
+, ParBreak
+, Text "At"
+, Space
+, Text "Beta,"
+, Space
+, Text "it"
+, Space
+, Text "was"
+, Space
+, Code
+    "test/typ/meta/counter-02.typ"
+    ( line 15 , column 18 )
+    (FuncCall
+       (Ident (Identifier "locate"))
+       [ NormalArg
+           (FuncExpr
+              [ NormalParam (Identifier "loc") ]
+              (Block
+                 (CodeBlock
+                    [ Let
+                        (BasicBind (Just (Identifier "it")))
+                        (FuncCall
+                           (FieldAccess
+                              (Ident (Identifier "find"))
+                              (FuncCall
+                                 (Ident (Identifier "query"))
+                                 [ NormalArg (Ident (Identifier "heading"))
+                                 , NormalArg (Ident (Identifier "loc"))
+                                 ]))
+                           [ NormalArg
+                               (FuncExpr
+                                  [ NormalParam (Identifier "it") ]
+                                  (Equals
+                                     (FieldAccess
+                                        (Ident (Identifier "body")) (Ident (Identifier "it")))
+                                     (Block (Content [ Text "Beta" ]))))
+                           ])
+                    , FuncCall
+                        (Ident (Identifier "numbering"))
+                        [ NormalArg
+                            (FieldAccess
+                               (Ident (Identifier "numbering")) (Ident (Identifier "it")))
+                        , SpreadArg
+                            (FuncCall
+                               (FieldAccess
+                                  (Ident (Identifier "at"))
+                                  (FuncCall
+                                     (Ident (Identifier "counter"))
+                                     [ NormalArg (Ident (Identifier "heading")) ]))
+                               [ NormalArg
+                                   (FuncCall
+                                      (FieldAccess
+                                         (Ident (Identifier "location")) (Ident (Identifier "it")))
+                                      [])
+                               ])
+                        ]
+                    ])))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Alpha]), 
+          level: 1, 
+          numbering: "1.a."), 
+  text(body: [In ]), 
+  text(body: [1]), 
+  text(body: [
+]), 
+  heading(body: text(body: [Beta]), 
+          level: 2, 
+          numbering: "1.a."), 
+  text(body: [
+]), 
+  heading(body: text(body: [Gamma]), 
+          level: 1, 
+          numbering: none), 
+  heading(body: text(body: [Delta]), 
+          numbering: "I."), 
+  parbreak(), 
+  text(body: [At Beta, it was ]), 
+  locate(func: ), 
+  parbreak() }
diff --git a/test/out/meta/counter-03.out b/test/out/meta/counter-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/counter-03.out
@@ -0,0 +1,179 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/counter-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/counter-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/counter-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/counter-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "A"))
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "Four"
+                 , Space
+                 , Quote '\''
+                 , Text "A"
+                 , Quote '\''
+                 , Text "s"
+                 ]))
+       , KeyValArg (Identifier "kind") (Ident (Identifier "image"))
+       , KeyValArg (Identifier "supplement") (Literal (String "Figure"))
+       , BlockArg [ Emph [ Text "AAAA!" ] ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ KeyValArg (Identifier "numbering") (Literal None)
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "Four"
+                 , Space
+                 , Quote '\''
+                 , Text "B"
+                 , Quote '\''
+                 , Text "s"
+                 ]))
+       , KeyValArg (Identifier "kind") (Ident (Identifier "image"))
+       , KeyValArg (Identifier "supplement") (Literal (String "Figure"))
+       , BlockArg [ Emph [ Text "BBBB!" ] ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "Four"
+                 , Space
+                 , Quote '\''
+                 , Text "C"
+                 , Quote '\''
+                 , Text "s"
+                 ]))
+       , KeyValArg (Identifier "kind") (Ident (Identifier "image"))
+       , KeyValArg (Identifier "supplement") (Literal (String "Figure"))
+       , BlockArg [ Emph [ Text "CCCC!" ] ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "update"))
+          (FuncCall
+             (Ident (Identifier "counter"))
+             [ NormalArg
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "where")) (Ident (Identifier "figure")))
+                    [ KeyValArg (Identifier "kind") (Ident (Identifier "image")) ])
+             ]))
+       [ NormalArg
+           (FuncExpr
+              [ NormalParam (Identifier "n") ]
+              (Plus (Ident (Identifier "n")) (Literal (Int 3))))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-03.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "Four"
+                 , Space
+                 , Quote '\''
+                 , Text "D"
+                 , Quote '\''
+                 , Text "s"
+                 ]))
+       , KeyValArg (Identifier "kind") (Ident (Identifier "image"))
+       , KeyValArg (Identifier "supplement") (Literal (String "Figure"))
+       , BlockArg [ Emph [ Text "DDDD!" ] ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  figure(body: emph(body: text(body: [AAAA!])), 
+         caption: text(body: [Four ‘A’s]), 
+         kind: , 
+         numbering: "A", 
+         supplement: "Figure"), 
+  text(body: [
+]), 
+  figure(body: emph(body: text(body: [BBBB!])), 
+         caption: text(body: [Four ‘B’s]), 
+         kind: , 
+         numbering: none, 
+         supplement: "Figure"), 
+  text(body: [
+]), 
+  figure(body: emph(body: text(body: [CCCC!])), 
+         caption: text(body: [Four ‘C’s]), 
+         kind: , 
+         supplement: "Figure"), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  figure(body: emph(body: text(body: [DDDD!])), 
+         caption: text(body: [Four ‘D’s]), 
+         kind: , 
+         supplement: "Figure"), 
+  parbreak() }
diff --git a/test/out/meta/counter-page-00.out b/test/out/meta/counter-page-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/counter-page-00.out
@@ -0,0 +1,130 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/counter-page-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/counter-page-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 50.0 Pt))
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "bottom" , Literal (Numeric 20.0 Pt) )
+              , ( Identifier "rest" , Literal (Numeric 10.0 Pt) )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 12)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "(i)")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 6)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall (Ident (Identifier "pagebreak")) [])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 9 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "1 / 1")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "update"))
+          (FuncCall
+             (Ident (Identifier "counter"))
+             [ NormalArg (Ident (Identifier "page")) ]))
+       [ NormalArg (Literal (Int 1)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/counter-page-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur]), 
+  text(body: [
+]), 
+  pagebreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut]), 
+  parbreak() }
diff --git a/test/out/meta/document-00.out b/test/out/meta/document-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-00.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/document-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/document-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/document-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/document-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "document"))
+       [ KeyValArg (Identifier "title") (Literal (String "Hello")) ])
+, SoftBreak
+, Text "What"
+, Quote '\''
+, Text "s"
+, Space
+, Text "up?"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+What’s up?]), 
+  parbreak() }
diff --git a/test/out/meta/document-01.out b/test/out/meta/document-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-01.out
@@ -0,0 +1,58 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/document-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/document-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/document-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/meta/document-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "document"))
+       [ KeyValArg
+           (Identifier "author")
+           (Array [ Literal (String "A") , Literal (String "B") ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak() }
diff --git a/test/out/meta/document-02.out b/test/out/meta/document-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/document-03.out b/test/out/meta/document-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/document-04.out b/test/out/meta/document-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/document-05.out b/test/out/meta/document-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/document-06.out b/test/out/meta/document-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/document-07.out b/test/out/meta/document-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/document-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/figure-00.out b/test/out/meta/figure-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/figure-00.out
@@ -0,0 +1,225 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/figure-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/figure-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/figure-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 150.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "figure"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "I")) ])
+, ParBreak
+, Text "We"
+, Space
+, Text "can"
+, Space
+, Text "clearly"
+, Space
+, Text "see"
+, Space
+, Text "that"
+, Space
+, Ref "fig-cylinder" (Literal Auto)
+, Space
+, Text "and"
+, SoftBreak
+, Ref "tab-complex" (Literal Auto)
+, Space
+, Text "are"
+, Space
+, Text "relevant"
+, Space
+, Text "in"
+, Space
+, Text "this"
+, Space
+, Text "context"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "table"))
+              [ KeyValArg (Identifier "columns") (Literal (Int 2))
+              , BlockArg [ Text "a" ]
+              , BlockArg [ Text "b" ]
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "The"
+                 , Space
+                 , Text "basic"
+                 , Space
+                 , Text "table"
+                 , Text "."
+                 ]))
+       ])
+, Space
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 11 , column 3 )
+    (Label "tab-basic")
+, ParBreak
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "pad"))
+              [ KeyValArg (Identifier "y") (Negated (Literal (Numeric 6.0 Pt)))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "image"))
+                     [ NormalArg (Literal (String "test/assets/files/cylinder.svg"))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm))
+                     ])
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "The"
+                 , Space
+                 , Text "basic"
+                 , Space
+                 , Text "shapes"
+                 , Text "."
+                 ]))
+       , KeyValArg (Identifier "numbering") (Literal (String "I"))
+       ])
+, Space
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 17 , column 3 )
+    (Label "fig-cylinder")
+, ParBreak
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "table"))
+              [ KeyValArg (Identifier "columns") (Literal (Int 3))
+              , BlockArg [ Text "a" ]
+              , BlockArg [ Text "b" ]
+              , BlockArg [ Text "c" ]
+              , BlockArg [ Text "d" ]
+              , BlockArg [ Text "e" ]
+              , BlockArg [ Text "f" ]
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "The"
+                 , Space
+                 , Text "complex"
+                 , Space
+                 , Text "table"
+                 , Text "."
+                 ]))
+       ])
+, Space
+, Code
+    "test/typ/meta/figure-00.typ"
+    ( line 22 , column 3 )
+    (Label "tab-complex")
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [We can clearly see that ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [ and
+]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [ are relevant in this context.]), 
+  parbreak(), 
+  figure(body: table(children: (text(body: [a]), 
+                                text(body: [b])), 
+                     columns: 2), 
+         caption: text(body: [The basic table.]), 
+         numbering: "I"), 
+  text(body: [ ]), 
+  <tab-basic>, 
+  parbreak(), 
+  figure(body: pad(body: image(height: 2.0cm, 
+                               path: "test/assets/files/cylinder.svg"), 
+                   y: -6.0pt), 
+         caption: text(body: [The basic shapes.]), 
+         numbering: "I"), 
+  text(body: [ ]), 
+  <fig-cylinder>, 
+  parbreak(), 
+  figure(body: table(children: (text(body: [a]), 
+                                text(body: [b]), 
+                                text(body: [c]), 
+                                text(body: [d]), 
+                                text(body: [e]), 
+                                text(body: [f])), 
+                     columns: 3), 
+         caption: text(body: [The complex table.]), 
+         numbering: "I"), 
+  text(body: [ ]), 
+  <tab-complex>, 
+  parbreak() }
diff --git a/test/out/meta/figure-01.out b/test/out/meta/figure-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/figure-01.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/figure-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/figure-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/figure-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Comment
+, Code
+    "test/typ/meta/figure-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "table"))
+              [ KeyValArg (Identifier "columns") (Literal (Int 2))
+              , NormalArg
+                  (Block (Content [ Text "Second" , Space , Text "cylinder" ]))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "image"))
+                     [ NormalArg (Literal (String "test/assets/files/cylinder.svg")) ])
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Literal (String "A table containing images."))
+       ])
+, Space
+, Code
+    "test/typ/meta/figure-01.typ"
+    ( line 11 , column 3 )
+    (Label "fig-image-in-table")
+, ParBreak
+]
+--- evaluated ---
+{ parbreak(), 
+  figure(body: table(children: (text(body: [Second cylinder]), 
+                                image(path: "test/assets/files/cylinder.svg")), 
+                     columns: 2), 
+         caption: "A table containing images."), 
+  text(body: [ ]), 
+  <fig-image-in-table>, 
+  parbreak() }
diff --git a/test/out/meta/figure-02.out b/test/out/meta/figure-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/figure-02.out
@@ -0,0 +1,294 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/figure-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/figure-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/figure-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Comment
+, Code
+    "test/typ/meta/figure-02.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "figure")))
+             [ KeyValArg (Identifier "kind") (Literal (String "theorem")) ]))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ Let (BasicBind (Just (Identifier "name"))) (Literal None)
+                , If
+                    [ ( Not
+                          (Equals
+                             (FieldAccess
+                                (Ident (Identifier "caption")) (Ident (Identifier "it")))
+                             (Literal None))
+                      , Block
+                          (CodeBlock
+                             [ Assign
+                                 (Binding (BasicBind (Just (Identifier "name"))))
+                                 (Block
+                                    (Content
+                                       [ Space
+                                       , Code
+                                           "test/typ/meta/figure-02.typ"
+                                           ( line 7 , column 15 )
+                                           (FuncCall
+                                              (Ident (Identifier "emph"))
+                                              [ NormalArg
+                                                  (FieldAccess
+                                                     (Ident (Identifier "caption"))
+                                                     (Ident (Identifier "it")))
+                                              ])
+                                       ]))
+                             ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (CodeBlock
+                             [ Assign
+                                 (Binding (BasicBind (Just (Identifier "name"))))
+                                 (Block (Content []))
+                             ])
+                      )
+                    ]
+                , Let (BasicBind (Just (Identifier "title"))) (Literal None)
+                , If
+                    [ ( Not
+                          (Equals
+                             (FieldAccess
+                                (Ident (Identifier "numbering")) (Ident (Identifier "it")))
+                             (Literal None))
+                      , Block
+                          (CodeBlock
+                             [ Assign
+                                 (Binding (BasicBind (Just (Identifier "title"))))
+                                 (FieldAccess
+                                    (Ident (Identifier "supplement")) (Ident (Identifier "it")))
+                             , If
+                                 [ ( Not
+                                       (Equals
+                                          (FieldAccess
+                                             (Ident (Identifier "numbering"))
+                                             (Ident (Identifier "it")))
+                                          (Literal None))
+                                   , Block
+                                       (CodeBlock
+                                          [ Assign
+                                              (Ident (Identifier "title"))
+                                              (Plus
+                                                 (Ident (Identifier "title"))
+                                                 (Plus
+                                                    (Literal (String " "))
+                                                    (FuncCall
+                                                       (FieldAccess
+                                                          (Ident (Identifier "display"))
+                                                          (FieldAccess
+                                                             (Ident (Identifier "counter"))
+                                                             (Ident (Identifier "it"))))
+                                                       [ NormalArg
+                                                           (FieldAccess
+                                                              (Ident (Identifier "numbering"))
+                                                              (Ident (Identifier "it")))
+                                                       ])))
+                                          ])
+                                   )
+                                 ]
+                             ])
+                      )
+                    ]
+                , Assign
+                    (Binding (BasicBind (Just (Identifier "title"))))
+                    (FuncCall
+                       (Ident (Identifier "strong"))
+                       [ NormalArg (Ident (Identifier "title")) ])
+                , FuncCall
+                    (Ident (Identifier "pad"))
+                    [ KeyValArg (Identifier "top") (Literal (Numeric 0.0 Em))
+                    , KeyValArg (Identifier "bottom") (Literal (Numeric 0.0 Em))
+                    , NormalArg
+                        (FuncCall
+                           (Ident (Identifier "block"))
+                           [ KeyValArg
+                               (Identifier "fill")
+                               (FuncCall
+                                  (FieldAccess
+                                     (Ident (Identifier "lighten")) (Ident (Identifier "green")))
+                                  [ NormalArg (Literal (Numeric 90.0 Percent)) ])
+                           , KeyValArg
+                               (Identifier "stroke")
+                               (Plus (Literal (Numeric 1.0 Pt)) (Ident (Identifier "green")))
+                           , KeyValArg (Identifier "inset") (Literal (Numeric 10.0 Pt))
+                           , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+                           , KeyValArg (Identifier "radius") (Literal (Numeric 5.0 Pt))
+                           , KeyValArg (Identifier "breakable") (Literal (Boolean False))
+                           , NormalArg
+                               (Block
+                                  (Content
+                                     [ Code
+                                         "test/typ/meta/figure-02.typ"
+                                         ( line 29 , column 9 )
+                                         (Ident (Identifier "title"))
+                                     , Code
+                                         "test/typ/meta/figure-02.typ"
+                                         ( line 29 , column 15 )
+                                         (Ident (Identifier "name"))
+                                     , Code
+                                         "test/typ/meta/figure-02.typ"
+                                         ( line 29 , column 20 )
+                                         (FuncCall
+                                            (Ident (Identifier "h"))
+                                            [ NormalArg (Literal (Numeric 0.1 Em)) ])
+                                     , Text ":"
+                                     , Code
+                                         "test/typ/meta/figure-02.typ"
+                                         ( line 29 , column 30 )
+                                         (FuncCall
+                                            (Ident (Identifier "h"))
+                                            [ NormalArg (Literal (Numeric 0.2 Em)) ])
+                                     , Code
+                                         "test/typ/meta/figure-02.typ"
+                                         ( line 29 , column 39 )
+                                         (FieldAccess
+                                            (Ident (Identifier "body")) (Ident (Identifier "it")))
+                                     , Code
+                                         "test/typ/meta/figure-02.typ"
+                                         ( line 29 , column 47 )
+                                         (FuncCall
+                                            (Ident (Identifier "v"))
+                                            [ NormalArg (Literal (Numeric 0.5 Em)) ])
+                                     ]))
+                           ])
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/meta/figure-02.typ"
+    ( line 34 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 150.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/figure-02.typ"
+    ( line 35 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     False
+                     [ MAttach Nothing (Just (Text "2")) (Text "a")
+                     , Text "+"
+                     , MAttach Nothing (Just (Text "2")) (Text "b")
+                     , Text "="
+                     , MAttach Nothing (Just (Text "2")) (Text "c")
+                     ]
+                 ]))
+       , KeyValArg (Identifier "supplement") (Literal (String "Theorem"))
+       , KeyValArg (Identifier "kind") (Literal (String "theorem"))
+       , KeyValArg
+           (Identifier "caption") (Literal (String "Pythagoras' theorem."))
+       , KeyValArg (Identifier "numbering") (Literal (String "1"))
+       ])
+, Space
+, Code
+    "test/typ/meta/figure-02.typ"
+    ( line 41 , column 3 )
+    (Label "fig-formula")
+, ParBreak
+, Code
+    "test/typ/meta/figure-02.typ"
+    ( line 43 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (Block
+              (Content
+                 [ Equation
+                     False
+                     [ MAttach Nothing (Just (Text "2")) (Text "a")
+                     , Text "+"
+                     , MAttach Nothing (Just (Text "2")) (Text "b")
+                     , Text "="
+                     , MAttach Nothing (Just (Text "2")) (Text "c")
+                     ]
+                 ]))
+       , KeyValArg (Identifier "supplement") (Literal (String "Theorem"))
+       , KeyValArg (Identifier "kind") (Literal (String "theorem"))
+       , KeyValArg
+           (Identifier "caption")
+           (Literal (String "Another Pythagoras' theorem."))
+       , KeyValArg (Identifier "numbering") (Literal None)
+       ])
+, Space
+, Code
+    "test/typ/meta/figure-02.typ"
+    ( line 49 , column 3 )
+    (Label "fig-formula")
+, ParBreak
+, Code
+    "test/typ/meta/figure-02.typ"
+    ( line 51 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (Block
+              (Content
+                 [ RawBlock "rust" "fn main() {\n    println!(\"Hello!\");\n  }\n  "
+                 ]))
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "Hello"
+                 , Space
+                 , Text "world"
+                 , Space
+                 , Text "in"
+                 , Space
+                 , Emph [ Text "rust" ]
+                 ]))
+       ])
+, ParBreak
+]
+"test/typ/meta/figure-02.typ" (line 35, column 2):
+Content does not have a method "counter" or FieldAccess requires a dictionary
diff --git a/test/out/meta/figure-03.out b/test/out/meta/figure-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/figure-03.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/figure-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/figure-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/figure-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/figure-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 6.0 Em)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/figure-03.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just (Ident (Identifier "figure")))
+       (Set
+          (Ident (Identifier "block"))
+          [ KeyValArg (Identifier "breakable") (Literal (Boolean True)) ]))
+, ParBreak
+, Code
+    "test/typ/meta/figure-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "table"))
+              [ BlockArg [ Text "a" ]
+              , BlockArg [ Text "b" ]
+              , BlockArg [ Text "c" ]
+              , BlockArg [ Text "d" ]
+              , BlockArg [ Text "e" ]
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block (Content [ Text "A" , Space , Text "table" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  figure(body: table(children: (text(body: [a]), 
+                                text(body: [b]), 
+                                text(body: [c]), 
+                                text(body: [d]), 
+                                text(body: [e]))), 
+         caption: text(body: [A table])), 
+  parbreak() }
diff --git a/test/out/meta/footnote-00.out b/test/out/meta/footnote-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-00.out
@@ -0,0 +1,53 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "footnote")) [ BlockArg [ Text "Hi" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  footnote(body: text(body: [Hi])), 
+  parbreak() }
diff --git a/test/out/meta/footnote-01.out b/test/out/meta/footnote-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-01.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Code
+    "test/typ/meta/footnote-01.typ"
+    ( line 3 , column 3 )
+    (FuncCall
+       (Ident (Identifier "footnote")) [ BlockArg [ Text "A" ] ])
+, Space
+, HardBreak
+, Text "A"
+, Space
+, Code
+    "test/typ/meta/footnote-01.typ"
+    ( line 4 , column 4 )
+    (FuncCall
+       (Ident (Identifier "footnote")) [ BlockArg [ Text "A" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A]), 
+  footnote(body: text(body: [A])), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [A ]), 
+  footnote(body: text(body: [A])), 
+  parbreak() }
diff --git a/test/out/meta/footnote-02.out b/test/out/meta/footnote-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-02.out
@@ -0,0 +1,114 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "First"
+, Space
+, HardBreak
+, Text "Second"
+, Space
+, Code
+    "test/typ/meta/footnote-02.typ"
+    ( line 4 , column 9 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Text "A,"
+           , Space
+           , Code
+               "test/typ/meta/footnote-02.typ"
+               ( line 4 , column 22 )
+               (FuncCall
+                  (Ident (Identifier "footnote"))
+                  [ BlockArg
+                      [ Text "B,"
+                      , Space
+                      , Code
+                          "test/typ/meta/footnote-02.typ"
+                          ( line 4 , column 35 )
+                          (FuncCall
+                             (Ident (Identifier "footnote")) [ BlockArg [ Text "C" ] ])
+                      ]
+                  ])
+           ]
+       ])
+, Space
+, HardBreak
+, Text "Third"
+, Space
+, Code
+    "test/typ/meta/footnote-02.typ"
+    ( line 5 , column 8 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Text "D,"
+           , Space
+           , Code
+               "test/typ/meta/footnote-02.typ"
+               ( line 5 , column 21 )
+               (FuncCall
+                  (Ident (Identifier "footnote")) [ BlockArg [ Text "E" ] ])
+           ]
+       ])
+, Space
+, HardBreak
+, Text "Fourth"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [First ]), 
+  linebreak(), 
+  text(body: [Second ]), 
+  footnote(body: { text(body: [A, ]), 
+                   footnote(body: { text(body: [B, ]), 
+                                    footnote(body: text(body: [C])) }) }), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [Third ]), 
+  footnote(body: { text(body: [D, ]), 
+                   footnote(body: text(body: [E])) }), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [Fourth]), 
+  parbreak() }
diff --git a/test/out/meta/footnote-03.out b/test/out/meta/footnote-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-03.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/meta/footnote-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Text "A,"
+           , Space
+           , Code
+               "test/typ/meta/footnote-03.typ"
+               ( line 4 , column 15 )
+               (FuncCall
+                  (Ident (Identifier "footnote")) [ BlockArg [ Text "B" ] ])
+           ]
+       ])
+, Text ","
+, Space
+, Code
+    "test/typ/meta/footnote-03.typ"
+    ( line 4 , column 30 )
+    (FuncCall
+       (Ident (Identifier "footnote")) [ BlockArg [ Text "C" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  footnote(body: { text(body: [A, ]), 
+                   footnote(body: text(body: [B])) }), 
+  text(body: [, ]), 
+  footnote(body: text(body: [C])), 
+  parbreak() }
diff --git a/test/out/meta/footnote-04.out b/test/out/meta/footnote-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-04.out
@@ -0,0 +1,111 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/footnote-04.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "footnote")))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Ident (Identifier "red")) ]))
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-04.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just
+          (FieldAccess
+             (Ident (Identifier "entry")) (Ident (Identifier "footnote"))))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Literal (Numeric 8.0 Pt))
+          , KeyValArg (Identifier "style") (Literal (String "italic"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-04.typ"
+    ( line 5 , column 2 )
+    (Set
+       (FieldAccess
+          (Ident (Identifier "entry")) (Ident (Identifier "footnote")))
+       [ KeyValArg (Identifier "indent") (Literal (Numeric 0.0 Pt))
+       , KeyValArg (Identifier "gap") (Literal (Numeric 0.6 Em))
+       , KeyValArg (Identifier "clearance") (Literal (Numeric 0.3 Em))
+       , KeyValArg
+           (Identifier "separator")
+           (FuncCall (Ident (Identifier "repeat")) [ BlockArg [ Text "." ] ])
+       ])
+, ParBreak
+, Text "Beautiful"
+, Space
+, Text "footnotes"
+, Text "."
+, Space
+, Code
+    "test/typ/meta/footnote-04.typ"
+    ( line 12 , column 23 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Text "Wonderful,"
+           , Space
+           , Text "aren"
+           , Quote '\''
+           , Text "t"
+           , Space
+           , Text "they?"
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Beautiful footnotes. ]), 
+  footnote(body: text(body: [Wonderful, aren’t they?])), 
+  parbreak() }
diff --git a/test/out/meta/footnote-break-00.out b/test/out/meta/footnote-break-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-break-00.out
@@ -0,0 +1,202 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-break-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-break-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 200.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 5)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Space
+           , Comment
+           , Space
+           , Text "A"
+           , Space
+           , Text "simple"
+           , Space
+           , Text "footnote"
+           , Text "."
+           , SoftBreak
+           , Code
+               "test/typ/meta/footnote-break-00.typ"
+               ( line 7 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "footnote"))
+                  [ BlockArg
+                      [ Text "Well,"
+                      , Space
+                      , Text "not"
+                      , Space
+                      , Text "that"
+                      , Space
+                      , Text "simple"
+                      , Space
+                      , Ellipsis
+                      ]
+                  ])
+           , Space
+           , Comment
+           ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 15)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Text "Another"
+           , Space
+           , Text "footnote"
+           , Text ":"
+           , Space
+           , Code
+               "test/typ/meta/footnote-break-00.typ"
+               ( line 10 , column 30 )
+               (FuncCall
+                  (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 30)) ])
+           ]
+       ])
+, Space
+, Comment
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 15)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Text "My"
+           , Space
+           , Text "fourth"
+           , Space
+           , Text "footnote"
+           , Text ":"
+           , Space
+           , Code
+               "test/typ/meta/footnote-break-00.typ"
+               ( line 12 , column 32 )
+               (FuncCall
+                  (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 50)) ])
+           ]
+       ])
+, Space
+, Comment
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 15)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-break-00.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Text "And"
+           , Space
+           , Text "a"
+           , Space
+           , Text "final"
+           , Space
+           , Text "footnote"
+           , Text "."
+           ]
+       ])
+, Space
+, Comment
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet,]), 
+  text(body: [
+]), 
+  footnote(body: { text(body: [ ]), 
+                   text(body: [ A simple footnote.
+]), 
+                   footnote(body: text(body: [Well, not that simple …])), 
+                   text(body: [ ]) }), 
+  text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore]), 
+  text(body: [
+]), 
+  footnote(body: { text(body: [Another footnote: ]), 
+                   text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi]) }), 
+  text(body: [ ]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore]), 
+  text(body: [
+]), 
+  footnote(body: { text(body: [My fourth footnote: ]), 
+                   text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat]) }), 
+  text(body: [ ]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore]), 
+  text(body: [
+]), 
+  footnote(body: text(body: [And a final footnote.])), 
+  text(body: [ ]) }
diff --git a/test/out/meta/footnote-container-00.out b/test/out/meta/footnote-container-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-container-00.out
@@ -0,0 +1,157 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-container-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-container-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-container-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Read"
+, Space
+, Text "the"
+, Space
+, Text "docs"
+, Space
+, Code
+    "test/typ/meta/footnote-container-00.typ"
+    ( line 3 , column 16 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg [ Url "https://typst.app/docs" ] ])
+, Text "!"
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-container-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/graph.png"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 70.0 Percent))
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ SoftBreak
+                 , Text "A"
+                 , Space
+                 , Text "graph"
+                 , Space
+                 , Code
+                     "test/typ/meta/footnote-container-00.typ"
+                     ( line 7 , column 14 )
+                     (FuncCall
+                        (Ident (Identifier "footnote"))
+                        [ BlockArg
+                            [ Text "A"
+                            , Space
+                            , Emph [ Text "graph" ]
+                            , Space
+                            , Text "is"
+                            , Space
+                            , Text "a"
+                            , Space
+                            , Text "structure"
+                            , Space
+                            , Text "with"
+                            , Space
+                            , Text "nodes"
+                            , Space
+                            , Text "and"
+                            , Space
+                            , Text "edges"
+                            , Text "."
+                            ]
+                        ])
+                 , ParBreak
+                 ]))
+       ])
+, SoftBreak
+, Text "More"
+, Space
+, Code
+    "test/typ/meta/footnote-container-00.typ"
+    ( line 10 , column 7 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg [ Text "just" , Space , Text "for" , Space , Ellipsis ]
+       ])
+, Space
+, Text "footnotes"
+, Space
+, Code
+    "test/typ/meta/footnote-container-00.typ"
+    ( line 10 , column 41 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ BlockArg
+           [ Ellipsis
+           , Space
+           , Text "testing"
+           , Text "."
+           , Space
+           , Text ":"
+           , Text ")"
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Read the docs ]), 
+  footnote(body: link(body: [https://typst.app/docs], 
+                      dest: "https://typst.app/docs")), 
+  text(body: [!
+]), 
+  figure(body: image(path: "test/assets/files/graph.png", 
+                     width: 70%), 
+         caption: { text(body: [
+A graph ]), 
+                    footnote(body: { text(body: [A ]), 
+                                     emph(body: text(body: [graph])), 
+                                     text(body: [ is a structure with nodes and edges.]) }), 
+                    parbreak() }), 
+  text(body: [
+More ]), 
+  footnote(body: text(body: [just for …])), 
+  text(body: [ footnotes ]), 
+  footnote(body: text(body: [… testing. :)])), 
+  parbreak() }
diff --git a/test/out/meta/footnote-container-01.out b/test/out/meta/footnote-container-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-container-01.out
@@ -0,0 +1,202 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-container-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-container-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-container-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/footnote-container-01.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "lang")))
+       (FuncCall
+          (Ident (Identifier "footnote"))
+          [ BlockArg [ Text "Languages" , Text "." ] ]))
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-container-01.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "nums")))
+       (FuncCall
+          (Ident (Identifier "footnote"))
+          [ BlockArg [ Text "Numbers" , Text "." ] ]))
+, ParBreak
+, DescListItem
+    [ Quote '"' , Text "Hello" , Quote '"' ]
+    [ Text "A"
+    , Space
+    , Text "word"
+    , Space
+    , Code
+        "test/typ/meta/footnote-container-01.typ"
+        ( line 6 , column 20 )
+        (Ident (Identifier "lang"))
+    ]
+, SoftBreak
+, DescListItem
+    [ Quote '"' , Text "123" , Quote '"' ]
+    [ Text "A"
+    , Space
+    , Text "number"
+    , Space
+    , Code
+        "test/typ/meta/footnote-container-01.typ"
+        ( line 7 , column 20 )
+        (Ident (Identifier "nums"))
+    , SoftBreak
+    ]
+, SoftBreak
+, BulletListItem
+    [ Quote '"'
+    , Text "Hello"
+    , Quote '"'
+    , Space
+    , Code
+        "test/typ/meta/footnote-container-01.typ"
+        ( line 9 , column 12 )
+        (Ident (Identifier "lang"))
+    ]
+, SoftBreak
+, BulletListItem
+    [ Quote '"'
+    , Text "123"
+    , Quote '"'
+    , Space
+    , Code
+        "test/typ/meta/footnote-container-01.typ"
+        ( line 10 , column 10 )
+        (Ident (Identifier "nums"))
+    , SoftBreak
+    ]
+, SoftBreak
+, EnumListItem
+    Nothing
+    [ Quote '"'
+    , Text "Hello"
+    , Quote '"'
+    , Space
+    , Code
+        "test/typ/meta/footnote-container-01.typ"
+        ( line 12 , column 12 )
+        (Ident (Identifier "lang"))
+    ]
+, SoftBreak
+, EnumListItem
+    Nothing
+    [ Quote '"'
+    , Text "123"
+    , Quote '"'
+    , Space
+    , Code
+        "test/typ/meta/footnote-container-01.typ"
+        ( line 13 , column 10 )
+        (Ident (Identifier "nums"))
+    , SoftBreak
+    ]
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-container-01.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 2))
+       , NormalArg (Block (Content [ Text "Hello" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "A"
+                 , Space
+                 , Text "word"
+                 , Space
+                 , Code
+                     "test/typ/meta/footnote-container-01.typ"
+                     ( line 17 , column 21 )
+                     (Ident (Identifier "lang"))
+                 ]))
+       , NormalArg (Block (Content [ Text "123" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "A"
+                 , Space
+                 , Text "number"
+                 , Space
+                 , Code
+                     "test/typ/meta/footnote-container-01.typ"
+                     ( line 18 , column 21 )
+                     (Ident (Identifier "nums"))
+                 ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  terms(children: ((text(body: [“Hello”]), 
+                    { text(body: [A word ]), 
+                      footnote(body: text(body: [Languages.])) }), 
+                   (text(body: [“123”]), 
+                    { text(body: [A number ]), 
+                      footnote(body: text(body: [Numbers.])), 
+                      text(body: [
+]) }))), 
+  list(children: ({ text(body: [“Hello” ]), 
+                    footnote(body: text(body: [Languages.])) }, 
+                  { text(body: [“123” ]), 
+                    footnote(body: text(body: [Numbers.])), 
+                    text(body: [
+]) })), 
+  enum(children: ({ text(body: [“Hello” ]), 
+                    footnote(body: text(body: [Languages.])) }, 
+                  { text(body: [“123” ]), 
+                    footnote(body: text(body: [Numbers.])), 
+                    text(body: [
+]) })), 
+  table(children: (text(body: [Hello]), 
+                   { text(body: [A word ]), 
+                     footnote(body: text(body: [Languages.])) }, 
+                   text(body: [123]), 
+                   { text(body: [A number ]), 
+                     footnote(body: text(body: [Numbers.])) }), 
+        columns: 2), 
+  parbreak() }
diff --git a/test/out/meta/footnote-invariant-00.out b/test/out/meta/footnote-invariant-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/footnote-invariant-00.out
@@ -0,0 +1,76 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/footnote-invariant-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/footnote-invariant-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/footnote-invariant-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/footnote-invariant-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 120.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/meta/footnote-invariant-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 13)) ])
+, ParBreak
+, Text "There"
+, Space
+, Code
+    "test/typ/meta/footnote-invariant-00.typ"
+    ( line 6 , column 8 )
+    (FuncCall
+       (Ident (Identifier "footnote"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt]), 
+  parbreak(), 
+  text(body: [There ]), 
+  footnote(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut]), 
+  parbreak() }
diff --git a/test/out/meta/heading-00.out b/test/out/meta/heading-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/heading-00.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/heading-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/heading-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/heading-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Heading 1 [ Text "Level" , Space , Text "1" ]
+, Heading 2 [ Text "Level" , Space , Text "2" ]
+, Heading 3 [ Text "Level" , Space , Text "3" ]
+, Comment
+, Heading 11 [ Text "Level" , Space , Text "11" ]
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  heading(body: text(body: [Level 1]), 
+          level: 1), 
+  heading(body: text(body: [Level 2]), 
+          level: 2), 
+  heading(body: text(body: [Level 3]), 
+          level: 3), 
+  heading(body: text(body: [Level 11]), 
+          level: 11) }
diff --git a/test/out/meta/heading-01.out b/test/out/meta/heading-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/heading-01.out
@@ -0,0 +1,97 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/heading-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/heading-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/heading-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Comment
+, Space
+, Text "="
+, Space
+, Text "Level"
+, Space
+, Text "1"
+, SoftBreak
+, Code
+    "test/typ/meta/heading-01.typ"
+    ( line 6 , column 2 )
+    (Block (Content [ Heading 2 [ Text "Level" , Space , Text "2" ] ]))
+, SoftBreak
+, Code
+    "test/typ/meta/heading-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ BlockArg [ Heading 3 [ Text "Level" , Space , Text "3" ] ] ])
+, ParBreak
+, Comment
+, Text "No"
+, Space
+, Text "="
+, Space
+, Text "heading"
+, ParBreak
+, Comment
+, Text "="
+, Space
+, Text "No"
+, Space
+, Text "heading"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [ = Level 1
+]), 
+  heading(body: text(body: [Level 2]), 
+          level: 2), 
+  text(body: [
+]), 
+  box(body: heading(body: text(body: [Level 3]), 
+                    level: 3)), 
+  parbreak(), 
+  text(body: [No = heading]), 
+  parbreak(), 
+  text(body: [= No heading]), 
+  parbreak() }
diff --git a/test/out/meta/heading-02.out b/test/out/meta/heading-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/heading-02.out
@@ -0,0 +1,80 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/heading-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/heading-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/heading-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Heading
+    1
+    [ Code
+        "test/typ/meta/heading-02.typ"
+        ( line 4 , column 4 )
+        (Block
+           (Content
+              [ Text "This"
+              , SoftBreak
+              , Text "is"
+              , SoftBreak
+              , Text "multiline"
+              , Text "."
+              , ParBreak
+              ]))
+    ]
+, Heading 1 [ Text "This" ]
+, Text "is"
+, Space
+, Text "not"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  heading(body: { text(body: [This
+is
+multiline.]), 
+                  parbreak() }, 
+          level: 1), 
+  heading(body: text(body: [This]), 
+          level: 1), 
+  text(body: [is not.]), 
+  parbreak() }
diff --git a/test/out/meta/heading-03.out b/test/out/meta/heading-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/heading-03.out
@@ -0,0 +1,94 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/heading-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/heading-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/heading-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/heading-03.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "heading")))
+             [ KeyValArg (Identifier "level") (Literal (Int 5)) ]))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (FuncCall
+             (Ident (Identifier "block"))
+             [ NormalArg
+                 (FuncCall
+                    (Ident (Identifier "text"))
+                    [ KeyValArg (Identifier "font") (Literal (String "Roboto"))
+                    , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+                    , NormalArg
+                        (Plus
+                           (FieldAccess (Ident (Identifier "body")) (Ident (Identifier "it")))
+                           (Block (Content [ Text "!" ])))
+                    ])
+             ])))
+, ParBreak
+, Heading 1 [ Text "Heading" ]
+, Heading 5 [ Text "Heading" , Space , Text "\127757" ]
+, Code
+    "test/typ/meta/heading-03.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "level") (Literal (Int 5))
+       , BlockArg [ Text "Heading" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Heading]), 
+          level: 1), 
+  block(body: text(body: { text(body: [Heading 🌍]), 
+                           text(body: [!]) }, 
+                   fill: rgb(13%,61%,67%,100%), 
+                   font: "Roboto")), 
+  block(body: text(body: { text(body: [Heading]), 
+                           text(body: [!]) }, 
+                   fill: rgb(13%,61%,67%,100%), 
+                   font: "Roboto")), 
+  parbreak() }
diff --git a/test/out/meta/heading-04.out b/test/out/meta/heading-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/heading-04.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/heading-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/heading-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/heading-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/heading-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "1.")) ])
+, SoftBreak
+, Heading 1 []
+, Text "Not"
+, Space
+, Text "in"
+, Space
+, Text "heading"
+, SoftBreak
+, Text "="
+, Text "Nope"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  heading(body: {  }, 
+          level: 1, 
+          numbering: "1."), 
+  text(body: [Not in heading
+=Nope]), 
+  parbreak() }
diff --git a/test/out/meta/link-00.out b/test/out/meta/link-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-00.out
@@ -0,0 +1,141 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Url "https://example.com/"
+, ParBreak
+, Comment
+, Code
+    "test/typ/meta/link-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg (Literal (String "https://typst.org/"))
+       , BlockArg
+           [ Text "Some"
+           , Space
+           , Text "text"
+           , Space
+           , Text "text"
+           , Space
+           , Text "text"
+           ]
+       ])
+, ParBreak
+, Comment
+, Text "This"
+, Space
+, Text "link"
+, Space
+, Text "appears"
+, Space
+, Code
+    "test/typ/meta/link-00.typ"
+    ( line 9 , column 20 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg (Literal (String "https://google.com/"))
+       , BlockArg
+           [ Text "in"
+           , Space
+           , Text "the"
+           , Space
+           , Text "middle"
+           , Space
+           , Text "of"
+           ]
+       ])
+, Space
+, Text "a"
+, Space
+, Text "paragraph"
+, Text "."
+, ParBreak
+, Comment
+, Text "Contact"
+, Space
+, Code
+    "test/typ/meta/link-00.typ"
+    ( line 12 , column 10 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg (Literal (String "mailto:hi@typst.app")) ])
+, Space
+, Text "or"
+, SoftBreak
+, Text "call"
+, Space
+, Code
+    "test/typ/meta/link-00.typ"
+    ( line 13 , column 7 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg (Literal (String "tel:123")) ])
+, Space
+, Text "for"
+, Space
+, Text "more"
+, Space
+, Text "information"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  link(body: [https://example.com/], 
+       dest: "https://example.com/"), 
+  parbreak(), 
+  link(body: text(body: [Some text text text]), 
+       dest: "https://typst.org/"), 
+  parbreak(), 
+  text(body: [This link appears ]), 
+  link(body: text(body: [in the middle of]), 
+       dest: "https://google.com/"), 
+  text(body: [ a paragraph.]), 
+  parbreak(), 
+  text(body: [Contact ]), 
+  link(dest: "mailto:hi@typst.app"), 
+  text(body: [ or
+call ]), 
+  link(dest: "tel:123"), 
+  text(body: [ for more information.]), 
+  parbreak() }
diff --git a/test/out/meta/link-01.out b/test/out/meta/link-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-01.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/link-01.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "link")))
+       (Ident (Identifier "underline")))
+, SoftBreak
+, Url "https://a.b.?q=%10#."
+, Space
+, HardBreak
+, Text "Wahttp"
+, Text ":"
+, Comment
+, Text "Nohttps"
+, Text ":"
+, Text "/"
+, Text "/"
+, Text "link"
+, Space
+, HardBreak
+, Text "Nohttp"
+, Text ":"
+, Comment
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  underline(body: link(body: [https://a.b.?q=%10#.], 
+                       dest: "https://a.b.?q=%10#.")), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [Wahttp:]), 
+  text(body: [Nohttps://link ]), 
+  linebreak(), 
+  text(body: [Nohttp:]), 
+  parbreak() }
diff --git a/test/out/meta/link-02.out b/test/out/meta/link-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-02.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Url "https://[::1]:8080/"
+, Space
+, HardBreak
+, Url "https://example.com/(paren)"
+, Space
+, HardBreak
+, Url "https://example.com/#(((nested)))"
+, Space
+, HardBreak
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  link(body: [https://[::1]:8080/], 
+       dest: "https://[::1]:8080/"), 
+  text(body: [ ]), 
+  linebreak(), 
+  link(body: [https://example.com/(paren)], 
+       dest: "https://example.com/(paren)"), 
+  text(body: [ ]), 
+  linebreak(), 
+  link(body: [https://example.com/#(((nested)))], 
+       dest: "https://example.com/#(((nested)))"), 
+  text(body: [ ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/meta/link-03.out b/test/out/meta/link-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-03.out
@@ -0,0 +1,63 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/link-03.typ"
+    ( line 3 , column 2 )
+    (Block (Content [ Url "https://example.com/" ]))
+, Space
+, HardBreak
+, Url "https://example.com/"
+, Text ")"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  link(body: [https://example.com/], 
+       dest: "https://example.com/"), 
+  text(body: [ ]), 
+  linebreak(), 
+  link(body: [https://example.com/], 
+       dest: "https://example.com/"), 
+  text(body: [)]), 
+  parbreak() }
diff --git a/test/out/meta/link-04.out b/test/out/meta/link-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/link-05.out b/test/out/meta/link-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-05.out
@@ -0,0 +1,104 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/link-05.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "link")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (FuncCall
+             (Ident (Identifier "underline"))
+             [ NormalArg
+                 (FuncCall
+                    (Ident (Identifier "text"))
+                    [ KeyValArg
+                        (Identifier "fill")
+                        (FuncCall
+                           (Ident (Identifier "rgb"))
+                           [ NormalArg (Literal (String "283663")) ])
+                    , NormalArg (Ident (Identifier "it"))
+                    ])
+             ])))
+, SoftBreak
+, Text "You"
+, Space
+, Text "could"
+, Space
+, Text "also"
+, Space
+, Text "make"
+, Space
+, Text "the"
+, SoftBreak
+, Code
+    "test/typ/meta/link-05.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg (Literal (String "https://html5zombo.com/"))
+       , BlockArg
+           [ Text "link"
+           , Space
+           , Text "look"
+           , Space
+           , Text "way"
+           , Space
+           , Text "more"
+           , Space
+           , Text "typical"
+           , Text "."
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+You could also make the
+]), 
+  underline(body: text(body: link(body: text(body: [link look way more typical.]), 
+                                  dest: "https://html5zombo.com/"), 
+                       fill: rgb(15%,21%,38%,100%))), 
+  parbreak() }
diff --git a/test/out/meta/link-06.out b/test/out/meta/link-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-06.out
@@ -0,0 +1,103 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/link-06.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/link-06.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "mylink")))
+       (FuncCall
+          (Ident (Identifier "link"))
+          [ NormalArg (Literal (String "https://typst.org/"))
+          , BlockArg [ Text "LINK" ]
+          ]))
+, SoftBreak
+, Text "My"
+, Space
+, Text "cool"
+, Space
+, Code
+    "test/typ/meta/link-06.typ"
+    ( line 5 , column 10 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "move"))
+              [ KeyValArg (Identifier "dx") (Literal (Numeric 0.7 Cm))
+              , KeyValArg (Identifier "dy") (Literal (Numeric 0.7 Cm))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rotate"))
+                     [ NormalArg (Literal (Numeric 10.0 Deg))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "scale"))
+                            [ NormalArg (Literal (Numeric 200.0 Percent))
+                            , NormalArg (Ident (Identifier "mylink"))
+                            ])
+                     ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+My cool ]), 
+  box(body: move(body: rotate(angle: 10.0deg, 
+                              body: scale(body: link(body: text(body: [LINK]), 
+                                                     dest: "https://typst.org/"), 
+                                          factor: 200%)), 
+                 dx: 0.7cm, 
+                 dy: 0.7cm)), 
+  parbreak() }
diff --git a/test/out/meta/link-07.out b/test/out/meta/link-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-07.out
@@ -0,0 +1,94 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/link-07.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg (Literal (String "https://example.com/"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "block"))
+              [ BlockArg
+                  [ SoftBreak
+                  , Text "My"
+                  , Space
+                  , Text "cool"
+                  , Space
+                  , Text "rhino"
+                  , SoftBreak
+                  , Code
+                      "test/typ/meta/link-07.typ"
+                      ( line 5 , column 4 )
+                      (FuncCall
+                         (Ident (Identifier "box"))
+                         [ NormalArg
+                             (FuncCall
+                                (Ident (Identifier "move"))
+                                [ KeyValArg (Identifier "dx") (Literal (Numeric 10.0 Pt))
+                                , NormalArg
+                                    (FuncCall
+                                       (Ident (Identifier "image"))
+                                       [ NormalArg (Literal (String "test/assets/files/rhino.png"))
+                                       , KeyValArg (Identifier "width") (Literal (Numeric 1.0 Cm))
+                                       ])
+                                ])
+                         ])
+                  , ParBreak
+                  ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  link(body: block(body: { text(body: [
+My cool rhino
+]), 
+                           box(body: move(body: image(path: "test/assets/files/rhino.png", 
+                                                      width: 1.0cm), 
+                                          dx: 10.0pt)), 
+                           parbreak() }), 
+       dest: "https://example.com/"), 
+  parbreak() }
diff --git a/test/out/meta/link-08.out b/test/out/meta/link-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-08.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/meta/link-08.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg
+           (Dict
+              [ ( Identifier "page" , Literal (Int 1) )
+              , ( Identifier "x" , Literal (Numeric 10.0 Pt) )
+              , ( Identifier "y" , Literal (Numeric 20.0 Pt) )
+              ])
+       , BlockArg
+           [ Text "Back"
+           , Space
+           , Text "to"
+           , Space
+           , Text "the"
+           , Space
+           , Text "start"
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  link(body: text(body: [Back to the start]), 
+       dest: (page: 1,
+              x: 10.0pt,
+              y: 20.0pt)), 
+  parbreak() }
diff --git a/test/out/meta/link-09.out b/test/out/meta/link-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-09.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/link-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/link-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/link-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Text"
+, Space
+, Code
+    "test/typ/meta/link-09.typ" ( line 3 , column 6 ) (Label "hey")
+, SoftBreak
+, Code
+    "test/typ/meta/link-09.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "link"))
+       [ NormalArg (Label "hey")
+       , BlockArg
+           [ Text "Go" , Space , Text "to" , Space , Text "text" , Text "." ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Text ]), 
+  <hey>, 
+  text(body: [
+]), 
+  link(body: text(body: [Go to text.]), 
+       dest: ), 
+  parbreak() }
diff --git a/test/out/meta/link-10.out b/test/out/meta/link-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/link-11.out b/test/out/meta/link-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/link-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/numbering-00.out b/test/out/meta/numbering-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/numbering-00.out
@@ -0,0 +1,163 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/numbering-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/numbering-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/numbering-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/numbering-00.typ"
+    ( line 2 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 9)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "*"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block (Content [ Space , Text "and" , Space ])
+             , FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "I.a"))
+                 , NormalArg (Ident (Identifier "i"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-00.typ"
+                        ( line 6 , column 10 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  numbering(numbering: "*", 
+            numbers: (0)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (0, 0)), 
+  text(body: [ for ]), 
+  text(body: [0]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (1)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (1, 1)), 
+  text(body: [ for ]), 
+  text(body: [1]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (2)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (2, 2)), 
+  text(body: [ for ]), 
+  text(body: [2]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (3)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (3, 3)), 
+  text(body: [ for ]), 
+  text(body: [3]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (4)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (4, 4)), 
+  text(body: [ for ]), 
+  text(body: [4]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (5)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (5, 5)), 
+  text(body: [ for ]), 
+  text(body: [5]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (6)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (6, 6)), 
+  text(body: [ for ]), 
+  text(body: [6]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (7)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (7, 7)), 
+  text(body: [ for ]), 
+  text(body: [7]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "*", 
+            numbers: (8)), 
+  text(body: [ and ]), 
+  numbering(numbering: "I.a", 
+            numbers: (8, 8)), 
+  text(body: [ for ]), 
+  text(body: [8]), 
+  text(body: [ ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/meta/numbering-01.out b/test/out/meta/numbering-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/numbering-01.out
@@ -0,0 +1,217 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/numbering-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/numbering-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/numbering-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/numbering-01.typ"
+    ( line 2 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 4)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "A"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-01.typ"
+                        ( line 4 , column 10 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, SoftBreak
+, Ellipsis
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/numbering-01.typ"
+    ( line 7 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 26)) , NormalArg (Literal (Int 30)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "A"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-01.typ"
+                        ( line 9 , column 10 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, SoftBreak
+, Ellipsis
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/numbering-01.typ"
+    ( line 12 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 702)) , NormalArg (Literal (Int 706)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "A"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-01.typ"
+                        ( line 14 , column 10 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  numbering(numbering: "A", 
+            numbers: (0)), 
+  text(body: [ for ]), 
+  text(body: [0]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (1)), 
+  text(body: [ for ]), 
+  text(body: [1]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (2)), 
+  text(body: [ for ]), 
+  text(body: [2]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (3)), 
+  text(body: [ for ]), 
+  text(body: [3]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+… ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (26)), 
+  text(body: [ for ]), 
+  text(body: [26]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (27)), 
+  text(body: [ for ]), 
+  text(body: [27]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (28)), 
+  text(body: [ for ]), 
+  text(body: [28]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (29)), 
+  text(body: [ for ]), 
+  text(body: [29]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+… ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (702)), 
+  text(body: [ for ]), 
+  text(body: [702]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (703)), 
+  text(body: [ for ]), 
+  text(body: [703]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (704)), 
+  text(body: [ for ]), 
+  text(body: [704]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "A", 
+            numbers: (705)), 
+  text(body: [ for ]), 
+  text(body: [705]), 
+  text(body: [ ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/meta/numbering-02.out b/test/out/meta/numbering-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/numbering-02.out
@@ -0,0 +1,129 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/numbering-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/numbering-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/numbering-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/numbering-02.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "he")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/numbering-02.typ"
+    ( line 3 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 9))
+          , NormalArg (Literal (Int 21))
+          , KeyValArg (Identifier "step") (Literal (Int 2))
+          ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\1488."))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Space
+                    , Text "\1506\1489\1493\1512"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-02.typ"
+                        ( line 5 , column 11 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], lang: "he"), 
+  numbering(numbering: "א.", 
+            numbers: (9)), 
+  text(body: [ עבור ], 
+       lang: "he"), 
+  text(body: [9], lang: "he"), 
+  text(body: [ ], lang: "he"), 
+  linebreak(), 
+  numbering(numbering: "א.", 
+            numbers: (11)), 
+  text(body: [ עבור ], 
+       lang: "he"), 
+  text(body: [11], lang: "he"), 
+  text(body: [ ], lang: "he"), 
+  linebreak(), 
+  numbering(numbering: "א.", 
+            numbers: (13)), 
+  text(body: [ עבור ], 
+       lang: "he"), 
+  text(body: [13], lang: "he"), 
+  text(body: [ ], lang: "he"), 
+  linebreak(), 
+  numbering(numbering: "א.", 
+            numbers: (15)), 
+  text(body: [ עבור ], 
+       lang: "he"), 
+  text(body: [15], lang: "he"), 
+  text(body: [ ], lang: "he"), 
+  linebreak(), 
+  numbering(numbering: "א.", 
+            numbers: (17)), 
+  text(body: [ עבור ], 
+       lang: "he"), 
+  text(body: [17], lang: "he"), 
+  text(body: [ ], lang: "he"), 
+  linebreak(), 
+  numbering(numbering: "א.", 
+            numbers: (19)), 
+  text(body: [ עבור ], 
+       lang: "he"), 
+  text(body: [19], lang: "he"), 
+  text(body: [ ], lang: "he"), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/meta/numbering-03.out b/test/out/meta/numbering-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/numbering-03.out
@@ -0,0 +1,159 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/numbering-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/numbering-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/numbering-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/numbering-03.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "zh")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/numbering-03.typ"
+    ( line 3 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 9))
+          , NormalArg (Literal (Int 21))
+          , KeyValArg (Identifier "step") (Literal (Int 2))
+          ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\19968"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block (Content [ Space , Text "and" , Space ])
+             , FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\22777"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-03.typ"
+                        ( line 7 , column 10 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], lang: "zh"), 
+  numbering(numbering: "一", 
+            numbers: (9)), 
+  text(body: [ and ], 
+       lang: "zh"), 
+  numbering(numbering: "壹", 
+            numbers: (9)), 
+  text(body: [ for ], 
+       lang: "zh"), 
+  text(body: [9], lang: "zh"), 
+  text(body: [ ], lang: "zh"), 
+  linebreak(), 
+  numbering(numbering: "一", 
+            numbers: (11)), 
+  text(body: [ and ], 
+       lang: "zh"), 
+  numbering(numbering: "壹", 
+            numbers: (11)), 
+  text(body: [ for ], 
+       lang: "zh"), 
+  text(body: [11], lang: "zh"), 
+  text(body: [ ], lang: "zh"), 
+  linebreak(), 
+  numbering(numbering: "一", 
+            numbers: (13)), 
+  text(body: [ and ], 
+       lang: "zh"), 
+  numbering(numbering: "壹", 
+            numbers: (13)), 
+  text(body: [ for ], 
+       lang: "zh"), 
+  text(body: [13], lang: "zh"), 
+  text(body: [ ], lang: "zh"), 
+  linebreak(), 
+  numbering(numbering: "一", 
+            numbers: (15)), 
+  text(body: [ and ], 
+       lang: "zh"), 
+  numbering(numbering: "壹", 
+            numbers: (15)), 
+  text(body: [ for ], 
+       lang: "zh"), 
+  text(body: [15], lang: "zh"), 
+  text(body: [ ], lang: "zh"), 
+  linebreak(), 
+  numbering(numbering: "一", 
+            numbers: (17)), 
+  text(body: [ and ], 
+       lang: "zh"), 
+  numbering(numbering: "壹", 
+            numbers: (17)), 
+  text(body: [ for ], 
+       lang: "zh"), 
+  text(body: [17], lang: "zh"), 
+  text(body: [ ], lang: "zh"), 
+  linebreak(), 
+  numbering(numbering: "一", 
+            numbers: (19)), 
+  text(body: [ and ], 
+       lang: "zh"), 
+  numbering(numbering: "壹", 
+            numbers: (19)), 
+  text(body: [ for ], 
+       lang: "zh"), 
+  text(body: [19], lang: "zh"), 
+  text(body: [ ], lang: "zh"), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/meta/numbering-04.out b/test/out/meta/numbering-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/numbering-04.out
@@ -0,0 +1,257 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/numbering-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/numbering-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/numbering-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/numbering-04.typ"
+    ( line 2 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 0)) , NormalArg (Literal (Int 4)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\12452"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block (Content [ Space , Text "(" , Text "or" , Space ])
+             , FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\12356"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Text ")"
+                    , Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-04.typ"
+                        ( line 6 , column 11 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, SoftBreak
+, Ellipsis
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/numbering-04.typ"
+    ( line 9 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 47)) , NormalArg (Literal (Int 51)) ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\12452"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block (Content [ Space , Text "(" , Text "or" , Space ])
+             , FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\12356"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Text ")"
+                    , Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-04.typ"
+                        ( line 13 , column 11 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, SoftBreak
+, Ellipsis
+, Space
+, HardBreak
+, Code
+    "test/typ/meta/numbering-04.typ"
+    ( line 16 , column 2 )
+    (For
+       (BasicBind (Just (Identifier "i")))
+       (FuncCall
+          (Ident (Identifier "range"))
+          [ NormalArg (Literal (Int 2256))
+          , NormalArg (Literal (Int 2260))
+          ])
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (Ident (Identifier "numbering"))
+                 [ NormalArg (Literal (String "\12452"))
+                 , NormalArg (Ident (Identifier "i"))
+                 ]
+             , Block
+                 (Content
+                    [ Space
+                    , Text "for"
+                    , Space
+                    , Code
+                        "test/typ/meta/numbering-04.typ"
+                        ( line 18 , column 10 )
+                        (Ident (Identifier "i"))
+                    , Space
+                    , HardBreak
+                    ])
+             ])))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  numbering(numbering: "イ", 
+            numbers: (0)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (0)), 
+  text(body: [) for ]), 
+  text(body: [0]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (1)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (1)), 
+  text(body: [) for ]), 
+  text(body: [1]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (2)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (2)), 
+  text(body: [) for ]), 
+  text(body: [2]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (3)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (3)), 
+  text(body: [) for ]), 
+  text(body: [3]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+… ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (47)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (47)), 
+  text(body: [) for ]), 
+  text(body: [47]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (48)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (48)), 
+  text(body: [) for ]), 
+  text(body: [48]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (49)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (49)), 
+  text(body: [) for ]), 
+  text(body: [49]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (50)), 
+  text(body: [ (or ]), 
+  numbering(numbering: "い", 
+            numbers: (50)), 
+  text(body: [) for ]), 
+  text(body: [50]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [
+… ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (2256)), 
+  text(body: [ for ]), 
+  text(body: [2256]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (2257)), 
+  text(body: [ for ]), 
+  text(body: [2257]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (2258)), 
+  text(body: [ for ]), 
+  text(body: [2258]), 
+  text(body: [ ]), 
+  linebreak(), 
+  numbering(numbering: "イ", 
+            numbers: (2259)), 
+  text(body: [ for ]), 
+  text(body: [2259]), 
+  text(body: [ ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/meta/numbering-05.out b/test/out/meta/numbering-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/numbering-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/outline-00.out b/test/out/meta/outline-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/outline-00.out
@@ -0,0 +1,228 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/outline-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/outline-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/outline-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ NormalArg (Literal (String "a7"))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "numbering") (Literal (String "1"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "(1/a)")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 4 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "heading")))
+             [ KeyValArg (Identifier "level") (Literal (Int 1)) ]))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Literal (Numeric 12.0 Pt)) ]))
+, SoftBreak
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 5 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "heading")))
+             [ KeyValArg (Identifier "level") (Literal (Int 2)) ]))
+       (Set
+          (Ident (Identifier "text"))
+          [ NormalArg (Literal (Numeric 10.0 Pt)) ]))
+, ParBreak
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall (Ident (Identifier "outline")) [])
+, ParBreak
+, Heading 1 [ Text "Einleitung" ]
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 12)) ])
+, ParBreak
+, Heading 1 [ Text "Analyse" ]
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 10)) ])
+, ParBreak
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 15 , column 2 )
+    (Block
+       (Content
+          [ SoftBreak
+          , Code
+              "test/typ/meta/outline-00.typ"
+              ( line 16 , column 4 )
+              (Set
+                 (Ident (Identifier "heading"))
+                 [ KeyValArg (Identifier "outlined") (Literal (Boolean False)) ])
+          , SoftBreak
+          , Heading 2 [ Text "Methodik" ]
+          , Code
+              "test/typ/meta/outline-00.typ"
+              ( line 18 , column 4 )
+              (FuncCall
+                 (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 6)) ])
+          , ParBreak
+          ]))
+, ParBreak
+, Heading 2 [ Text "Verarbeitung" ]
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 4)) ])
+, ParBreak
+, Heading 2 [ Text "Programmierung" ]
+, RawBlock "rust" "fn main() {\n  panic!(\"in the disco\");\n}\n"
+, ParBreak
+, Heading 4 [ Text "Deep" , Space , Text "Stuff" ]
+, Text "Ok"
+, Space
+, Ellipsis
+, ParBreak
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 34 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "(I)")) ])
+, ParBreak
+, Heading
+    1
+    [ Code
+        "test/typ/meta/outline-00.typ"
+        ( line 36 , column 4 )
+        (FuncCall
+           (Ident (Identifier "text"))
+           [ NormalArg (Ident (Identifier "blue"))
+           , BlockArg [ Text "Zusammen" ]
+           ])
+    , Text "fassung"
+    ]
+, Code
+    "test/typ/meta/outline-00.typ"
+    ( line 37 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 10)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  outline(), 
+  parbreak(), 
+  heading(body: text(body: [Einleitung]), 
+          level: 1, 
+          numbering: "(1/a)"), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor]), 
+  parbreak(), 
+  heading(body: text(body: [Analyse]), 
+          level: 1, 
+          numbering: "(1/a)"), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  heading(body: text(body: [Methodik]), 
+          level: 2, 
+          numbering: "(1/a)", 
+          outlined: false), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur]), 
+  parbreak(), 
+  parbreak(), 
+  heading(body: text(body: [Verarbeitung]), 
+          level: 2, 
+          numbering: "(1/a)", 
+          outlined: false), 
+  text(body: [Lorem ipsum dolor sit]), 
+  parbreak(), 
+  heading(body: text(body: [Programmierung]), 
+          level: 2, 
+          numbering: "(1/a)", 
+          outlined: false), 
+  raw(block: true, 
+      lang: "rust", 
+      text: "fn main() {\n  panic!(\"in the disco\");\n}\n"), 
+  parbreak(), 
+  heading(body: text(body: [Deep Stuff]), 
+          level: 4, 
+          numbering: "(1/a)", 
+          outlined: false), 
+  text(body: [Ok …]), 
+  parbreak(), 
+  parbreak(), 
+  heading(body: { text(body: text(body: [Zusammen]), 
+                       color: rgb(0%,45%,85%,100%)), 
+                  text(body: [fassung]) }, 
+          level: 1, 
+          numbering: "(I)", 
+          outlined: false), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do]), 
+  parbreak() }
diff --git a/test/out/meta/query-before-after-00.out b/test/out/meta/query-before-after-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/query-before-after-00.out
@@ -0,0 +1,181 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/query-before-after-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/query-before-after-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/query-before-after-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/query-before-after-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "paper") (Literal (String "a7"))
+       , KeyValArg (Identifier "numbering") (Literal (String "1 / 1"))
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "bottom" , Literal (Numeric 1.0 Cm) )
+              , ( Identifier "rest" , Literal (Numeric 0.5 Cm) )
+              ])
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-before-after-00.typ"
+    ( line 8 , column 2 )
+    (Show
+       (Just
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "where")) (Ident (Identifier "heading")))
+             [ KeyValArg (Identifier "level") (Literal (Int 1))
+             , KeyValArg (Identifier "outlined") (Literal (Boolean True))
+             ]))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (Content
+                [ SoftBreak
+                , Code
+                    "test/typ/meta/query-before-after-00.typ"
+                    ( line 9 , column 4 )
+                    (Ident (Identifier "it"))
+                , ParBreak
+                , Code
+                    "test/typ/meta/query-before-after-00.typ"
+                    ( line 11 , column 4 )
+                    (Set
+                       (Ident (Identifier "text"))
+                       [ KeyValArg (Identifier "size") (Literal (Numeric 12.0 Pt))
+                       , KeyValArg (Identifier "weight") (Literal (String "regular"))
+                       ])
+                , SoftBreak
+                , Code
+                    "test/typ/meta/query-before-after-00.typ"
+                    ( line 12 , column 4 )
+                    (FuncCall
+                       (Ident (Identifier "outline"))
+                       [ KeyValArg
+                           (Identifier "title") (Literal (String "Chapter outline"))
+                       , KeyValArg (Identifier "indent") (Literal (Boolean True))
+                       , KeyValArg
+                           (Identifier "target")
+                           (FuncCall
+                              (FieldAccess
+                                 (Ident (Identifier "before"))
+                                 (FuncCall
+                                    (FieldAccess
+                                       (Ident (Identifier "after"))
+                                       (FuncCall
+                                          (FieldAccess
+                                             (Ident (Identifier "or"))
+                                             (FuncCall
+                                                (FieldAccess
+                                                   (Ident (Identifier "where"))
+                                                   (Ident (Identifier "heading")))
+                                                [ KeyValArg (Identifier "level") (Literal (Int 1))
+                                                ]))
+                                          [ NormalArg
+                                              (FuncCall
+                                                 (FieldAccess
+                                                    (Ident (Identifier "where"))
+                                                    (Ident (Identifier "heading")))
+                                                 [ KeyValArg (Identifier "level") (Literal (Int 2))
+                                                 ])
+                                          ]))
+                                    [ NormalArg
+                                        (FuncCall
+                                           (FieldAccess
+                                              (Ident (Identifier "location"))
+                                              (Ident (Identifier "it")))
+                                           [])
+                                    , KeyValArg (Identifier "inclusive") (Literal (Boolean True))
+                                    ]))
+                              [ NormalArg
+                                  (FuncCall
+                                     (FieldAccess
+                                        (Ident (Identifier "after"))
+                                        (FuncCall
+                                           (FieldAccess
+                                              (Ident (Identifier "where"))
+                                              (Ident (Identifier "heading")))
+                                           [ KeyValArg (Identifier "level") (Literal (Int 1))
+                                           , KeyValArg
+                                               (Identifier "outlined") (Literal (Boolean True))
+                                           ]))
+                                     [ NormalArg
+                                         (FuncCall
+                                            (FieldAccess
+                                               (Ident (Identifier "location"))
+                                               (Ident (Identifier "it")))
+                                            [])
+                                     , KeyValArg (Identifier "inclusive") (Literal (Boolean False))
+                                     ])
+                              , KeyValArg (Identifier "inclusive") (Literal (Boolean False))
+                              ])
+                       ])
+                , ParBreak
+                ]))))
+, ParBreak
+, Code
+    "test/typ/meta/query-before-after-00.typ"
+    ( line 28 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "outlined") (Literal (Boolean True))
+       , KeyValArg (Identifier "numbering") (Literal (String "1."))
+       ])
+, ParBreak
+, Heading 1 [ Text "Section" , Space , Text "1" ]
+, Heading 2 [ Text "Subsection" , Space , Text "1" ]
+, Heading 2 [ Text "Subsection" , Space , Text "2" ]
+, Heading 3 [ Text "Subsubsection" , Space , Text "1" ]
+, Heading 3 [ Text "Subsubsection" , Space , Text "2" ]
+, Heading 2 [ Text "Subsection" , Space , Text "3" ]
+, Heading 1 [ Text "Section" , Space , Text "2" ]
+, Heading 2 [ Text "Subsection" , Space , Text "1" ]
+, Heading 2 [ Text "Subsection" , Space , Text "2" ]
+, Heading 1 [ Text "Section" , Space , Text "3" ]
+, Heading 2 [ Text "Subsection" , Space , Text "1" ]
+, Heading 2 [ Text "Subsection" , Space , Text "2" ]
+, Heading 3 [ Text "Subsubsection" , Space , Text "1" ]
+, Heading 3 [ Text "Subsubsection" , Space , Text "2" ]
+, Heading 3 [ Text "Subsubsection" , Space , Text "3" ]
+, Heading 2 [ Text "Subsection" , Space , Text "3" ]
+]
+"test/typ/meta/query-before-after-00.typ" (line 12, column 4):
+Method "location" is not yet implemented or FieldAccess requires a dictionary
diff --git a/test/out/meta/query-before-after-01.out b/test/out/meta/query-before-after-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/query-before-after-01.out
@@ -0,0 +1,187 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/query-before-after-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/query-before-after-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "paper") (Literal (String "a7"))
+       , KeyValArg (Identifier "numbering") (Literal (String "1 / 1"))
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "bottom" , Literal (Numeric 1.0 Cm) )
+              , ( Identifier "rest" , Literal (Numeric 0.5 Cm) )
+              ])
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 9 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "outlined") (Literal (Boolean True))
+       , KeyValArg (Identifier "numbering") (Literal (String "1."))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "locate"))
+       [ NormalArg
+           (FuncExpr
+              [ NormalParam (Identifier "loc") ]
+              (Block
+                 (Content
+                    [ SoftBreak
+                    , Text "Non"
+                    , Text "-"
+                    , Text "outlined"
+                    , Space
+                    , Text "elements"
+                    , Text ":"
+                    , SoftBreak
+                    , Code
+                        "test/typ/meta/query-before-after-01.typ"
+                        ( line 14 , column 4 )
+                        (FuncCall
+                           (FieldAccess
+                              (Ident (Identifier "join"))
+                              (FuncCall
+                                 (FieldAccess
+                                    (Ident (Identifier "map"))
+                                    (FuncCall
+                                       (Ident (Identifier "query"))
+                                       [ NormalArg
+                                           (FuncCall
+                                              (FieldAccess
+                                                 (Ident (Identifier "and"))
+                                                 (FuncCall
+                                                    (Ident (Identifier "selector"))
+                                                    [ NormalArg (Ident (Identifier "heading")) ]))
+                                              [ NormalArg
+                                                  (FuncCall
+                                                     (FieldAccess
+                                                        (Ident (Identifier "where"))
+                                                        (Ident (Identifier "heading")))
+                                                     [ KeyValArg
+                                                         (Identifier "outlined")
+                                                         (Literal (Boolean False))
+                                                     ])
+                                              ])
+                                       , NormalArg (Ident (Identifier "loc"))
+                                       ]))
+                                 [ NormalArg
+                                     (FuncExpr
+                                        [ NormalParam (Identifier "it") ]
+                                        (FieldAccess
+                                           (Ident (Identifier "body")) (Ident (Identifier "it"))))
+                                 ]))
+                           [ NormalArg (Literal (String ", ")) ])
+                    , ParBreak
+                    ])))
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "heading"))
+       [ NormalArg (Literal (String "A"))
+       , KeyValArg (Identifier "outlined") (Literal (Boolean False))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "heading"))
+       [ NormalArg (Literal (String "B"))
+       , KeyValArg (Identifier "outlined") (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 20 , column 2 )
+    (FuncCall
+       (Ident (Identifier "heading"))
+       [ NormalArg (Literal (String "C"))
+       , KeyValArg (Identifier "outlined") (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/meta/query-before-after-01.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "heading"))
+       [ NormalArg (Literal (String "D"))
+       , KeyValArg (Identifier "outlined") (Literal (Boolean False))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ parbreak(), 
+  parbreak(), 
+  parbreak(), 
+  locate(func: ), 
+  parbreak(), 
+  heading(body: [A], 
+          numbering: "1.", 
+          outlined: false), 
+  text(body: [
+]), 
+  heading(body: [B], 
+          numbering: "1.", 
+          outlined: true), 
+  text(body: [
+]), 
+  heading(body: [C], 
+          numbering: "1.", 
+          outlined: true), 
+  text(body: [
+]), 
+  heading(body: [D], 
+          numbering: "1.", 
+          outlined: false), 
+  parbreak() }
diff --git a/test/out/meta/query-figure-00.out b/test/out/meta/query-figure-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/query-figure-00.out
@@ -0,0 +1,259 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/query-figure-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/query-figure-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "paper") (Literal (String "a7"))
+       , KeyValArg (Identifier "numbering") (Literal (String "1 / 1"))
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "bottom" , Literal (Numeric 1.0 Cm) )
+              , ( Identifier "rest" , Literal (Numeric 0.5 Cm) )
+              ])
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 8 , column 2 )
+    (Set
+       (Ident (Identifier "figure"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "I")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 9 , column 2 )
+    (Show
+       (Just (Ident (Identifier "figure")))
+       (Set
+          (Ident (Identifier "image"))
+          [ KeyValArg (Identifier "width") (Literal (Numeric 80.0 Percent))
+          ]))
+, ParBreak
+, Heading
+    1 [ Text "List" , Space , Text "of" , Space , Text "Figures" ]
+, Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "locate"))
+       [ NormalArg
+           (FuncExpr
+              [ NormalParam (Identifier "it") ]
+              (Block
+                 (CodeBlock
+                    [ Let
+                        (BasicBind (Just (Identifier "elements")))
+                        (FuncCall
+                           (Ident (Identifier "query"))
+                           [ NormalArg
+                               (FuncCall
+                                  (FieldAccess
+                                     (Ident (Identifier "after"))
+                                     (FuncCall
+                                        (Ident (Identifier "selector"))
+                                        [ NormalArg (Ident (Identifier "figure")) ]))
+                                  [ NormalArg (Ident (Identifier "it")) ])
+                           , NormalArg (Ident (Identifier "it"))
+                           ])
+                    , For
+                        (BasicBind (Just (Identifier "it")))
+                        (Ident (Identifier "elements"))
+                        (Block
+                           (Content
+                              [ SoftBreak
+                              , Text "Figure"
+                              , SoftBreak
+                              , Code
+                                  "test/typ/meta/query-figure-00.typ"
+                                  ( line 16 , column 6 )
+                                  (FuncCall
+                                     (Ident (Identifier "numbering"))
+                                     [ NormalArg
+                                         (FieldAccess
+                                            (Ident (Identifier "numbering"))
+                                            (Ident (Identifier "it")))
+                                     , SpreadArg
+                                         (FuncCall
+                                            (FieldAccess
+                                               (Ident (Identifier "at"))
+                                               (FuncCall
+                                                  (Ident (Identifier "counter"))
+                                                  [ NormalArg (Ident (Identifier "figure")) ]))
+                                            [ NormalArg
+                                                (FuncCall
+                                                   (FieldAccess
+                                                      (Ident (Identifier "location"))
+                                                      (Ident (Identifier "it")))
+                                                   [])
+                                            ])
+                                     ])
+                              , Text ":"
+                              , SoftBreak
+                              , Code
+                                  "test/typ/meta/query-figure-00.typ"
+                                  ( line 18 , column 6 )
+                                  (FieldAccess
+                                     (Ident (Identifier "caption")) (Ident (Identifier "it")))
+                              , SoftBreak
+                              , Code
+                                  "test/typ/meta/query-figure-00.typ"
+                                  ( line 19 , column 6 )
+                                  (FuncCall
+                                     (Ident (Identifier "box"))
+                                     [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Fr))
+                                     , NormalArg
+                                         (FuncCall
+                                            (Ident (Identifier "repeat")) [ BlockArg [ Text "." ] ])
+                                     ])
+                              , SoftBreak
+                              , Code
+                                  "test/typ/meta/query-figure-00.typ"
+                                  ( line 20 , column 6 )
+                                  (FuncCall
+                                     (FieldAccess
+                                        (Ident (Identifier "first"))
+                                        (FuncCall
+                                           (FieldAccess
+                                              (Ident (Identifier "at"))
+                                              (FuncCall
+                                                 (Ident (Identifier "counter"))
+                                                 [ NormalArg (Ident (Identifier "page")) ]))
+                                           [ NormalArg
+                                               (FuncCall
+                                                  (FieldAccess
+                                                     (Ident (Identifier "location"))
+                                                     (Ident (Identifier "it")))
+                                                  [])
+                                           ]))
+                                     [])
+                              , Space
+                              , HardBreak
+                              ]))
+                    ])))
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 24 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/glacier.jpg")) ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block (Content [ Text "Glacier" , Space , Text "melting" ]))
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 29 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ BlockArg
+                  [ Text "Just"
+                  , Space
+                  , Text "some"
+                  , Space
+                  , Text "stand"
+                  , Text "-"
+                  , Text "in"
+                  , Space
+                  , Text "text"
+                  ]
+              ])
+       , KeyValArg (Identifier "kind") (Ident (Identifier "image"))
+       , KeyValArg (Identifier "supplement") (Literal (String "Figure"))
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "Stand" , Text "-" , Text "in" , Space , Text "text" ]))
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-figure-00.typ"
+    ( line 36 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg")) ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block (Content [ Text "Tiger" , Space , Text "world" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [List of Figures]), 
+          level: 1), 
+  locate(func: ), 
+  parbreak(), 
+  figure(body: image(path: "test/assets/files/glacier.jpg"), 
+         caption: text(body: [Glacier melting]), 
+         numbering: "I"), 
+  parbreak(), 
+  figure(body: rect(body: text(body: [Just some stand-in text])), 
+         caption: text(body: [Stand-in text]), 
+         kind: , 
+         numbering: "I", 
+         supplement: "Figure"), 
+  parbreak(), 
+  figure(body: image(path: "test/assets/files/tiger.jpg"), 
+         caption: text(body: [Tiger world]), 
+         numbering: "I"), 
+  parbreak() }
diff --git a/test/out/meta/query-header-00.out b/test/out/meta/query-header-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/query-header-00.out
@@ -0,0 +1,192 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/query-header-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/query-header-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/query-header-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/query-header-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "paper") (Literal (String "a7"))
+       , KeyValArg
+           (Identifier "margin")
+           (Dict
+              [ ( Identifier "y" , Literal (Numeric 1.0 Cm) )
+              , ( Identifier "x" , Literal (Numeric 0.5 Cm) )
+              ])
+       , KeyValArg
+           (Identifier "header")
+           (Block
+              (CodeBlock
+                 [ FuncCall
+                     (Ident (Identifier "smallcaps"))
+                     [ BlockArg [ Text "Typst" , Space , Text "Academy" ] ]
+                 , FuncCall
+                     (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 1.0 Fr)) ]
+                 , FuncCall
+                     (Ident (Identifier "locate"))
+                     [ NormalArg
+                         (FuncExpr
+                            [ NormalParam (Identifier "it") ]
+                            (Block
+                               (CodeBlock
+                                  [ Let
+                                      (BasicBind (Just (Identifier "after")))
+                                      (FuncCall
+                                         (Ident (Identifier "query"))
+                                         [ NormalArg
+                                             (FuncCall
+                                                (FieldAccess
+                                                   (Ident (Identifier "after"))
+                                                   (FuncCall
+                                                      (Ident (Identifier "selector"))
+                                                      [ NormalArg (Ident (Identifier "heading")) ]))
+                                                [ NormalArg (Ident (Identifier "it")) ])
+                                         , NormalArg (Ident (Identifier "it"))
+                                         ])
+                                  , Let
+                                      (BasicBind (Just (Identifier "before")))
+                                      (FuncCall
+                                         (Ident (Identifier "query"))
+                                         [ NormalArg
+                                             (FuncCall
+                                                (FieldAccess
+                                                   (Ident (Identifier "before"))
+                                                   (FuncCall
+                                                      (Ident (Identifier "selector"))
+                                                      [ NormalArg (Ident (Identifier "heading")) ]))
+                                                [ NormalArg (Ident (Identifier "it")) ])
+                                         , NormalArg (Ident (Identifier "it"))
+                                         ])
+                                  , Let
+                                      (BasicBind (Just (Identifier "elem")))
+                                      (If
+                                         [ ( Not
+                                               (Equals
+                                                  (FuncCall
+                                                     (FieldAccess
+                                                        (Ident (Identifier "len"))
+                                                        (Ident (Identifier "before")))
+                                                     [])
+                                                  (Literal (Int 0)))
+                                           , Block
+                                               (CodeBlock
+                                                  [ FuncCall
+                                                      (FieldAccess
+                                                         (Ident (Identifier "last"))
+                                                         (Ident (Identifier "before")))
+                                                      []
+                                                  ])
+                                           )
+                                         , ( Not
+                                               (Equals
+                                                  (FuncCall
+                                                     (FieldAccess
+                                                        (Ident (Identifier "len"))
+                                                        (Ident (Identifier "after")))
+                                                     [])
+                                                  (Literal (Int 0)))
+                                           , Block
+                                               (CodeBlock
+                                                  [ FuncCall
+                                                      (FieldAccess
+                                                         (Ident (Identifier "first"))
+                                                         (Ident (Identifier "after")))
+                                                      []
+                                                  ])
+                                           )
+                                         ])
+                                  , FuncCall
+                                      (Ident (Identifier "emph"))
+                                      [ NormalArg
+                                          (FieldAccess
+                                             (Ident (Identifier "body"))
+                                             (Ident (Identifier "elem")))
+                                      ]
+                                  ])))
+                     ]
+                 ]))
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/query-header-00.typ"
+    ( line 21 , column 2 )
+    (FuncCall (Ident (Identifier "outline")) [])
+, ParBreak
+, Heading 1 [ Text "Introduction" ]
+, Code
+    "test/typ/meta/query-header-00.typ"
+    ( line 24 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 35)) ])
+, ParBreak
+, Heading 1 [ Text "Background" ]
+, Code
+    "test/typ/meta/query-header-00.typ"
+    ( line 27 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 35)) ])
+, ParBreak
+, Heading 1 [ Text "Approach" ]
+, Code
+    "test/typ/meta/query-header-00.typ"
+    ( line 30 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 60)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  outline(), 
+  parbreak(), 
+  heading(body: text(body: [Introduction]), 
+          level: 1), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo]), 
+  parbreak(), 
+  heading(body: text(body: [Background]), 
+          level: 1), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo]), 
+  parbreak(), 
+  heading(body: text(body: [Approach]), 
+          level: 1), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in]), 
+  parbreak() }
diff --git a/test/out/meta/ref-00.out b/test/out/meta/ref-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/ref-00.out
@@ -0,0 +1,100 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/ref-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/ref-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/ref-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/ref-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg (Identifier "numbering") (Literal (String "1.")) ])
+, ParBreak
+, Heading 1 [ Text "Introduction" ]
+, Code
+    "test/typ/meta/ref-00.typ" ( line 4 , column 16 ) (Label "intro")
+, SoftBreak
+, Text "See"
+, Space
+, Ref "setup" (Literal Auto)
+, Text "."
+, ParBreak
+, Heading 2 [ Text "Setup" ]
+, Code
+    "test/typ/meta/ref-00.typ" ( line 7 , column 10 ) (Label "setup")
+, SoftBreak
+, Text "As"
+, Space
+, Text "seen"
+, Space
+, Text "in"
+, Space
+, Ref "intro" (Literal Auto)
+, Text ","
+, Space
+, Text "we"
+, Space
+, Text "proceed"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  heading(body: text(body: [Introduction]), 
+          level: 1, 
+          numbering: "1."), 
+  <intro>, 
+  text(body: [
+See ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [.]), 
+  parbreak(), 
+  heading(body: text(body: [Setup]), 
+          level: 2, 
+          numbering: "1."), 
+  <setup>, 
+  text(body: [
+As seen in ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [, we proceed.]), 
+  parbreak() }
diff --git a/test/out/meta/ref-01.out b/test/out/meta/ref-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/ref-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/ref-02.out b/test/out/meta/ref-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/ref-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/meta/ref-03.out b/test/out/meta/ref-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/ref-03.out
@@ -0,0 +1,169 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/ref-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/ref-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/ref-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/meta/ref-03.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "ref")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( And
+                          (Not
+                             (Equals
+                                (FieldAccess
+                                   (Ident (Identifier "element")) (Ident (Identifier "it")))
+                                (Literal None)))
+                          (Equals
+                             (FuncCall
+                                (FieldAccess
+                                   (Ident (Identifier "func"))
+                                   (FieldAccess
+                                      (Ident (Identifier "element")) (Ident (Identifier "it"))))
+                                [])
+                             (Ident (Identifier "figure")))
+                      , Block
+                          (CodeBlock
+                             [ Let
+                                 (BasicBind (Just (Identifier "element")))
+                                 (FieldAccess
+                                    (Ident (Identifier "element")) (Ident (Identifier "it")))
+                             , Literal (String "[")
+                             , FieldAccess
+                                 (Ident (Identifier "supplement")) (Ident (Identifier "element"))
+                             , Literal (String "-")
+                             , FuncCall
+                                 (Ident (Identifier "str"))
+                                 [ NormalArg
+                                     (FuncCall
+                                        (FieldAccess
+                                           (Ident (Identifier "at"))
+                                           (FuncCall
+                                              (FieldAccess
+                                                 (Ident (Identifier "at"))
+                                                 (FieldAccess
+                                                    (Ident (Identifier "counter"))
+                                                    (Ident (Identifier "element"))))
+                                              [ NormalArg
+                                                  (FuncCall
+                                                     (FieldAccess
+                                                        (Ident (Identifier "location"))
+                                                        (Ident (Identifier "element")))
+                                                     [])
+                                              ]))
+                                        [ NormalArg (Literal (Int 0)) ])
+                                 ]
+                             , Literal (String "]")
+                             ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block (CodeBlock [ Ident (Identifier "it") ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/meta/ref-03.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/cylinder.svg"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 3.0 Cm))
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block (Content [ Text "A" , Space , Text "sylinder" , Text "." ]))
+       , KeyValArg (Identifier "supplement") (Literal (String "Fig"))
+       ])
+, Space
+, Code
+    "test/typ/meta/ref-03.typ" ( line 21 , column 3 ) (Label "fig1")
+, ParBreak
+, Code
+    "test/typ/meta/ref-03.typ"
+    ( line 23 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 3.0 Cm))
+              ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block (Content [ Text "A" , Space , Text "tiger" , Text "." ]))
+       , KeyValArg (Identifier "supplement") (Literal (String "Figg"))
+       ])
+, Space
+, Code
+    "test/typ/meta/ref-03.typ" ( line 27 , column 3 ) (Label "fig2")
+, ParBreak
+, Code
+    "test/typ/meta/ref-03.typ"
+    ( line 29 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (Block
+              (Content [ Equation True [ Text "A" , Text "=" , Text "1" ] ]))
+       , KeyValArg (Identifier "kind") (Literal (String "equation"))
+       , KeyValArg (Identifier "supplement") (Literal (String "Equa"))
+       ])
+, Space
+, Code
+    "test/typ/meta/ref-03.typ" ( line 34 , column 3 ) (Label "eq1")
+, SoftBreak
+, Ref "fig1" (Literal Auto)
+, ParBreak
+, Ref "fig2" (Literal Auto)
+, ParBreak
+, Ref "eq1" (Literal Auto)
+, ParBreak
+]
+"test/typ/meta/ref-03.typ" (line 34, column 3):
+Content does not have a method "element" or FieldAccess requires a dictionary
diff --git a/test/out/meta/ref-04.out b/test/out/meta/ref-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/ref-04.out
@@ -0,0 +1,159 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/ref-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/ref-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/ref-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/ref-04.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "heading"))
+       [ KeyValArg
+           (Identifier "numbering")
+           (FuncExpr
+              [ SinkParam (Just (Identifier "nums")) ]
+              (Block
+                 (CodeBlock
+                    [ FuncCall
+                        (FieldAccess
+                           (Ident (Identifier "join"))
+                           (FuncCall
+                              (FieldAccess
+                                 (Ident (Identifier "map"))
+                                 (FuncCall
+                                    (FieldAccess
+                                       (Ident (Identifier "pos")) (Ident (Identifier "nums")))
+                                    []))
+                              [ NormalArg (Ident (Identifier "str")) ]))
+                        [ NormalArg (Literal (String ".")) ]
+                    ])))
+       , KeyValArg
+           (Identifier "supplement") (Block (Content [ Text "Chapt" ]))
+       ])
+, ParBreak
+, Code
+    "test/typ/meta/ref-04.typ"
+    ( line 6 , column 2 )
+    (Show
+       (Just (Ident (Identifier "ref")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( And
+                          (Not
+                             (Equals
+                                (FieldAccess
+                                   (Ident (Identifier "element")) (Ident (Identifier "it")))
+                                (Literal None)))
+                          (Equals
+                             (FuncCall
+                                (FieldAccess
+                                   (Ident (Identifier "func"))
+                                   (FieldAccess
+                                      (Ident (Identifier "element")) (Ident (Identifier "it"))))
+                                [])
+                             (Ident (Identifier "heading")))
+                      , Block
+                          (CodeBlock
+                             [ Let
+                                 (BasicBind (Just (Identifier "element")))
+                                 (FieldAccess
+                                    (Ident (Identifier "element")) (Ident (Identifier "it")))
+                             , Literal (String "[")
+                             , FuncCall
+                                 (Ident (Identifier "emph"))
+                                 [ NormalArg
+                                     (FieldAccess
+                                        (Ident (Identifier "supplement"))
+                                        (Ident (Identifier "element")))
+                                 ]
+                             , Literal (String "-")
+                             , FuncCall
+                                 (Ident (Identifier "numbering"))
+                                 [ NormalArg
+                                     (FieldAccess
+                                        (Ident (Identifier "numbering"))
+                                        (Ident (Identifier "element")))
+                                 , SpreadArg
+                                     (FuncCall
+                                        (FieldAccess
+                                           (Ident (Identifier "at"))
+                                           (FuncCall
+                                              (Ident (Identifier "counter"))
+                                              [ NormalArg (Ident (Identifier "heading")) ]))
+                                        [ NormalArg
+                                            (FuncCall
+                                               (FieldAccess
+                                                  (Ident (Identifier "location"))
+                                                  (Ident (Identifier "element")))
+                                               [])
+                                        ])
+                                 ]
+                             , Literal (String "]")
+                             ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block (CodeBlock [ Ident (Identifier "it") ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Heading 1 [ Text "Introduction" ]
+, Code
+    "test/typ/meta/ref-04.typ" ( line 19 , column 16 ) (Label "intro")
+, ParBreak
+, Heading 1 [ Text "Summary" ]
+, Code
+    "test/typ/meta/ref-04.typ" ( line 21 , column 11 ) (Label "sum")
+, ParBreak
+, Heading 2 [ Text "Subsection" ]
+, Code
+    "test/typ/meta/ref-04.typ" ( line 23 , column 15 ) (Label "sub")
+, ParBreak
+, Ref "intro" (Literal Auto)
+, ParBreak
+, Ref "sum" (Literal Auto)
+, ParBreak
+, Ref "sub" (Literal Auto)
+, ParBreak
+]
+"test/typ/meta/ref-04.typ" (line 23, column 15):
+Content does not have a method "element" or FieldAccess requires a dictionary
diff --git a/test/out/meta/ref-05.out b/test/out/meta/ref-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/ref-05.out
@@ -0,0 +1,149 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/ref-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/ref-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/ref-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/meta/ref-05.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "ref")))
+       (FuncExpr
+          [ NormalParam (Identifier "it") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Not
+                          (Equals
+                             (FieldAccess
+                                (Ident (Identifier "element")) (Ident (Identifier "it")))
+                             (Literal None))
+                      , Block
+                          (CodeBlock
+                             [ If
+                                 [ ( Equals
+                                       (FuncCall
+                                          (FieldAccess
+                                             (Ident (Identifier "func"))
+                                             (FieldAccess
+                                                (Ident (Identifier "element"))
+                                                (Ident (Identifier "it"))))
+                                          [])
+                                       (Ident (Identifier "text"))
+                                   , Block
+                                       (CodeBlock
+                                          [ Let
+                                              (BasicBind (Just (Identifier "element")))
+                                              (FieldAccess
+                                                 (Ident (Identifier "element"))
+                                                 (Ident (Identifier "it")))
+                                          , Literal (String "[")
+                                          , Ident (Identifier "element")
+                                          , Literal (String "]")
+                                          ])
+                                   )
+                                 , ( Equals
+                                       (FuncCall
+                                          (FieldAccess
+                                             (Ident (Identifier "func"))
+                                             (FieldAccess
+                                                (Ident (Identifier "element"))
+                                                (Ident (Identifier "it"))))
+                                          [])
+                                       (Ident (Identifier "underline"))
+                                   , Block
+                                       (CodeBlock
+                                          [ Let
+                                              (BasicBind (Just (Identifier "element")))
+                                              (FieldAccess
+                                                 (Ident (Identifier "element"))
+                                                 (Ident (Identifier "it")))
+                                          , Literal (String "{")
+                                          , Ident (Identifier "element")
+                                          , Literal (String "}")
+                                          ])
+                                   )
+                                 , ( Literal (Boolean True)
+                                   , Block (CodeBlock [ Ident (Identifier "it") ])
+                                   )
+                                 ]
+                             ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block (CodeBlock [ Ident (Identifier "it") ])
+                      )
+                    ]
+                ]))))
+, ParBreak
+, Ref "txt" (Literal Auto)
+, ParBreak
+, Text "Ref"
+, Space
+, Text "something"
+, Space
+, Text "unreferable"
+, Space
+, Code
+    "test/typ/meta/ref-05.typ" ( line 25 , column 27 ) (Label "txt")
+, ParBreak
+, Ref "under" (Literal Auto)
+, SoftBreak
+, Code
+    "test/typ/meta/ref-05.typ"
+    ( line 28 , column 2 )
+    (FuncCall
+       (Ident (Identifier "underline"))
+       [ BlockArg
+           [ SoftBreak
+           , Text "Some"
+           , Space
+           , Text "underline"
+           , Space
+           , Text "text"
+           , Text "."
+           , ParBreak
+           ]
+       ])
+, Space
+, Code
+    "test/typ/meta/ref-05.typ" ( line 30 , column 3 ) (Label "under")
+, ParBreak
+]
+"test/typ/meta/ref-05.typ" (line 3, column 2):
+Content does not have a method "element" or FieldAccess requires a dictionary
diff --git a/test/out/meta/state-00.out b/test/out/meta/state-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/state-00.out
@@ -0,0 +1,139 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/state-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/state-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/state-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/state-00.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "s")))
+       (FuncCall
+          (Ident (Identifier "state"))
+          [ NormalArg (Literal (String "hey"))
+          , NormalArg (Literal (String "a"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/meta/state-00.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "double")
+       [ NormalParam (Identifier "it") ]
+       (Times (Literal (Int 2)) (Ident (Identifier "it"))))
+, ParBreak
+, Code
+    "test/typ/meta/state-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "update")) (Ident (Identifier "s")))
+       [ NormalArg (Ident (Identifier "double")) ])
+, SoftBreak
+, Code
+    "test/typ/meta/state-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "update")) (Ident (Identifier "s")))
+       [ NormalArg (Ident (Identifier "double")) ])
+, SoftBreak
+, Equation True [ Text "2" , Text "+" , Text "3" ]
+, SoftBreak
+, Code
+    "test/typ/meta/state-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "update")) (Ident (Identifier "s")))
+       [ NormalArg (Ident (Identifier "double")) ])
+, ParBreak
+, Text "Is"
+, Text ":"
+, Space
+, Code
+    "test/typ/meta/state-00.typ"
+    ( line 10 , column 6 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "display")) (Ident (Identifier "s")))
+       [])
+, Text ","
+, SoftBreak
+, Text "Was"
+, Text ":"
+, Space
+, Code
+    "test/typ/meta/state-00.typ"
+    ( line 11 , column 7 )
+    (FuncCall
+       (Ident (Identifier "locate"))
+       [ NormalArg
+           (FuncExpr
+              [ NormalParam (Identifier "location") ]
+              (Block
+                 (CodeBlock
+                    [ Let
+                        (BasicBind (Just (Identifier "it")))
+                        (FuncCall
+                           (FieldAccess
+                              (Ident (Identifier "first"))
+                              (FuncCall
+                                 (Ident (Identifier "query"))
+                                 [ NormalArg
+                                     (FieldAccess
+                                        (Ident (Identifier "equation")) (Ident (Identifier "math")))
+                                 , NormalArg (Ident (Identifier "location"))
+                                 ]))
+                           [])
+                    , FuncCall
+                        (FieldAccess (Ident (Identifier "at")) (Ident (Identifier "s")))
+                        [ NormalArg
+                            (FuncCall
+                               (FieldAccess
+                                  (Ident (Identifier "location")) (Ident (Identifier "it")))
+                               [])
+                        ]
+                    ])))
+       ])
+, Text "."
+, ParBreak
+]
+"test/typ/meta/state-00.typ" (line 5, column 2):
+Content does not have a method "update" or FieldAccess requires a dictionary
diff --git a/test/out/meta/state-01.out b/test/out/meta/state-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/meta/state-01.out
@@ -0,0 +1,216 @@
+--- parse tree ---
+[ Code
+    "test/typ/meta/state-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/meta/state-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/meta/state-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 5 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "ls")))
+       (FuncCall
+          (Ident (Identifier "state"))
+          [ NormalArg (Literal (String "lorem"))
+          , NormalArg
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "split"))
+                    (FuncCall
+                       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 1000)) ]))
+                 [ NormalArg (Literal (String ".")) ])
+          ]))
+, SoftBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 6 , column 2 )
+    (LetFunc
+       (Identifier "loremum")
+       [ NormalParam (Identifier "count") ]
+       (Block
+          (CodeBlock
+             [ FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "display")) (Ident (Identifier "ls")))
+                 [ NormalArg
+                     (FuncExpr
+                        [ NormalParam (Identifier "list") ]
+                        (Plus
+                           (FuncCall
+                              (FieldAccess
+                                 (Ident (Identifier "trim"))
+                                 (FuncCall
+                                    (FieldAccess
+                                       (Ident (Identifier "join"))
+                                       (FuncCall
+                                          (FieldAccess
+                                             (Ident (Identifier "slice"))
+                                             (Ident (Identifier "list")))
+                                          [ NormalArg (Literal (Int 0))
+                                          , NormalArg (Ident (Identifier "count"))
+                                          ]))
+                                    [ NormalArg (Literal (String ".")) ]))
+                              [])
+                           (Literal (String "."))))
+                 ]
+             , FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "update")) (Ident (Identifier "ls")))
+                 [ NormalArg
+                     (FuncExpr
+                        [ NormalParam (Identifier "list") ]
+                        (FuncCall
+                           (FieldAccess
+                              (Ident (Identifier "slice")) (Ident (Identifier "list")))
+                           [ NormalArg (Ident (Identifier "count")) ]))
+                 ]
+             ])))
+, ParBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 11 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "fs")))
+       (FuncCall
+          (Ident (Identifier "state"))
+          [ NormalArg (Literal (String "fader"))
+          , NormalArg (Ident (Identifier "red"))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 12 , column 2 )
+    (LetFunc
+       (Identifier "trait")
+       [ NormalParam (Identifier "title") ]
+       (FuncCall
+          (Ident (Identifier "block"))
+          [ BlockArg
+              [ SoftBreak
+              , Code
+                  "test/typ/meta/state-01.typ"
+                  ( line 13 , column 4 )
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "display")) (Ident (Identifier "fs")))
+                     [ NormalArg
+                         (FuncExpr
+                            [ NormalParam (Identifier "color") ]
+                            (FuncCall
+                               (Ident (Identifier "text"))
+                               [ KeyValArg (Identifier "fill") (Ident (Identifier "color"))
+                               , BlockArg
+                                   [ SoftBreak
+                                   , Strong
+                                       [ Code
+                                           "test/typ/meta/state-01.typ"
+                                           ( line 14 , column 7 )
+                                           (Ident (Identifier "title"))
+                                       , Text ":"
+                                       ]
+                                   , Space
+                                   , Code
+                                       "test/typ/meta/state-01.typ"
+                                       ( line 14 , column 16 )
+                                       (FuncCall
+                                          (Ident (Identifier "loremum"))
+                                          [ NormalArg (Literal (Int 1)) ])
+                                   , ParBreak
+                                   ]
+                               ]))
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/meta/state-01.typ"
+                  ( line 16 , column 4 )
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "update")) (Ident (Identifier "fs")))
+                     [ NormalArg
+                         (FuncExpr
+                            [ NormalParam (Identifier "color") ]
+                            (FuncCall
+                               (FieldAccess
+                                  (Ident (Identifier "lighten")) (Ident (Identifier "color")))
+                               [ NormalArg (Literal (Numeric 30.0 Percent)) ]))
+                     ])
+              , ParBreak
+              ]
+          ]))
+, ParBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 19 , column 2 )
+    (FuncCall
+       (Ident (Identifier "trait")) [ BlockArg [ Text "Boldness" ] ])
+, SoftBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 20 , column 2 )
+    (FuncCall
+       (Ident (Identifier "trait")) [ BlockArg [ Text "Adventure" ] ])
+, SoftBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 21 , column 2 )
+    (FuncCall
+       (Ident (Identifier "trait")) [ BlockArg [ Text "Fear" ] ])
+, SoftBreak
+, Code
+    "test/typ/meta/state-01.typ"
+    ( line 22 , column 2 )
+    (FuncCall
+       (Ident (Identifier "trait")) [ BlockArg [ Text "Anger" ] ])
+, ParBreak
+]
+"test/typ/meta/state-01.typ" (line 13, column 4):
+Content does not have a method "display" or FieldAccess requires a dictionary
diff --git a/test/out/text/baseline-00.out b/test/out/text/baseline-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/baseline-00.out
@@ -0,0 +1,193 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/baseline-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/baseline-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/baseline-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, EmDash
+, SoftBreak
+, Text "Hi"
+, Space
+, Code
+    "test/typ/text/baseline-00.typ"
+    ( line 5 , column 5 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 1.5 Em)) , BlockArg [ Text "You" ] ])
+, Text ","
+, Space
+, Code
+    "test/typ/text/baseline-00.typ"
+    ( line 5 , column 24 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 0.75 Em))
+       , BlockArg
+           [ Text "how" , Space , Text "are" , Space , Text "you?" ]
+       ])
+, ParBreak
+, Text "Our"
+, Space
+, Text "cockatoo"
+, Space
+, Text "was"
+, Space
+, Text "one"
+, Space
+, Text "of"
+, Space
+, Text "the"
+, SoftBreak
+, Code
+    "test/typ/text/baseline-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "baseline") (Negated (Literal (Numeric 0.2 Em)))
+       , BlockArg
+           [ Code
+               "test/typ/text/baseline-00.typ"
+               ( line 8 , column 26 )
+               (FuncCall
+                  (Ident (Identifier "box"))
+                  [ NormalArg
+                      (FuncCall
+                         (Ident (Identifier "circle"))
+                         [ KeyValArg (Identifier "radius") (Literal (Numeric 2.0 Pt)) ])
+                  ])
+           , Space
+           , Text "first"
+           ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/baseline-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "baseline") (Literal (Numeric 0.2 Em))
+       , BlockArg
+           [ Text "birds"
+           , Space
+           , Code
+               "test/typ/text/baseline-00.typ"
+               ( line 9 , column 31 )
+               (FuncCall
+                  (Ident (Identifier "box"))
+                  [ NormalArg
+                      (FuncCall
+                         (Ident (Identifier "circle"))
+                         [ KeyValArg (Identifier "radius") (Literal (Numeric 2.0 Pt)) ])
+                  ])
+           ]
+       ])
+, SoftBreak
+, Text "that"
+, Space
+, Text "ever"
+, Space
+, Text "learned"
+, Space
+, Text "to"
+, Space
+, Text "mimic"
+, Space
+, Text "a"
+, Space
+, Text "human"
+, Space
+, Text "voice"
+, Text "."
+, ParBreak
+, EmDash
+, SoftBreak
+, Text "Hey"
+, Space
+, Code
+    "test/typ/text/baseline-00.typ"
+    ( line 13 , column 6 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ KeyValArg
+           (Identifier "baseline") (Literal (Numeric 40.0 Percent))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 1.5 Cm))
+              ])
+       ])
+, Space
+, Text "there!"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+—
+Hi ]), 
+  text(body: text(body: [You]), 
+       size: 1.5em), 
+  text(body: [, ]), 
+  text(body: text(body: [how are you?]), 
+       size: 0.75em), 
+  parbreak(), 
+  text(body: [Our cockatoo was one of the
+]), 
+  text(baseline: -0.2em, 
+       body: { box(body: circle(radius: 2.0pt)), 
+               text(body: [ first]) }), 
+  text(body: [
+]), 
+  text(baseline: 0.2em, 
+       body: { text(body: [birds ]), 
+               box(body: circle(radius: 2.0pt)) }), 
+  text(body: [
+that ever learned to mimic a human voice.]), 
+  parbreak(), 
+  text(body: [—
+Hey ]), 
+  box(baseline: 40%, 
+      body: image(path: "test/assets/files/tiger.jpg", 
+                  width: 1.5cm)), 
+  text(body: [ there!]), 
+  parbreak() }
diff --git a/test/out/text/case-00.out b/test/out/text/case-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/case-00.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/case-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/case-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/case-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/case-00.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "memes")))
+       (Literal (String "ArE mEmEs gReAt?")))
+, SoftBreak
+, Code
+    "test/typ/text/case-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "lower"))
+              [ NormalArg (Ident (Identifier "memes")) ])
+       , NormalArg (Literal (String "are memes great?"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/case-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "upper"))
+              [ NormalArg (Ident (Identifier "memes")) ])
+       , NormalArg (Literal (String "ARE MEMES GREAT?"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/case-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "upper"))
+              [ NormalArg (Literal (String "\917\955\955\940\948\945")) ])
+       , NormalArg (Literal (String "\917\923\923\902\916\913"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  text(body: [
+]), 
+  text(body: [✅]), 
+  parbreak() }
diff --git a/test/out/text/case-01.out b/test/out/text/case-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/case-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/chinese-00.out b/test/out/text/chinese-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/chinese-00.out
@@ -0,0 +1,73 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/chinese-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/chinese-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/chinese-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/chinese-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "Noto Serif CJK SC"))
+       ])
+, ParBreak
+, Text
+    "\26159\32654\22269\24191\25773\20844\21496\30005\35270\21095\12298\36855\22833\12299\31532\&3\23395\30340\31532\&22\21644\&23\38598\65292\20063\26159\20840\21095\30340\31532\&71\38598\21644\&72\38598"
+, SoftBreak
+, Text
+    "\30001\25191\34892\21046\20316\20154\25140\33945\183\26519\36947\22827\21644\21345\23572\39039\183\24211\26031\32534\21095\65292\23548\28436\21017\26159\21478\19968\21517\25191\34892\21046\20316\20154\26480\20811\183\26412\24503"
+, SoftBreak
+, Text
+    "\33410\30446\20110\&2007\24180\&5\26376\&23\26085\22312\32654\22269\21644\21152\25343\22823\39318\25773\65292\20849\35745\21560\24341\20102\&1400\19975\32654\22269\35266\20247\25910\30475"
+, SoftBreak
+, Text
+    "\26412\38598\21152\19978\25554\25773\24191\21578\19968\20849\20063\25345\32493\26377\20004\20010\23567\26102"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [是美国广播公司电视剧《迷失》第3季的第22和23集，也是全剧的第71集和72集
+由执行制作人戴蒙·林道夫和卡尔顿·库斯编剧，导演则是另一名执行制作人杰克·本德
+节目于2007年5月23日在美国和加拿大首播，共计吸引了1400万美国观众收看
+本集加上插播广告一共也持续有两个小时], 
+       font: "Noto Serif CJK SC"), 
+  parbreak() }
diff --git a/test/out/text/copy-paste-00.out b/test/out/text/copy-paste-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/copy-paste-00.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/copy-paste-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/copy-paste-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/copy-paste-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Text "The"
+, Space
+, Text "after"
+, Space
+, Text "fira"
+, Space
+, Text "\127987\65039\8205\127752!"
+, ParBreak
+, Code
+    "test/typ/text/copy-paste-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ar"))
+       , KeyValArg
+           (Identifier "font") (Literal (String "Noto Sans Arabic"))
+       ])
+, SoftBreak
+, Text "\1605\1585\1581\1576\1611\1575"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+The after fira 🏳️‍🌈!]), 
+  parbreak(), 
+  text(body: [
+مرحبًا], 
+       font: "Noto Sans Arabic", 
+       lang: "ar"), 
+  parbreak() }
diff --git a/test/out/text/deco-00.out b/test/out/text/deco-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/deco-00.out
@@ -0,0 +1,170 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/deco-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/deco-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/deco-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/deco-00.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "red")))
+       (FuncCall
+          (Ident (Identifier "rgb"))
+          [ NormalArg (Literal (String "fc0030")) ]))
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/deco-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "strike"))
+       [ BlockArg
+           [ Text "Statements"
+           , Space
+           , Text "dreamt"
+           , Space
+           , Text "up"
+           , Space
+           , Text "by"
+           , Space
+           , Text "the"
+           , Space
+           , Text "utterly"
+           , Space
+           , Text "deranged"
+           , Text "."
+           ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/deco-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "underline"))
+       [ KeyValArg (Identifier "offset") (Literal (Numeric 5.0 Pt))
+       , BlockArg [ Text "Further" , Space , Text "below" , Text "." ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/deco-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "underline"))
+       [ KeyValArg (Identifier "stroke") (Ident (Identifier "red"))
+       , KeyValArg (Identifier "evade") (Literal (Boolean False))
+       , BlockArg
+           [ Text "Critical"
+           , Space
+           , Text "information"
+           , Space
+           , Text "is"
+           , Space
+           , Text "conveyed"
+           , Space
+           , Text "here"
+           , Text "."
+           ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/deco-00.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "underline"))
+              [ BlockArg
+                  [ Text "Change"
+                  , Space
+                  , Text "with"
+                  , Space
+                  , Text "the"
+                  , Space
+                  , Text "wind"
+                  , Text "."
+                  ]
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/deco-00.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "overline"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "underline"))
+              [ BlockArg
+                  [ Text "Running"
+                  , Space
+                  , Text "amongst"
+                  , Space
+                  , Text "the"
+                  , Space
+                  , Text "wolves"
+                  , Text "."
+                  ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  strike(body: text(body: [Statements dreamt up by the utterly deranged.])), 
+  parbreak(), 
+  underline(body: text(body: [Further below.]), 
+            offset: 5.0pt), 
+  parbreak(), 
+  underline(body: text(body: [Critical information is conveyed here.]), 
+            evade: false, 
+            stroke: rgb(98%,0%,18%,100%)), 
+  parbreak(), 
+  text(body: underline(body: text(body: [Change with the wind.])), 
+       fill: rgb(98%,0%,18%,100%)), 
+  parbreak(), 
+  overline(body: underline(body: text(body: [Running amongst the wolves.]))), 
+  parbreak() }
diff --git a/test/out/text/deco-01.out b/test/out/text/deco-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/deco-01.out
@@ -0,0 +1,125 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/deco-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/deco-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/deco-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/deco-01.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "redact")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "strike")))
+          [ KeyValArg (Identifier "stroke") (Literal (Numeric 10.0 Pt))
+          , KeyValArg (Identifier "extent") (Literal (Numeric 5.0e-2 Em))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/text/deco-01.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "highlight")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "strike")))
+          [ KeyValArg
+              (Identifier "stroke")
+              (Plus
+                 (Literal (Numeric 10.0 Pt))
+                 (FuncCall
+                    (Ident (Identifier "rgb"))
+                    [ NormalArg (Literal (String "abcdef88")) ]))
+          , KeyValArg (Identifier "extent") (Literal (Numeric 5.0e-2 Em))
+          ]))
+, ParBreak
+, Comment
+, Text "Sometimes,"
+, Space
+, Text "we"
+, Space
+, Text "work"
+, Space
+, Code
+    "test/typ/text/deco-01.typ"
+    ( line 6 , column 21 )
+    (FuncCall
+       (Ident (Identifier "redact"))
+       [ BlockArg [ Text "in" , Space , Text "secret" ] ])
+, Text "."
+, SoftBreak
+, Text "There"
+, Space
+, Text "might"
+, Space
+, Text "be"
+, Space
+, Code
+    "test/typ/text/deco-01.typ"
+    ( line 7 , column 17 )
+    (FuncCall
+       (Ident (Identifier "highlight")) [ BlockArg [ Text "redacted" ] ])
+, Space
+, Text "things"
+, Text "."
+, SoftBreak
+, Text "underline"
+, Text "("
+, Text ")"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Sometimes, we work ]), 
+  strike(body: text(body: [in secret]), 
+         extent: 5.0e-2em, 
+         stroke: 10.0pt), 
+  text(body: [.
+There might be ]), 
+  strike(body: text(body: [redacted]), 
+         extent: 5.0e-2em, 
+         stroke: (thickness: 10.0pt,
+                  color: rgb(67%,80%,93%,53%))), 
+  text(body: [ things.
+underline()]), 
+  parbreak() }
diff --git a/test/out/text/deco-02.out b/test/out/text/deco-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/deco-02.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/deco-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/deco-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/deco-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/deco-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "underline"))
+       [ KeyValArg (Identifier "stroke") (Literal (Numeric 2.0 Pt))
+       , KeyValArg (Identifier "offset") (Literal (Numeric 2.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/deco-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "underline"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "text"))
+              [ NormalArg (Ident (Identifier "red"))
+              , NormalArg (Block (Content [ Text "DANGER!" ]))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  underline(body: text(body: text(body: [DANGER!]), 
+                       color: rgb(100%,25%,21%,100%)), 
+            offset: 2.0pt, 
+            stroke: 2.0pt), 
+  parbreak() }
diff --git a/test/out/text/edge-00.out b/test/out/text/edge-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/edge-00.out
@@ -0,0 +1,333 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/edge-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/edge-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/edge-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 160.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "size") (Literal (Numeric 8.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 5 , column 2 )
+    (LetFunc
+       (Identifier "try")
+       [ NormalParam (Identifier "top")
+       , NormalParam (Identifier "bottom")
+       ]
+       (FuncCall
+          (Ident (Identifier "rect"))
+          [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+          , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+          , BlockArg
+              [ SoftBreak
+              , Code
+                  "test/typ/text/edge-00.typ"
+                  ( line 6 , column 4 )
+                  (Set
+                     (Ident (Identifier "text"))
+                     [ KeyValArg (Identifier "font") (Literal (String "IBM Plex Mono"))
+                     , KeyValArg (Identifier "top-edge") (Ident (Identifier "top"))
+                     , KeyValArg
+                         (Identifier "bottom-edge") (Ident (Identifier "bottom"))
+                     ])
+              , SoftBreak
+              , Text "From"
+              , Space
+              , Code
+                  "test/typ/text/edge-00.typ"
+                  ( line 7 , column 9 )
+                  (Ident (Identifier "top"))
+              , Space
+              , Text "to"
+              , Space
+              , Code
+                  "test/typ/text/edge-00.typ"
+                  ( line 7 , column 17 )
+                  (Ident (Identifier "bottom"))
+              , ParBreak
+              ]
+          ]))
+, ParBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "try"))
+       [ NormalArg (Literal (String "ascender"))
+       , NormalArg (Literal (String "descender"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "try"))
+       [ NormalArg (Literal (String "ascender"))
+       , NormalArg (Literal (String "baseline"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "try"))
+       [ NormalArg (Literal (String "cap-height"))
+       , NormalArg (Literal (String "baseline"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "try"))
+       [ NormalArg (Literal (String "x-height"))
+       , NormalArg (Literal (String "baseline"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "try"))
+       [ NormalArg (Literal (Numeric 4.0 Pt))
+       , NormalArg (Negated (Literal (Numeric 2.0 Pt)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/edge-00.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "try"))
+       [ NormalArg
+           (Plus (Literal (Numeric 1.0 Pt)) (Literal (Numeric 0.3 Em)))
+       , NormalArg (Negated (Literal (Numeric 0.15 Em)))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  rect(body: { text(body: [
+], 
+                    size: 8.0pt), 
+               text(body: [
+From ], 
+                    bottom-edge: "descender", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               text(body: [ascender], 
+                    bottom-edge: "descender", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               text(body: [ to ], 
+                    bottom-edge: "descender", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               text(body: [descender], 
+                    bottom-edge: "descender", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               parbreak() }, 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 0.0pt), 
+  text(body: [
+], size: 8.0pt), 
+  rect(body: { text(body: [
+], 
+                    size: 8.0pt), 
+               text(body: [
+From ], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               text(body: [ascender], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               text(body: [ to ], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               text(body: [baseline], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "ascender"), 
+               parbreak() }, 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 0.0pt), 
+  text(body: [
+], size: 8.0pt), 
+  rect(body: { text(body: [
+], 
+                    size: 8.0pt), 
+               text(body: [
+From ], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "cap-height"), 
+               text(body: [cap-height], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "cap-height"), 
+               text(body: [ to ], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "cap-height"), 
+               text(body: [baseline], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "cap-height"), 
+               parbreak() }, 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 0.0pt), 
+  text(body: [
+], size: 8.0pt), 
+  rect(body: { text(body: [
+], 
+                    size: 8.0pt), 
+               text(body: [
+From ], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "x-height"), 
+               text(body: [x-height], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "x-height"), 
+               text(body: [ to ], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "x-height"), 
+               text(body: [baseline], 
+                    bottom-edge: "baseline", 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: "x-height"), 
+               parbreak() }, 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 0.0pt), 
+  text(body: [
+], size: 8.0pt), 
+  rect(body: { text(body: [
+], 
+                    size: 8.0pt), 
+               text(body: [
+From ], 
+                    bottom-edge: -2.0pt, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 4.0pt), 
+               text(body: [4.0pt], 
+                    bottom-edge: -2.0pt, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 4.0pt), 
+               text(body: [ to ], 
+                    bottom-edge: -2.0pt, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 4.0pt), 
+               text(body: [-2.0pt], 
+                    bottom-edge: -2.0pt, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 4.0pt), 
+               parbreak() }, 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 0.0pt), 
+  text(body: [
+], size: 8.0pt), 
+  rect(body: { text(body: [
+], 
+                    size: 8.0pt), 
+               text(body: [
+From ], 
+                    bottom-edge: -0.15em, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 1.0pt + 0.3em), 
+               text(body: [1.0pt + 0.3em], 
+                    bottom-edge: -0.15em, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 1.0pt + 0.3em), 
+               text(body: [ to ], 
+                    bottom-edge: -0.15em, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 1.0pt + 0.3em), 
+               text(body: [-0.15em], 
+                    bottom-edge: -0.15em, 
+                    font: "IBM Plex Mono", 
+                    size: 8.0pt, 
+                    top-edge: 1.0pt + 0.3em), 
+               parbreak() }, 
+       fill: rgb(18%,80%,25%,100%), 
+       inset: 0.0pt), 
+  parbreak() }
diff --git a/test/out/text/edge-01.out b/test/out/text/edge-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/edge-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/edge-02.out b/test/out/text/edge-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/edge-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/em-00.out b/test/out/text/em-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/em-00.out
@@ -0,0 +1,150 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/em-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/em-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/em-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/em-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "size") (Literal (Numeric 5.0 Pt)) ])
+, SoftBreak
+, Text "A"
+, Space
+, Comment
+, Code
+    "test/typ/text/em-00.typ"
+    ( line 4 , column 2 )
+    (Block
+       (Content
+          [ SoftBreak
+          , Code
+              "test/typ/text/em-00.typ"
+              ( line 5 , column 4 )
+              (Set
+                 (Ident (Identifier "text"))
+                 [ KeyValArg (Identifier "size") (Literal (Numeric 2.0 Em)) ])
+          , SoftBreak
+          , Text "B"
+          , Space
+          , Comment
+          , Space
+          , Code
+              "test/typ/text/em-00.typ"
+              ( line 7 , column 4 )
+              (Block
+                 (Content
+                    [ SoftBreak
+                    , Code
+                        "test/typ/text/em-00.typ"
+                        ( line 8 , column 6 )
+                        (Set
+                           (Ident (Identifier "text"))
+                           [ KeyValArg
+                               (Identifier "size")
+                               (Plus (Literal (Numeric 1.5 Em)) (Literal (Numeric 1.0 Pt)))
+                           ])
+                    , SoftBreak
+                    , Text "C"
+                    , Space
+                    , Comment
+                    , Space
+                    , Code
+                        "test/typ/text/em-00.typ"
+                        ( line 10 , column 6 )
+                        (FuncCall
+                           (Ident (Identifier "text"))
+                           [ KeyValArg (Identifier "size") (Literal (Numeric 2.0 Em))
+                           , BlockArg [ Text "D" ]
+                           ])
+                    , Space
+                    , Comment
+                    , Space
+                    , Text "E"
+                    , Space
+                    , Comment
+                    , Space
+                    ]))
+          , SoftBreak
+          , Text "F"
+          , Space
+          , Comment
+          ]))
+, SoftBreak
+, Text "G"
+, Space
+, Comment
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+A ], 
+       size: 5.0pt), 
+  text(body: [
+], size: 5.0pt), 
+  text(body: [
+B ], 
+       size: 2.0em), 
+  text(body: [ ], size: 2.0em), 
+  text(body: [
+], size: 2.0em), 
+  text(body: [
+C ], 
+       size: 1.5em + 1.0pt), 
+  text(body: [ ], 
+       size: 1.5em + 1.0pt), 
+  text(body: text(body: [D], 
+                  size: 1.5em + 1.0pt), 
+       size: 2.0em), 
+  text(body: [ ], 
+       size: 1.5em + 1.0pt), 
+  text(body: [ E ], 
+       size: 1.5em + 1.0pt), 
+  text(body: [ ], 
+       size: 1.5em + 1.0pt), 
+  text(body: [
+F ], 
+       size: 1.5em + 1.0pt), 
+  text(body: [
+G ], 
+       size: 1.5em + 1.0pt), 
+  parbreak() }
diff --git a/test/out/text/em-01.out b/test/out/text/em-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/em-01.out
@@ -0,0 +1,120 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/em-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/em-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/em-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/em-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "size") (Literal (Numeric 5.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/em-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "size") (Literal (Numeric 2.0 Em)) ])
+, SoftBreak
+, Code
+    "test/typ/text/em-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red")) ])
+, ParBreak
+, Code
+    "test/typ/text/em-01.typ"
+    ( line 7 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "size")))
+       (Block
+          (CodeBlock
+             [ Let
+                 (BasicBind (Just (Identifier "size")))
+                 (Plus (Literal (Numeric 0.25 Em)) (Literal (Numeric 1.0 Pt)))
+             , For
+                 (BasicBind Nothing)
+                 (FuncCall
+                    (Ident (Identifier "range")) [ NormalArg (Literal (Int 3)) ])
+                 (Block
+                    (CodeBlock
+                       [ Assign
+                           (Ident (Identifier "size"))
+                           (Times (Ident (Identifier "size")) (Literal (Int 2)))
+                       ]))
+             , Minus (Ident (Identifier "size")) (Literal (Numeric 3.0 Pt))
+             ])))
+, ParBreak
+, Code
+    "test/typ/text/em-01.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "size") (Ident (Identifier "size")) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "size") (Literal (Numeric 25.0 Pt)) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], size: 5.0pt), 
+  text(body: [
+], size: 2.0em), 
+  parbreak(), 
+  parbreak(), 
+  stack(children: (square(fill: rgb(100%,25%,21%,100%), 
+                          size: (2.0em + 8.0pt) + -3.0pt), 
+                   square(fill: rgb(100%,25%,21%,100%), 
+                          size: 25.0pt)), 
+        dir: ltr, 
+        spacing: 1.0fr), 
+  parbreak() }
diff --git a/test/out/text/emoji-00.out b/test/out/text/emoji-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emoji-00.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/emoji-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/emoji-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/emoji-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "\128105\8205\128105\8205\128102"
+, ParBreak
+, Comment
+, Text "\127987\65039\8205\127752"
+, ParBreak
+, Comment
+, Text "\128077\127999"
+, ParBreak
+, Comment
+, Text "1\65039\8419"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [👩‍👩‍👦]), 
+  parbreak(), 
+  text(body: [🏳️‍🌈]), 
+  parbreak(), 
+  text(body: [👍🏿]), 
+  parbreak(), 
+  text(body: [1️⃣]), 
+  parbreak() }
diff --git a/test/out/text/emoji-01.out b/test/out/text/emoji-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emoji-01.out
@@ -0,0 +1,50 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/emoji-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/emoji-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/emoji-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "\127966\8205\127755"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [🏞‍🌋]), 
+  parbreak() }
diff --git a/test/out/text/emphasis-00.out b/test/out/text/emphasis-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emphasis-00.out
@@ -0,0 +1,84 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/emphasis-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/emphasis-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/emphasis-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Emph
+    [ Text "Emphasized"
+    , Space
+    , Text "and"
+    , Space
+    , Strong [ Text "strong" ]
+    , Space
+    , Text "words!"
+    ]
+, ParBreak
+, Comment
+, Text "hello_world"
+, Space
+, Text "Nutzer*innen"
+, ParBreak
+, Comment
+, Emph
+    [ Text "Still"
+    , Space
+    , Code
+        "test/typ/text/emphasis-00.typ"
+        ( line 9 , column 9 )
+        (Block (Content [ ParBreak ]))
+    , Space
+    , Text "emphasized"
+    , Text "."
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  emph(body: { text(body: [Emphasized and ]), 
+               strong(body: text(body: [strong])), 
+               text(body: [ words!]) }), 
+  parbreak(), 
+  text(body: [hello_world Nutzer*innen]), 
+  parbreak(), 
+  emph(body: { text(body: [Still ]), 
+               parbreak(), 
+               text(body: [ emphasized.]) }), 
+  parbreak() }
diff --git a/test/out/text/emphasis-01.out b/test/out/text/emphasis-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emphasis-01.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/emphasis-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/emphasis-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/emphasis-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "P"
+, Code
+    "test/typ/text/emphasis-01.typ"
+    ( line 3 , column 3 )
+    (FuncCall
+       (Ident (Identifier "strong")) [ BlockArg [ Text "art" ] ])
+, Text "ly"
+, Space
+, Text "em"
+, Code
+    "test/typ/text/emphasis-01.typ"
+    ( line 3 , column 20 )
+    (FuncCall (Ident (Identifier "emph")) [ BlockArg [ Text "phas" ] ])
+, Text "ized"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [P]), 
+  strong(body: text(body: [art])), 
+  text(body: [ly em]), 
+  emph(body: text(body: [phas])), 
+  text(body: [ized.]), 
+  parbreak() }
diff --git a/test/out/text/emphasis-02.out b/test/out/text/emphasis-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emphasis-02.out
@@ -0,0 +1,91 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/emphasis-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/emphasis-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/emphasis-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Normal"
+, ParBreak
+, Code
+    "test/typ/text/emphasis-02.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "strong"))
+       [ KeyValArg (Identifier "delta") (Literal (Int 300)) ])
+, SoftBreak
+, Strong [ Text "Bold" ]
+, ParBreak
+, Code
+    "test/typ/text/emphasis-02.typ"
+    ( line 8 , column 2 )
+    (Set
+       (Ident (Identifier "strong"))
+       [ KeyValArg (Identifier "delta") (Literal (Int 150)) ])
+, SoftBreak
+, Strong [ Text "Medium" ]
+, Space
+, Text "and"
+, Space
+, Strong
+    [ Code
+        "test/typ/text/emphasis-02.typ"
+        ( line 9 , column 16 )
+        (Block (Content [ Strong [ Text "Bold" ] ]))
+    ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Normal]), 
+  parbreak(), 
+  text(body: [
+]), 
+  strong(body: text(body: [Bold]), 
+         delta: 300), 
+  parbreak(), 
+  text(body: [
+]), 
+  strong(body: text(body: [Medium]), 
+         delta: 150), 
+  text(body: [ and ]), 
+  strong(body: strong(body: text(body: [Bold]), 
+                      delta: 150), 
+         delta: 150), 
+  parbreak() }
diff --git a/test/out/text/emphasis-03.out b/test/out/text/emphasis-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emphasis-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/emphasis-04.out b/test/out/text/emphasis-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emphasis-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/emphasis-05.out b/test/out/text/emphasis-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/emphasis-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/escape-00.out b/test/out/text/escape-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/escape-00.out
@@ -0,0 +1,187 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/escape-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/escape-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/escape-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "\\"
+, Space
+, Text "/"
+, Space
+, Text "["
+, Space
+, Text "]"
+, Space
+, Text "{"
+, Space
+, Text "}"
+, Space
+, Text "#"
+, Space
+, Text "*"
+, Space
+, Text "_"
+, Space
+, Text "+"
+, Space
+, Text "="
+, Space
+, Text "~"
+, Space
+, HardBreak
+, Text "`"
+, Space
+, Text "$"
+, Space
+, Text "\""
+, Space
+, Text "'"
+, Space
+, Text "<"
+, Space
+, Text ">"
+, Space
+, Text "@"
+, Space
+, Text "("
+, Space
+, Text ")"
+, Space
+, Text "A"
+, ParBreak
+, Comment
+, Text "("
+, Space
+, Text ")"
+, Space
+, Text ";"
+, ParBreak
+, Comment
+, Text "/"
+, Text "/"
+, SoftBreak
+, Text "/"
+, Text "*"
+, Space
+, Text "*"
+, Text "/"
+, SoftBreak
+, Text "/"
+, Strong [ Space , Text "*" , Text "/" , Space ]
+, ParBreak
+, Comment
+, Text "\127957"
+, Space
+, Text "="
+, Text "="
+, Space
+, Text "\127957"
+, ParBreak
+, Comment
+, Text "A"
+, Space
+, Text "vs"
+, Text "."
+, Space
+, Text "\\"
+, Text "u"
+, Text "{"
+, Text "41"
+, Text "}"
+, ParBreak
+, Comment
+, Text "let"
+, Space
+, Text "f"
+, Text "("
+, Text ")"
+, Space
+, Text ","
+, Space
+, Text ";"
+, Space
+, Text ":"
+, Space
+, Text "|"
+, Space
+, Text "+"
+, Space
+, Text "-"
+, Space
+, Text "/"
+, Text "="
+, Space
+, Text "="
+, Text "="
+, Space
+, Text "12"
+, Space
+, Quote '"'
+, Text "string"
+, Quote '"'
+, ParBreak
+, Comment
+, Text "10"
+, Text "."
+, Space
+, Text "May"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [\ / [ ] { } # * _ + = ~ ]), 
+  linebreak(), 
+  text(body: [` $ " ' < > @ ( ) A]), 
+  parbreak(), 
+  text(body: [( ) ;]), 
+  parbreak(), 
+  text(body: [//
+/* */
+/]), 
+  strong(body: text(body: [ */ ])), 
+  parbreak(), 
+  text(body: [🏕 == 🏕]), 
+  parbreak(), 
+  text(body: [A vs. \u{41}]), 
+  parbreak(), 
+  text(body: [let f() , ; : | + - /= == 12 “string”]), 
+  parbreak(), 
+  text(body: [10. May]), 
+  parbreak() }
diff --git a/test/out/text/escape-01.out b/test/out/text/escape-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/escape-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/escape-02.out b/test/out/text/escape-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/escape-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/fallback-00.out b/test/out/text/fallback-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/fallback-00.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/fallback-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/fallback-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/fallback-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A\128512B"
+, ParBreak
+, Comment
+, Text "\1583\1593"
+, Space
+, Text "\1575\1604\1606\1589"
+, Space
+, Text "\1610\1605\1591\1585"
+, Space
+, Text "\1593\1604\1610\1603"
+, ParBreak
+, Comment
+, Text "\1576\128008\128512\1587\1605"
+, ParBreak
+, Comment
+, Text "A\1576\128512\127966\1587\1605B"
+, ParBreak
+, Comment
+, Text "01\65039\8419\&2"
+, ParBreak
+, Comment
+, Text "A\128008\4850\4638B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A😀B]), 
+  parbreak(), 
+  text(body: [دع النص يمطر عليك]), 
+  parbreak(), 
+  text(body: [ب🐈😀سم]), 
+  parbreak(), 
+  text(body: [Aب😀🏞سمB]), 
+  parbreak(), 
+  text(body: [01️⃣2]), 
+  parbreak(), 
+  text(body: [A🐈ዲሞB]), 
+  parbreak() }
diff --git a/test/out/text/features-00.out b/test/out/text/features-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-00.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/features-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "kerning") (Literal (Boolean True))
+       , BlockArg [ Text "Tq" ]
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/text/features-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "kerning") (Literal (Boolean False))
+       , BlockArg [ Text "Tq" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: text(body: [Tq]), 
+       kerning: true), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: text(body: [Tq]), 
+       kerning: false), 
+  parbreak() }
diff --git a/test/out/text/features-01.out b/test/out/text/features-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-01.out
@@ -0,0 +1,54 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/features-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "smallcaps")) [ BlockArg [ Text "Smallcaps" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  smallcaps(body: text(body: [Smallcaps])), 
+  parbreak() }
diff --git a/test/out/text/features-02.out b/test/out/text/features-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-02.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/features-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "IBM Plex Serif"))
+       ])
+, SoftBreak
+, Text "a"
+, Space
+, Text "vs"
+, Space
+, Code
+    "test/typ/text/features-02.typ"
+    ( line 4 , column 7 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "alternates") (Literal (Boolean True))
+       , BlockArg [ Text "a" ]
+       ])
+, Space
+, HardBreak
+, Text "\223"
+, Space
+, Text "vs"
+, Space
+, Code
+    "test/typ/text/features-02.typ"
+    ( line 5 , column 7 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "stylistic-set") (Literal (Int 5))
+       , BlockArg [ Text "\223" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+a vs ], 
+       font: "IBM Plex Serif"), 
+  text(alternates: true, 
+       body: text(body: [a], 
+                  font: "IBM Plex Serif"), 
+       font: "IBM Plex Serif"), 
+  text(body: [ ], 
+       font: "IBM Plex Serif"), 
+  linebreak(), 
+  text(body: [ß vs ], 
+       font: "IBM Plex Serif"), 
+  text(body: text(body: [ß], 
+                  font: "IBM Plex Serif"), 
+       font: "IBM Plex Serif", 
+       stylistic-set: 5), 
+  parbreak() }
diff --git a/test/out/text/features-03.out b/test/out/text/features-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-03.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "fi"
+, Space
+, Text "vs"
+, Text "."
+, Space
+, Code
+    "test/typ/text/features-03.typ"
+    ( line 3 , column 9 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "ligatures") (Literal (Boolean False))
+       , BlockArg [ Text "No" , Space , Text "fi" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [fi vs. ]), 
+  text(body: text(body: [No fi]), 
+       ligatures: false), 
+  parbreak() }
diff --git a/test/out/text/features-04.out b/test/out/text/features-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-04.out
@@ -0,0 +1,75 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/features-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "number-type") (Literal (String "old-style"))
+       ])
+, SoftBreak
+, Text "0123456789"
+, Space
+, HardBreak
+, Code
+    "test/typ/text/features-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "number-type") (Literal Auto)
+       , BlockArg [ Text "0123456789" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+0123456789 ], 
+       number-type: "old-style"), 
+  linebreak(), 
+  text(body: text(body: [0123456789], 
+                  number-type: "old-style"), 
+       number-type: auto), 
+  parbreak() }
diff --git a/test/out/text/features-05.out b/test/out/text/features-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-05.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/features-05.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "number-width") (Literal (String "proportional"))
+       , BlockArg [ Text "0123456789" ]
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/text/features-05.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "number-width") (Literal (String "tabular"))
+       , BlockArg [ Text "3456789123" ]
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/text/features-05.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "number-width") (Literal (String "tabular"))
+       , BlockArg [ Text "0123456789" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: text(body: [0123456789]), 
+       number-width: "proportional"), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: text(body: [3456789123]), 
+       number-width: "tabular"), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: text(body: [0123456789]), 
+       number-width: "tabular"), 
+  parbreak() }
diff --git a/test/out/text/features-06.out b/test/out/text/features-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-06.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/features-06.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "IBM Plex Serif"))
+       ])
+, SoftBreak
+, Text "0"
+, Space
+, Text "vs"
+, Text "."
+, Space
+, Code
+    "test/typ/text/features-06.typ"
+    ( line 4 , column 8 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "slashed-zero") (Literal (Boolean True))
+       , BlockArg [ Text "0" ]
+       ])
+, Space
+, HardBreak
+, Text "1"
+, Text "/"
+, Text "2"
+, Space
+, Text "vs"
+, Text "."
+, Space
+, Code
+    "test/typ/text/features-06.typ"
+    ( line 5 , column 10 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "fractions") (Literal (Boolean True))
+       , BlockArg [ Text "1" , Text "/" , Text "2" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+0 vs. ], 
+       font: "IBM Plex Serif"), 
+  text(body: text(body: [0], 
+                  font: "IBM Plex Serif"), 
+       font: "IBM Plex Serif", 
+       slashed-zero: true), 
+  text(body: [ ], 
+       font: "IBM Plex Serif"), 
+  linebreak(), 
+  text(body: [1/2 vs. ], 
+       font: "IBM Plex Serif"), 
+  text(body: text(body: [1/2], 
+                  font: "IBM Plex Serif"), 
+       font: "IBM Plex Serif", 
+       fractions: true), 
+  parbreak() }
diff --git a/test/out/text/features-07.out b/test/out/text/features-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-07.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/features-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/features-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/features-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/features-07.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "features") (Array [ Literal (String "smcp") ])
+       , BlockArg [ Text "Smcp" ]
+       ])
+, Space
+, HardBreak
+, Text "fi"
+, Space
+, Text "vs"
+, Text "."
+, Space
+, Code
+    "test/typ/text/features-07.typ"
+    ( line 4 , column 9 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "features")
+           (Dict [ ( Identifier "liga" , Literal (Int 0) ) ])
+       , BlockArg [ Text "No" , Space , Text "fi" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: text(body: [Smcp]), 
+       features: ("smcp")), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [fi vs. ]), 
+  text(body: text(body: [No fi]), 
+       features: (liga: 0)), 
+  parbreak() }
diff --git a/test/out/text/features-08.out b/test/out/text/features-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/features-09.out b/test/out/text/features-09.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-09.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/features-10.out b/test/out/text/features-10.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-10.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/features-11.out b/test/out/text/features-11.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-11.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/features-12.out b/test/out/text/features-12.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/features-12.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/font-00.out b/test/out/text/font-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/font-00.out
@@ -0,0 +1,239 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/font-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/font-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/font-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 20.0 Pt)) , BlockArg [ Text "A" ] ])
+, SoftBreak
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 2.0 Em)) , BlockArg [ Text "A" ] ])
+, SoftBreak
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "size")
+           (Plus (Literal (Numeric 15.0 Pt)) (Literal (Numeric 0.5 Em)))
+       , BlockArg [ Text "A" ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text")) [ BlockArg [ Text "Normal" ] ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "style") (Literal (String "italic"))
+       , BlockArg [ Text "Italic" ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 14 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "weight") (Literal (String "bold"))
+       , BlockArg [ Text "Bold" ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "stretch") (Literal (Numeric 50.0 Percent))
+       , BlockArg [ Text "Condensed" ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 20 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "IBM Plex Serif"))
+       , BlockArg [ Text "Serif" ]
+       ])
+, ParBreak
+, Comment
+, Text "Emoji"
+, Text ":"
+, Space
+, Text "\128042,"
+, Space
+, Text "\127755,"
+, Space
+, Text "\127966"
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 26 , column 2 )
+    (Block
+       (Content
+          [ SoftBreak
+          , Code
+              "test/typ/text/font-00.typ"
+              ( line 27 , column 4 )
+              (Set
+                 (Ident (Identifier "text"))
+                 [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern")) ])
+          , SoftBreak
+          , Text "This"
+          , Space
+          , Text "is"
+          , Space
+          , Code
+              "test/typ/text/font-00.typ"
+              ( line 28 , column 12 )
+              (FuncCall
+                 (Ident (Identifier "text"))
+                 [ NormalArg
+                     (FuncCall
+                        (Ident (Identifier "rgb"))
+                        [ NormalArg (Literal (String "FA644B")) ])
+                 , BlockArg [ Text "way" , Space , Text "more" ]
+                 ])
+          , Space
+          , Text "colorful"
+          , Text "."
+          , ParBreak
+          ]))
+, ParBreak
+, Comment
+, Comment
+, Code
+    "test/typ/text/font-00.typ"
+    ( line 33 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "PT Sans")
+              , Literal (String "Twitter Color Emoji")
+              ])
+       , KeyValArg (Identifier "fallback") (Literal (Boolean False))
+       ])
+, SoftBreak
+, Text "2\960"
+, Space
+, Text "="
+, Space
+, Text "\120572"
+, Space
+, Text "+"
+, Space
+, Text "\120573"
+, Text "."
+, Space
+, Text "\9989"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: text(body: [A]), 
+       size: 20.0pt), 
+  text(body: [
+]), 
+  text(body: text(body: [A]), 
+       size: 2.0em), 
+  text(body: [
+]), 
+  text(body: text(body: [A]), 
+       size: 15.0pt + 0.5em), 
+  parbreak(), 
+  text(body: text(body: [Normal])), 
+  parbreak(), 
+  text(body: text(body: [Italic]), 
+       style: "italic"), 
+  parbreak(), 
+  text(body: text(body: [Bold]), 
+       weight: "bold"), 
+  parbreak(), 
+  text(body: text(body: [Condensed]), 
+       stretch: 50%), 
+  parbreak(), 
+  text(body: text(body: [Serif]), 
+       font: "IBM Plex Serif"), 
+  parbreak(), 
+  text(body: [Emoji: 🐪, 🌋, 🏞]), 
+  parbreak(), 
+  text(body: [
+]), 
+  text(body: [
+This is ], 
+       fill: rgb(13%,61%,67%,100%)), 
+  text(body: text(body: [way more], 
+                  fill: rgb(13%,61%,67%,100%)), 
+       color: rgb(98%,39%,29%,100%), 
+       fill: rgb(13%,61%,67%,100%)), 
+  text(body: [ colorful.], 
+       fill: rgb(13%,61%,67%,100%)), 
+  parbreak(), 
+  parbreak(), 
+  text(body: [
+2π = 𝛼 + 𝛽. ✅], 
+       fallback: false, 
+       fill: rgb(13%,61%,67%,100%), 
+       font: ("PT Sans", 
+              "Twitter Color Emoji")), 
+  parbreak() }
diff --git a/test/out/text/font-01.out b/test/out/text/font-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/font-01.out
@@ -0,0 +1,122 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/font-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/font-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/font-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/font-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (String "Text")) ])
+, Space
+, HardBreak
+, Code
+    "test/typ/text/font-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Ident (Identifier "red"))
+       , NormalArg (Literal (String "Text"))
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/text/font-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "Ubuntu"))
+       , NormalArg (Ident (Identifier "blue"))
+       , NormalArg (Literal (String "Text"))
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/text/font-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Block (Content [ Text "Text" ]))
+       , NormalArg (Ident (Identifier "teal"))
+       , KeyValArg (Identifier "font") (Literal (String "IBM Plex Serif"))
+       ])
+, Space
+, HardBreak
+, Code
+    "test/typ/text/font-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ NormalArg (Ident (Identifier "red"))
+       , KeyValArg
+           (Identifier "font") (Literal (String "New Computer Modern"))
+       , NormalArg (Block (Content [ Text "Text" ]))
+       ])
+, Space
+, HardBreak
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: "Text"), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: "Text", 
+       color: rgb(100%,25%,21%,100%)), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: "Text", 
+       color: rgb(0%,45%,85%,100%), 
+       font: "Ubuntu"), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: text(body: [Text]), 
+       color: rgb(22%,80%,80%,100%), 
+       font: "IBM Plex Serif"), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: text(body: [Text]), 
+       color: rgb(100%,25%,21%,100%), 
+       font: "New Computer Modern"), 
+  text(body: [ ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/text/font-02.out b/test/out/text/font-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/font-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/font-03.out b/test/out/text/font-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/font-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/font-04.out b/test/out/text/font-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/font-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/font-05.out b/test/out/text/font-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/font-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/hyphenate-00.out b/test/out/text/hyphenate-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/hyphenate-00.out
@@ -0,0 +1,111 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/hyphenate-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/hyphenate-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/hyphenate-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/hyphenate-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/text/hyphenate-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal Auto) ])
+, SoftBreak
+, Code
+    "test/typ/text/hyphenate-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array [ Literal (Numeric 50.0 Pt) , Literal (Numeric 50.0 Pt) ])
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "Warm"
+                 , Space
+                 , Text "welcomes"
+                 , Space
+                 , Text "to"
+                 , Space
+                 , Text "Typst"
+                 , Text "."
+                 ]))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "text"))
+              [ KeyValArg (Identifier "lang") (Literal (String "el"))
+              , BlockArg
+                  [ Text "\948\953\945\956\949\961\943\963\956\945\964\945"
+                  , Text "."
+                  , Space
+                  , HardBreak
+                  , Text "\955\945\964\961\949\965\964\972\962"
+                  ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       hyphenate: true), 
+  text(body: [
+], 
+       hyphenate: true), 
+  grid(children: (text(body: [Warm welcomes to Typst.], 
+                       hyphenate: true), 
+                  text(body: { text(body: [διαμερίσματα. ], 
+                                    hyphenate: true), 
+                               linebreak(), 
+                               text(body: [λατρευτός], 
+                                    hyphenate: true) }, 
+                       hyphenate: true, 
+                       lang: "el")), 
+       columns: (50.0pt, 50.0pt)), 
+  parbreak() }
diff --git a/test/out/text/hyphenate-01.out b/test/out/text/hyphenate-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/hyphenate-01.out
@@ -0,0 +1,201 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/hyphenate-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/hyphenate-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/hyphenate-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/hyphenate-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 110.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/hyphenate-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean True)) ])
+, ParBreak
+, Text "Welcome"
+, Space
+, Text "to"
+, Space
+, Text "wonderful"
+, Space
+, Text "experiences"
+, Text "."
+, Space
+, HardBreak
+, Text "Welcome"
+, Space
+, Text "to"
+, Space
+, RawInline "wonderful"
+, Space
+, Text "experiences"
+, Text "."
+, Space
+, HardBreak
+, Text "Welcome"
+, Space
+, Text "to"
+, Space
+, Code
+    "test/typ/text/hyphenate-01.typ"
+    ( line 8 , column 13 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean False))
+       , BlockArg [ Text "wonderful" ]
+       ])
+, Space
+, Text "experiences"
+, Text "."
+, Space
+, HardBreak
+, Text "Welcome"
+, Space
+, Text "to"
+, Space
+, Text "wonde"
+, Code
+    "test/typ/text/hyphenate-01.typ"
+    ( line 9 , column 18 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean False))
+       , BlockArg [ Text "rf" ]
+       ])
+, Text "ul"
+, Space
+, Text "experiences"
+, Text "."
+, Space
+, HardBreak
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/hyphenate-01.typ"
+    ( line 12 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean False)) ])
+, SoftBreak
+, Text "Welcome"
+, Space
+, Text "to"
+, Space
+, Text "wonderful"
+, Space
+, Text "experiences"
+, Text "."
+, Space
+, HardBreak
+, Text "Welcome"
+, Space
+, Text "to"
+, Space
+, Text "wo"
+, Code
+    "test/typ/text/hyphenate-01.typ"
+    ( line 14 , column 15 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean True))
+       , BlockArg [ Text "nd" ]
+       ])
+, Text "erful"
+, Space
+, Text "experiences"
+, Text "."
+, Space
+, HardBreak
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Welcome to wonderful experiences. ], 
+       hyphenate: true), 
+  linebreak(), 
+  text(body: [Welcome to ], 
+       hyphenate: true), 
+  raw(block: false, 
+      lang: none, 
+      text: "wonderful"), 
+  text(body: [ experiences. ], 
+       hyphenate: true), 
+  linebreak(), 
+  text(body: [Welcome to ], 
+       hyphenate: true), 
+  text(body: text(body: [wonderful], 
+                  hyphenate: true), 
+       hyphenate: false), 
+  text(body: [ experiences. ], 
+       hyphenate: true), 
+  linebreak(), 
+  text(body: [Welcome to wonde], 
+       hyphenate: true), 
+  text(body: text(body: [rf], 
+                  hyphenate: true), 
+       hyphenate: false), 
+  text(body: [ul experiences. ], 
+       hyphenate: true), 
+  linebreak(), 
+  text(body: [
+], 
+       hyphenate: true), 
+  text(body: [
+Welcome to wonderful experiences. ], 
+       hyphenate: false), 
+  linebreak(), 
+  text(body: [Welcome to wo], 
+       hyphenate: false), 
+  text(body: text(body: [nd], 
+                  hyphenate: false), 
+       hyphenate: true), 
+  text(body: [erful experiences. ], 
+       hyphenate: false), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/text/hyphenate-02.out b/test/out/text/hyphenate-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/hyphenate-02.out
@@ -0,0 +1,83 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/hyphenate-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/hyphenate-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/hyphenate-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/hyphenate-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 80.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/hyphenate-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "It"
+, Quote '\''
+, Text "s"
+, Space
+, Text "a"
+, Space
+, Code
+    "test/typ/text/hyphenate-02.typ"
+    ( line 5 , column 9 )
+    (FuncCall (Ident (Identifier "emph")) [ BlockArg [ Text "Tree" ] ])
+, Text "beard"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+It’s a ], 
+       hyphenate: true), 
+  emph(body: text(body: [Tree], 
+                  hyphenate: true)), 
+  text(body: [beard.], 
+       hyphenate: true), 
+  parbreak() }
diff --git a/test/out/text/hyphenate-03.out b/test/out/text/hyphenate-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/hyphenate-03.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/hyphenate-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/hyphenate-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/hyphenate-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/hyphenate-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "de"))
+       , KeyValArg (Identifier "hyphenate") (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/hyphenate-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Times (Literal (Int 2)) (Array [ Literal (Numeric 20.0 Pt) ]))
+       , KeyValArg (Identifier "gutter") (Literal (Numeric 20.0 Pt))
+       , NormalArg (Block (Content [ Text "Barankauf" ]))
+       , NormalArg (Block (Content [ Text "Bar" , Shy , Text "ankauf" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       hyphenate: true, 
+       lang: "de"), 
+  grid(children: (text(body: [Barankauf], 
+                       hyphenate: true, 
+                       lang: "de"), 
+                  text(body: [Bar­ankauf], 
+                       hyphenate: true, 
+                       lang: "de")), 
+       columns: (20.0pt, 20.0pt), 
+       gutter: 20.0pt), 
+  parbreak() }
diff --git a/test/out/text/hyphenate-04.out b/test/out/text/hyphenate-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/hyphenate-04.out
@@ -0,0 +1,85 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/hyphenate-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/hyphenate-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/hyphenate-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Comment
+, Comment
+, Code
+    "test/typ/text/hyphenate-04.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/hyphenate-04.typ"
+    ( line 7 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/text/hyphenate-04.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "h")) [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, Space
+, Text "networks,"
+, Space
+, Text "the"
+, Space
+, Text "rest"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       hyphenate: true), 
+  h(amount: 6.0pt), 
+  text(body: [ networks, the rest.], 
+       hyphenate: true), 
+  parbreak() }
diff --git a/test/out/text/lang-00.out b/test/out/text/lang-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-00.out
@@ -0,0 +1,90 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/lang-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/lang-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/lang-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/lang-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "hyphenate") (Literal (Boolean True)) ])
+, SoftBreak
+, Code
+    "test/typ/text/lang-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Times (Literal (Int 2)) (Array [ Literal (Numeric 20.0 Pt) ]))
+       , KeyValArg (Identifier "gutter") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "text"))
+              [ KeyValArg (Identifier "lang") (Literal (String "en"))
+              , BlockArg [ Quote '"' , Text "Eingabeaufforderung" , Quote '"' ]
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "text"))
+              [ KeyValArg (Identifier "lang") (Literal (String "de"))
+              , BlockArg [ Quote '"' , Text "Eingabeaufforderung" , Quote '"' ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       hyphenate: true), 
+  grid(children: (text(body: text(body: [“Eingabeaufforderung”], 
+                                  hyphenate: true), 
+                       hyphenate: true, 
+                       lang: "en"), 
+                  text(body: text(body: [“Eingabeaufforderung”], 
+                                  hyphenate: true), 
+                       hyphenate: true, 
+                       lang: "de")), 
+       columns: (20.0pt, 20.0pt), 
+       gutter: 1.0fr), 
+  parbreak() }
diff --git a/test/out/text/lang-01.out b/test/out/text/lang-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-01.out
@@ -0,0 +1,93 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/lang-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/lang-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/lang-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/lang-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "Ubuntu")) ])
+, ParBreak
+, Comment
+, Comment
+, Comment
+, Comment
+, Text "\1041\1073"
+, SoftBreak
+, Code
+    "test/typ/text/lang-01.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "uk"))
+       , BlockArg [ Text "\1041\1073" ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/lang-01.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "sr"))
+       , BlockArg [ Text "\1041\1073" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Бб
+], 
+       font: "Ubuntu"), 
+  text(body: text(body: [Бб], 
+                  font: "Ubuntu"), 
+       font: "Ubuntu", 
+       lang: "uk"), 
+  text(body: [
+], 
+       font: "Ubuntu"), 
+  text(body: text(body: [Бб], 
+                  font: "Ubuntu"), 
+       font: "Ubuntu", 
+       lang: "sr"), 
+  parbreak() }
diff --git a/test/out/text/lang-02.out b/test/out/text/lang-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/lang-03.out b/test/out/text/lang-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/lang-04.out b/test/out/text/lang-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/lang-05.out b/test/out/text/lang-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/lang-with-region-00.out b/test/out/text/lang-with-region-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-with-region-00.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/lang-with-region-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/lang-with-region-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/lang-with-region-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/lang-with-region-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "zh")) ])
+, SoftBreak
+, Code
+    "test/typ/text/lang-with-region-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall (Ident (Identifier "outline")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], lang: "zh"), 
+  outline(), 
+  parbreak() }
diff --git a/test/out/text/lang-with-region-01.out b/test/out/text/lang-with-region-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-with-region-01.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/lang-with-region-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/lang-with-region-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/lang-with-region-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/lang-with-region-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "zh"))
+       , KeyValArg (Identifier "region") (Literal (String "XX"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/lang-with-region-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall (Ident (Identifier "outline")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       lang: "zh", 
+       region: "XX"), 
+  outline(), 
+  parbreak() }
diff --git a/test/out/text/lang-with-region-02.out b/test/out/text/lang-with-region-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lang-with-region-02.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/lang-with-region-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/lang-with-region-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/lang-with-region-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/lang-with-region-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "zh"))
+       , KeyValArg (Identifier "region") (Literal (String "TW"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/lang-with-region-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall (Ident (Identifier "outline")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       lang: "zh", 
+       region: "TW"), 
+  outline(), 
+  parbreak() }
diff --git a/test/out/text/linebreak-00.out b/test/out/text/linebreak-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-00.out
@@ -0,0 +1,57 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "a"
+, Space
+, Text "spaceexceedinglylongy"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [This is a spaceexceedinglylongy.]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-01.out b/test/out/text/linebreak-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-01.out
@@ -0,0 +1,53 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Supercalifragilisticexpialidocious"
+, Space
+, Text "Expialigoricmetrioxidation"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Supercalifragilisticexpialidocious Expialigoricmetrioxidation.]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-02.out b/test/out/text/linebreak-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-02.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "partly"
+, Space
+, Text "emp"
+, Code
+    "test/typ/text/linebreak-02.typ"
+    ( line 3 , column 20 )
+    (FuncCall (Ident (Identifier "emph")) [ BlockArg [ Text "has" ] ])
+, Text "ized"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [This is partly emp]), 
+  emph(body: text(body: [has])), 
+  text(body: [ized.]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-03.out b/test/out/text/linebreak-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-03.out
@@ -0,0 +1,58 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Text "Hard"
+, Space
+, Code
+    "test/typ/text/linebreak-03.typ"
+    ( line 2 , column 7 )
+    (FuncCall (Ident (Identifier "linebreak")) [])
+, Space
+, Text "break"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+Hard ]), 
+  linebreak(), 
+  text(body: [ break.]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-04.out b/test/out/text/linebreak-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-04.out
@@ -0,0 +1,64 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Hard"
+, Space
+, Text "break"
+, Space
+, Text "directly"
+, Space
+, Text "after"
+, Space
+, HardBreak
+, Text "normal"
+, Space
+, Text "break"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Hard break directly after ]), 
+  linebreak(), 
+  text(body: [normal break.]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-05.out b/test/out/text/linebreak-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-05.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Two"
+, Space
+, Text "consecutive"
+, Space
+, HardBreak
+, HardBreak
+, Text "breaks"
+, Space
+, Text "and"
+, Space
+, Text "three"
+, Space
+, HardBreak
+, HardBreak
+, Text "more"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Two consecutive ]), 
+  linebreak(), 
+  linebreak(), 
+  text(body: [breaks and three ]), 
+  linebreak(), 
+  linebreak(), 
+  text(body: [more.]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-06.out b/test/out/text/linebreak-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-06.out
@@ -0,0 +1,57 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Trailing"
+, Space
+, Text "break"
+, Space
+, HardBreak
+, HardBreak
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Trailing break ]), 
+  linebreak(), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/text/linebreak-07.out b/test/out/text/linebreak-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-07.out
@@ -0,0 +1,113 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/linebreak-07.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "With"
+, Space
+, Text "a"
+, Space
+, Text "soft"
+, Space
+, Code
+    "test/typ/text/linebreak-07.typ"
+    ( line 4 , column 14 )
+    (FuncCall
+       (Ident (Identifier "linebreak"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "break"
+, Space
+, Text "you"
+, Space
+, Text "can"
+, Space
+, Text "force"
+, Space
+, Text "a"
+, Space
+, Text "break"
+, Space
+, Text "without"
+, Space
+, Code
+    "test/typ/text/linebreak-07.typ"
+    ( line 5 , column 38 )
+    (FuncCall
+       (Ident (Identifier "linebreak"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True)) ])
+, SoftBreak
+, Text "breaking"
+, Space
+, Text "justification"
+, Text "."
+, Space
+, Code
+    "test/typ/text/linebreak-07.typ"
+    ( line 6 , column 26 )
+    (FuncCall
+       (Ident (Identifier "linebreak"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean False)) ])
+, SoftBreak
+, Text "Nice!"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+With a soft ]), 
+  linebreak(justify: true), 
+  text(body: [
+break you can force a break without ]), 
+  linebreak(justify: true), 
+  text(body: [
+breaking justification. ]), 
+  linebreak(justify: false), 
+  text(body: [
+Nice!]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-08.out b/test/out/text/linebreak-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-08.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-08.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-08.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-08.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "First"
+, Space
+, Text "part"
+, Comment
+, Text "Second"
+, Space
+, Text "part"
+, ParBreak
+, Comment
+, Text "First"
+, Space
+, Text "part"
+, Space
+, Comment
+, Text "Second"
+, Space
+, Text "part"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [First part]), 
+  text(body: [Second part]), 
+  parbreak(), 
+  text(body: [First part ]), 
+  text(body: [Second part]), 
+  parbreak() }
diff --git a/test/out/text/linebreak-obj-00.out b/test/out/text/linebreak-obj-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-obj-00.out
@@ -0,0 +1,97 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-obj-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-obj-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-obj-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/linebreak-obj-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 162.0 Pt)) ])
+, ParBreak
+, Text "They"
+, Space
+, Text "can"
+, Space
+, Text "look"
+, Space
+, Text "for"
+, Space
+, Text "the"
+, Space
+, Text "details"
+, Space
+, Text "in"
+, Space
+, Ref "netwok" (Literal Auto)
+, Text ","
+, SoftBreak
+, Text "which"
+, Space
+, Text "is"
+, Space
+, Text "the"
+, Space
+, Text "authoritative"
+, Space
+, Text "source"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/linebreak-obj-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "bibliography"))
+       [ NormalArg (Literal (String "/works.bib")) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [They can look for the details in ]), 
+  ref(supplement: auto, 
+      target: ), 
+  text(body: [,
+which is the authoritative source.]), 
+  parbreak(), 
+  bibliography(path: "/works.bib"), 
+  parbreak() }
diff --git a/test/out/text/linebreak-obj-01.out b/test/out/text/linebreak-obj-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/linebreak-obj-01.out
@@ -0,0 +1,198 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/linebreak-obj-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/linebreak-obj-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/linebreak-obj-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/linebreak-obj-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 85.0 Pt)) ])
+, ParBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text "."
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text "!"
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text "?"
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text ","
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text ";"
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text ":"
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text "-"
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text "\8211"
+, Space
+, HardBreak
+, Text "We"
+, Space
+, Text "prove"
+, Space
+, Equation False [ Text "1" , Text "<" , Text "2" ]
+, Text "\8212"
+, Space
+, HardBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [. ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [! ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [? ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [, ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [; ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [: ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [- ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [– ]), 
+  linebreak(), 
+  text(body: [We prove ]), 
+  math.equation(block: false, 
+                body: { text(body: [1]), 
+                        text(body: [<]), 
+                        text(body: [2]) }, 
+                numbering: none), 
+  text(body: [— ]), 
+  linebreak() }
diff --git a/test/out/text/lorem-00.out b/test/out/text/lorem-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lorem-00.out
@@ -0,0 +1,54 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/lorem-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/lorem-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/lorem-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/lorem-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 19)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.]), 
+  parbreak() }
diff --git a/test/out/text/lorem-01.out b/test/out/text/lorem-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lorem-01.out
@@ -0,0 +1,129 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/lorem-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/lorem-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/lorem-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/lorem-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/text/lorem-01.typ"
+    ( line 5 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "sentences")))
+              (FuncCall
+                 (FieldAccess
+                    (Ident (Identifier "map"))
+                    (FuncCall
+                       (FieldAccess
+                          (Ident (Identifier "filter"))
+                          (FuncCall
+                             (FieldAccess
+                                (Ident (Identifier "split"))
+                                (FuncCall
+                                   (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 59)) ]))
+                             [ NormalArg (Literal (String ".")) ]))
+                       [ NormalArg
+                           (FuncExpr
+                              [ NormalParam (Identifier "s") ]
+                              (Not (Equals (Ident (Identifier "s")) (Literal (String "")))))
+                       ]))
+                 [ NormalArg
+                     (FuncExpr
+                        [ NormalParam (Identifier "s") ]
+                        (Plus (Ident (Identifier "s")) (Literal (String "."))))
+                 ])
+          , Let (BasicBind (Just (Identifier "used"))) (Literal (Int 0))
+          , For
+              (BasicBind (Just (Identifier "s")))
+              (Ident (Identifier "sentences"))
+              (Block
+                 (CodeBlock
+                    [ If
+                        [ ( LessThan (Ident (Identifier "used")) (Literal (Int 2))
+                          , Block
+                              (CodeBlock
+                                 [ Assign
+                                     (Ident (Identifier "used"))
+                                     (Plus (Ident (Identifier "used")) (Literal (Int 1)))
+                                 ])
+                          )
+                        , ( Literal (Boolean True)
+                          , Block
+                              (CodeBlock
+                                 [ FuncCall (Ident (Identifier "parbreak")) []
+                                 , Assign
+                                     (Binding (BasicBind (Just (Identifier "used"))))
+                                     (Literal (Int 0))
+                                 ])
+                          )
+                        ]
+                    , FuncCall
+                        (FieldAccess (Ident (Identifier "trim")) (Ident (Identifier "s")))
+                        []
+                    , Block (Content [ Space ])
+                    ]))
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.], 
+       size: 8.0pt), 
+  text(body: [ ], size: 8.0pt), 
+  text(body: [Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.], 
+       size: 8.0pt), 
+  text(body: [ ], size: 8.0pt), 
+  parbreak(), 
+  text(body: [Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.], 
+       size: 8.0pt), 
+  text(body: [ ], size: 8.0pt), 
+  text(body: [Excepteur sint occaecat cupidatat non proident, sunt.], 
+       size: 8.0pt), 
+  text(body: [ ], size: 8.0pt), 
+  parbreak() }
diff --git a/test/out/text/lorem-02.out b/test/out/text/lorem-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/lorem-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/microtype-00.out b/test/out/text/microtype-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/microtype-00.out
@@ -0,0 +1,213 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/microtype-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/microtype-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/microtype-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/microtype-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 130.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 15.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/microtype-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "par"))
+       [ KeyValArg (Identifier "justify") (Literal (Boolean True))
+       , KeyValArg (Identifier "linebreaks") (Literal (String "simple"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/microtype-00.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "size") (Literal (Numeric 9.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/microtype-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Int 0))
+              ])
+       , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , BlockArg
+           [ SoftBreak
+           , Text "This"
+           , Space
+           , Text "is"
+           , Space
+           , Text "a"
+           , Space
+           , Text "little"
+           , Space
+           , Text "bit"
+           , Space
+           , Text "of"
+           , Space
+           , Text "text"
+           , Space
+           , Text "that"
+           , Space
+           , Text "builds"
+           , Space
+           , Text "up"
+           , Space
+           , Text "to"
+           , SoftBreak
+           , Text "hang"
+           , Text "-"
+           , Text "ing"
+           , Space
+           , Text "hyphens"
+           , Space
+           , Text "and"
+           , Space
+           , Text "dash"
+           , EmDash
+           , Text "es"
+           , Space
+           , Text "and"
+           , Space
+           , Text "then,"
+           , Space
+           , Text "you"
+           , Space
+           , Text "know,"
+           , SoftBreak
+           , Text "some"
+           , Space
+           , Text "punctuation"
+           , Space
+           , Text "in"
+           , Space
+           , Text "the"
+           , Space
+           , Text "margin"
+           , Text "."
+           , ParBreak
+           ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/microtype-00.typ"
+    ( line 13 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "he"))
+       , KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "PT Sans")
+              , Literal (String "Noto Serif Hebrew")
+              ])
+       ])
+, SoftBreak
+, Text "\1489\1504\1497\1497\1492"
+, Space
+, Text "\1504\1499\1493\1504\1492"
+, Space
+, Text "\1513\1500"
+, Space
+, Text "\1502\1513\1508\1496\1497\1501"
+, Space
+, Text "\1488\1512\1493\1499\1497\1501"
+, Space
+, Text "\1491\1493\1512\1513\1514"
+, Space
+, Text "\1497\1491\1506"
+, Space
+, Text "\1489\1513\1508\1492"
+, Text "."
+, Space
+, Text "\1488\1494"
+, Space
+, Text "\1489\1493\1488\1493"
+, Space
+, Text "\1504\1491\1489\1512"
+, Space
+, Text "\1506\1500"
+, Space
+, Text "\1502\1494\1490"
+, Space
+, Text "\1492\1488\1493\1493\1497\1512"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], size: 9.0pt), 
+  rect(body: { text(body: [
+This is a little bit of text that builds up to
+hang-ing hyphens and dash—es and then, you know,
+some punctuation in the margin.], 
+                    size: 9.0pt), 
+               parbreak() }, 
+       fill: rgb(0%,0%,0%,0%), 
+       inset: 0.0pt, 
+       width: 100%), 
+  parbreak(), 
+  text(body: [
+בנייה נכונה של משפטים ארוכים דורשת ידע בשפה. אז בואו נדבר על מזג האוויר.], 
+       font: ("PT Sans", 
+              "Noto Serif Hebrew"), 
+       lang: "he", 
+       size: 9.0pt), 
+  parbreak() }
diff --git a/test/out/text/microtype-01.out b/test/out/text/microtype-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/microtype-01.out
@@ -0,0 +1,76 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/microtype-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/microtype-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/microtype-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/microtype-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/microtype-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "end")) ])
+, SoftBreak
+, Code
+    "test/typ/text/microtype-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl")) ])
+, SoftBreak
+, Text ":"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+:], dir: rtl), 
+  parbreak() }
diff --git a/test/out/text/quotes-00.out b/test/out/text/quotes-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/quotes-00.out
@@ -0,0 +1,500 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/quotes-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/quotes-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/quotes-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 250.0 Pt)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "en")) ])
+, SoftBreak
+, Quote '"'
+, Text "The"
+, Space
+, Text "horse"
+, Space
+, Text "eats"
+, Space
+, Text "no"
+, Space
+, Text "cucumber"
+, Space
+, Text "salad"
+, Quote '"'
+, Space
+, Text "was"
+, Space
+, Text "the"
+, Space
+, Text "first"
+, Space
+, Text "sentence"
+, Space
+, Text "ever"
+, Space
+, Text "uttered"
+, Space
+, Text "on"
+, Space
+, Text "the"
+, Space
+, Quote '\''
+, Text "telephone"
+, Text "."
+, Quote '\''
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 8 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "de")) ])
+, SoftBreak
+, Quote '"'
+, Text "Das"
+, Space
+, Text "Pferd"
+, Space
+, Text "frisst"
+, Space
+, Text "keinen"
+, Space
+, Text "Gurkensalat"
+, Quote '"'
+, Space
+, Text "war"
+, Space
+, Text "der"
+, Space
+, Text "erste"
+, Space
+, Text "jemals"
+, Space
+, Text "am"
+, Space
+, Quote '\''
+, Text "Fernsprecher"
+, Quote '\''
+, Space
+, Text "gesagte"
+, Space
+, Text "Satz"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 11 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "de"))
+       , KeyValArg (Identifier "region") (Literal (String "CH"))
+       ])
+, SoftBreak
+, Quote '"'
+, Text "Das"
+, Space
+, Text "Pferd"
+, Space
+, Text "frisst"
+, Space
+, Text "keinen"
+, Space
+, Text "Gurkensalat"
+, Quote '"'
+, Space
+, Text "war"
+, Space
+, Text "der"
+, Space
+, Text "erste"
+, Space
+, Text "jemals"
+, Space
+, Text "am"
+, Space
+, Quote '\''
+, Text "Fernsprecher"
+, Quote '\''
+, Space
+, Text "gesagte"
+, Space
+, Text "Satz"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 14 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "es"))
+       , KeyValArg (Identifier "region") (Literal None)
+       ])
+, SoftBreak
+, Quote '"'
+, Text "El"
+, Space
+, Text "caballo"
+, Space
+, Text "no"
+, Space
+, Text "come"
+, Space
+, Text "ensalada"
+, Space
+, Text "de"
+, Space
+, Text "pepino"
+, Quote '"'
+, Space
+, Text "fue"
+, Space
+, Text "la"
+, Space
+, Text "primera"
+, Space
+, Text "frase"
+, Space
+, Text "pronunciada"
+, Space
+, Text "por"
+, Space
+, Quote '\''
+, Text "tel\233fono"
+, Quote '\''
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 17 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "es"))
+       , KeyValArg (Identifier "region") (Literal (String "MX"))
+       ])
+, SoftBreak
+, Quote '"'
+, Text "El"
+, Space
+, Text "caballo"
+, Space
+, Text "no"
+, Space
+, Text "come"
+, Space
+, Text "ensalada"
+, Space
+, Text "de"
+, Space
+, Text "pepino"
+, Quote '"'
+, Space
+, Text "fue"
+, Space
+, Text "la"
+, Space
+, Text "primera"
+, Space
+, Text "frase"
+, Space
+, Text "pronunciada"
+, Space
+, Text "por"
+, Space
+, Quote '\''
+, Text "tel\233fono"
+, Quote '\''
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 20 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "fr"))
+       , KeyValArg (Identifier "region") (Literal None)
+       ])
+, SoftBreak
+, Quote '"'
+, Text "Le"
+, Space
+, Text "cheval"
+, Space
+, Text "ne"
+, Space
+, Text "mange"
+, Space
+, Text "pas"
+, Space
+, Text "de"
+, Space
+, Text "salade"
+, Space
+, Text "de"
+, Space
+, Text "concombres"
+, Quote '"'
+, Space
+, Text "est"
+, Space
+, Text "la"
+, Space
+, Text "premi\232re"
+, Space
+, Text "phrase"
+, Space
+, Text "jamais"
+, Space
+, Text "prononc\233e"
+, Space
+, Text "au"
+, Space
+, Quote '\''
+, Text "t\233l\233phone"
+, Quote '\''
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 23 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "fi")) ])
+, SoftBreak
+, Quote '"'
+, Text "Hevonen"
+, Space
+, Text "ei"
+, Space
+, Text "sy\246"
+, Space
+, Text "kurkkusalaattia"
+, Quote '"'
+, Space
+, Text "oli"
+, Space
+, Text "ensimm\228inen"
+, Space
+, Text "koskaan"
+, Space
+, Quote '\''
+, Text "puhelimessa"
+, Quote '\''
+, Space
+, Text "lausuttu"
+, Space
+, Text "lause"
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 26 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "he")) ])
+, SoftBreak
+, Quote '"'
+, Text "\1492\1505\1493\1505"
+, Space
+, Text "\1500\1488"
+, Space
+, Text "\1488\1493\1499\1500"
+, Space
+, Text "\1505\1500\1496"
+, Space
+, Text "\1502\1500\1508\1508\1493\1504\1497\1501"
+, Quote '"'
+, Space
+, Text "\1492\1497\1492"
+, Space
+, Text "\1492\1502\1513\1508\1496"
+, Space
+, Text "\1492\1492\1512\1488\1513\1493\1503"
+, Space
+, Text "\1513\1504\1488\1502\1512"
+, Space
+, Text "\1489"
+, Space
+, Quote '\''
+, Text "\1496\1500\1508\1493\1503"
+, Quote '\''
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 29 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ro")) ])
+, SoftBreak
+, Quote '"'
+, Text "Calul"
+, Space
+, Text "nu"
+, Space
+, Text "m\259n\226nc\259"
+, Space
+, Text "salat\259"
+, Space
+, Text "de"
+, Space
+, Text "castrave\539i"
+, Quote '"'
+, Space
+, Text "a"
+, Space
+, Text "fost"
+, Space
+, Text "prima"
+, Space
+, Text "propozi\539ie"
+, Space
+, Text "rostit\259"
+, Space
+, Text "vreodat\259"
+, Space
+, Text "la"
+, Space
+, Quote '\''
+, Text "telefon"
+, Quote '\''
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-00.typ"
+    ( line 32 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "ru")) ])
+, SoftBreak
+, Quote '"'
+, Text "\1051\1086\1096\1072\1076\1100"
+, Space
+, Text "\1085\1077"
+, Space
+, Text "\1077\1089\1090"
+, Space
+, Text "\1089\1072\1083\1072\1090"
+, Space
+, Text "\1080\1079"
+, Space
+, Text "\1086\1075\1091\1088\1094\1086\1074"
+, Quote '"'
+, Space
+, Text "-"
+, Space
+, Text "\1101\1090\1086"
+, Space
+, Text "\1073\1099\1083\1072"
+, Space
+, Text "\1087\1077\1088\1074\1072\1103"
+, Space
+, Text "\1092\1088\1072\1079\1072,"
+, Space
+, Text "\1089\1082\1072\1079\1072\1085\1085\1072\1103"
+, Space
+, Text "\1087\1086"
+, Space
+, Quote '\''
+, Text "\1090\1077\1083\1077\1092\1086\1085\1091"
+, Quote '\''
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+“The horse eats no cucumber salad” was the first sentence ever uttered on the ‘telephone.’], 
+       lang: "en"), 
+  parbreak(), 
+  text(body: [
+“Das Pferd frisst keinen Gurkensalat” war der erste jemals am ‘Fernsprecher” gesagte Satz.], 
+       lang: "de"), 
+  parbreak(), 
+  text(body: [
+“Das Pferd frisst keinen Gurkensalat” war der erste jemals am ‘Fernsprecher” gesagte Satz.], 
+       lang: "de", 
+       region: "CH"), 
+  parbreak(), 
+  text(body: [
+“El caballo no come ensalada de pepino” fue la primera frase pronunciada por ‘teléfono’.], 
+       lang: "es", 
+       region: none), 
+  parbreak(), 
+  text(body: [
+“El caballo no come ensalada de pepino” fue la primera frase pronunciada por ‘teléfono’.], 
+       lang: "es", 
+       region: "MX"), 
+  parbreak(), 
+  text(body: [
+“Le cheval ne mange pas de salade de concombres” est la première phrase jamais prononcée au ‘téléphone’.], 
+       lang: "fr", 
+       region: none), 
+  parbreak(), 
+  text(body: [
+“Hevonen ei syö kurkkusalaattia” oli ensimmäinen koskaan ‘puhelimessa” lausuttu lause.], 
+       lang: "fi", 
+       region: none), 
+  parbreak(), 
+  text(body: [
+“הסוס לא אוכל סלט מלפפונים” היה המשפט ההראשון שנאמר ב ‘טלפון’.], 
+       lang: "he", 
+       region: none), 
+  parbreak(), 
+  text(body: [
+“Calul nu mănâncă salată de castraveți” a fost prima propoziție rostită vreodată la ‘telefon’.], 
+       lang: "ro", 
+       region: none), 
+  parbreak(), 
+  text(body: [
+“Лошадь не ест салат из огурцов” - это была первая фраза, сказанная по ‘телефону’.], 
+       lang: "ru", 
+       region: none), 
+  parbreak() }
diff --git a/test/out/text/quotes-01.out b/test/out/text/quotes-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/quotes-01.out
@@ -0,0 +1,51 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/quotes-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/quotes-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/quotes-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Quote '"'
+, Quote '"'
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [””]), 
+  parbreak() }
diff --git a/test/out/text/quotes-02.out b/test/out/text/quotes-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/quotes-02.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/quotes-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/quotes-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/quotes-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "The"
+, Space
+, Text "5"
+, Quote '\''
+, Text "11"
+, Quote '"'
+, Space
+, Quote '\''
+, Text "quick"
+, Quote '\''
+, Space
+, Text "brown"
+, Space
+, Text "fox"
+, Space
+, Text "jumps"
+, Space
+, Text "over"
+, Space
+, Text "the"
+, Space
+, Quote '"'
+, Text "lazy"
+, Quote '"'
+, Space
+, Text "dog"
+, Quote '\''
+, Text "s"
+, Space
+, Text "ear"
+, Text "."
+, ParBreak
+, Text "He"
+, Space
+, Text "said"
+, Space
+, Quote '"'
+, Text "I"
+, Quote '\''
+, Text "m"
+, Space
+, Text "a"
+, Space
+, Text "big"
+, Space
+, Text "fella"
+, Text "."
+, Quote '"'
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [The 5’11” ‘quick” brown fox jumps over the “lazy” dog’s ear.]), 
+  parbreak(), 
+  text(body: [He said “I’m a big fella.”]), 
+  parbreak() }
diff --git a/test/out/text/quotes-03.out b/test/out/text/quotes-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/quotes-03.out
@@ -0,0 +1,80 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/quotes-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/quotes-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/quotes-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "The"
+, Space
+, Text "5"
+, Text "'"
+, Text "11"
+, Text "\""
+, Space
+, Quote '\''
+, Text "quick"
+, Text "'"
+, Space
+, Text "brown"
+, Space
+, Text "fox"
+, Space
+, Text "jumps"
+, Space
+, Text "over"
+, Space
+, Text "the"
+, Space
+, Text "\""
+, Text "lazy"
+, Quote '"'
+, Space
+, Text "dog"
+, Text "'"
+, Text "s"
+, Space
+, Text "ear"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [The 5'11" ‘quick' brown fox jumps over the "lazy” dog's ear.]), 
+  parbreak() }
diff --git a/test/out/text/quotes-04.out b/test/out/text/quotes-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/quotes-04.out
@@ -0,0 +1,100 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/quotes-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/quotes-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/quotes-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "He"
+, Quote '\''
+, Text "s"
+, Space
+, Text "told"
+, Space
+, Text "some"
+, Space
+, Text "books"
+, Space
+, Text "contain"
+, Space
+, Text "questionable"
+, Space
+, Quote '"'
+, Text "example"
+, Space
+, Text "text"
+, Quote '"'
+, Text "."
+, ParBreak
+, Code
+    "test/typ/text/quotes-04.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "smartquote"))
+       [ KeyValArg (Identifier "enabled") (Literal (Boolean False)) ])
+, SoftBreak
+, Text "He"
+, Quote '\''
+, Text "s"
+, Space
+, Text "told"
+, Space
+, Text "some"
+, Space
+, Text "books"
+, Space
+, Text "contain"
+, Space
+, Text "questionable"
+, Space
+, Quote '"'
+, Text "example"
+, Space
+, Text "text"
+, Quote '"'
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [He’s told some books contain questionable “example text”.]), 
+  parbreak(), 
+  text(body: [
+He’s told some books contain questionable “example text”.]), 
+  parbreak() }
diff --git a/test/out/text/quotes-05.out b/test/out/text/quotes-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/quotes-05.out
@@ -0,0 +1,128 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/quotes-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/quotes-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/quotes-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Quote '"'
+, Text "She"
+, Space
+, Text "suddenly"
+, Space
+, Text "started"
+, Space
+, Text "speaking"
+, Space
+, Text "french"
+, Text ":"
+, Space
+, Code
+    "test/typ/text/quotes-05.typ"
+    ( line 3 , column 41 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "lang") (Literal (String "fr"))
+       , BlockArg
+           [ Quote '\''
+           , Text "Je"
+           , Space
+           , Text "suis"
+           , Space
+           , Text "une"
+           , Space
+           , Text "banane"
+           , Text "."
+           , Quote '\''
+           ]
+       ])
+, Quote '"'
+, Space
+, Text "Roman"
+, Space
+, Text "told"
+, Space
+, Text "me"
+, Text "."
+, ParBreak
+, Text "Some"
+, Space
+, Text "people"
+, Quote '\''
+, Text "s"
+, Space
+, Text "thought"
+, Space
+, Text "on"
+, Space
+, Text "this"
+, Space
+, Text "would"
+, Space
+, Text "be"
+, Space
+, Code
+    "test/typ/text/quotes-05.typ"
+    ( line 5 , column 41 )
+    (Block
+       (Content
+          [ Code
+              "test/typ/text/quotes-05.typ"
+              ( line 5 , column 43 )
+              (Set
+                 (Ident (Identifier "smartquote"))
+                 [ KeyValArg (Identifier "enabled") (Literal (Boolean False)) ])
+          , Space
+          , Quote '"'
+          , Text "strange"
+          , Text "."
+          , Quote '"'
+          ]))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [“She suddenly started speaking french: ]), 
+  text(body: text(body: [‘Je suis une banane.’]), 
+       lang: "fr"), 
+  text(body: [” Roman told me.]), 
+  parbreak(), 
+  text(body: [Some people’s thought on this would be ]), 
+  text(body: [ “strange.”]), 
+  parbreak() }
diff --git a/test/out/text/raw-00.out b/test/out/text/raw-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-00.out
@@ -0,0 +1,56 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, RawInline "A"
+, RawInline "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  raw(block: false, 
+      lang: none, 
+      text: "A"), 
+  raw(block: false, 
+      lang: none, 
+      text: "B"), 
+  parbreak() }
diff --git a/test/out/text/raw-01.out b/test/out/text/raw-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-01.out
@@ -0,0 +1,60 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, RawBlock "typ" "#let x = 1"
+, Space
+, HardBreak
+, RawBlock "typ" "#f(1)"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  raw(block: true, 
+      lang: "typ", 
+      text: "#let x = 1"), 
+  text(body: [ ]), 
+  linebreak(), 
+  raw(block: true, 
+      lang: "typ", 
+      text: "#f(1)"), 
+  parbreak() }
diff --git a/test/out/text/raw-02.out b/test/out/text/raw-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-02.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Text "Text"
+, SoftBreak
+, RawBlock "rust" "fn code() {}\n"
+, SoftBreak
+, Text "Text"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Text
+]), 
+  raw(block: true, 
+      lang: "rust", 
+      text: "fn code() {}\n"), 
+  text(body: [
+Text]), 
+  parbreak() }
diff --git a/test/out/text/raw-03.out b/test/out/text/raw-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-03.out
@@ -0,0 +1,52 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, RawBlock "" "```backticks```\n"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  raw(block: true, 
+      lang: none, 
+      text: "```backticks```\n"), 
+  parbreak() }
diff --git a/test/out/text/raw-04.out b/test/out/text/raw-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-04.out
@@ -0,0 +1,121 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Text "The"
+, Space
+, Text "keyword"
+, Space
+, RawBlock "rust" "let"
+, Text "."
+, ParBreak
+, Comment
+, Text "("
+, RawInline ""
+, Text ")"
+, Space
+, HardBreak
+, Text "("
+, RawInline " untrimmed "
+, Text ")"
+, Space
+, HardBreak
+, Text "("
+, RawBlock "" "trimmed` "
+, Text ")"
+, Space
+, HardBreak
+, Text "("
+, RawBlock "" "trimmed "
+, Text ")"
+, Space
+, HardBreak
+, Text "("
+, RawBlock "" "trimmed"
+, Text ")"
+, Space
+, HardBreak
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [The keyword ]), 
+  raw(block: true, 
+      lang: "rust", 
+      text: "let"), 
+  text(body: [.]), 
+  parbreak(), 
+  text(body: [(]), 
+  raw(block: false, 
+      lang: none, 
+      text: ""), 
+  text(body: [) ]), 
+  linebreak(), 
+  text(body: [(]), 
+  raw(block: false, 
+      lang: none, 
+      text: " untrimmed "), 
+  text(body: [) ]), 
+  linebreak(), 
+  text(body: [(]), 
+  raw(block: true, 
+      lang: none, 
+      text: "trimmed` "), 
+  text(body: [) ]), 
+  linebreak(), 
+  text(body: [(]), 
+  raw(block: true, 
+      lang: none, 
+      text: "trimmed "), 
+  text(body: [) ]), 
+  linebreak(), 
+  text(body: [(]), 
+  raw(block: true, 
+      lang: none, 
+      text: "trimmed"), 
+  text(body: [) ]), 
+  linebreak(), 
+  parbreak() }
diff --git a/test/out/text/raw-05.out b/test/out/text/raw-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-05.out
@@ -0,0 +1,52 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, RawInline "rust let"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  raw(block: false, 
+      lang: none, 
+      text: "rust let"), 
+  parbreak() }
diff --git a/test/out/text/raw-06.out b/test/out/text/raw-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-06.out
@@ -0,0 +1,54 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Space
+, RawBlock "" "  A\n        B\n       C\n     "
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [ ]), 
+  raw(block: true, 
+      lang: none, 
+      text: "  A\n        B\n       C\n     "), 
+  parbreak() }
diff --git a/test/out/text/raw-07.out b/test/out/text/raw-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-07.out
@@ -0,0 +1,63 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/raw-07.typ"
+    ( line 3 , column 2 )
+    (Show
+       (Just (Ident (Identifier "raw")))
+       (Set
+          (Ident (Identifier "text"))
+          [ KeyValArg (Identifier "font") (Literal (String "Roboto")) ]))
+, SoftBreak
+, RawInline "Roboto"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  raw(block: false, 
+      lang: none, 
+      text: "Roboto"), 
+  parbreak() }
diff --git a/test/out/text/raw-08.out b/test/out/text/raw-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/raw-align-00.out b/test/out/text/raw-align-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-align-00.out
@@ -0,0 +1,98 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-align-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-align-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-align-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/raw-align-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center")) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-align-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-align-00.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/text/raw-align-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+, ParBreak
+, RawBlock
+    "py"
+    "def something(x):\n  return x\n\na = 342395823859823958329\nb = 324923\n"
+, ParBreak
+, Code
+    "test/typ/text/raw-align-00.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut], 
+       size: 6.0pt), 
+  parbreak(), 
+  raw(block: true, 
+      lang: "py", 
+      text: "def something(x):\n  return x\n\na = 342395823859823958329\nb = 324923\n"), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut], 
+       size: 6.0pt), 
+  parbreak() }
diff --git a/test/out/text/raw-align-01.out b/test/out/text/raw-align-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-align-01.out
@@ -0,0 +1,107 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-align-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-align-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-align-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/raw-align-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-align-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/text/raw-align-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-align-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "raw"))
+              [ KeyValArg (Identifier "lang") (Literal (String "typ"))
+              , KeyValArg (Identifier "block") (Literal (Boolean True))
+              , KeyValArg (Identifier "align") (Ident (Identifier "right"))
+              , NormalArg
+                  (Literal
+                     (String "#let f(x) = x\n#align(center, line(length: 1em))"))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-align-01.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "lorem")) [ NormalArg (Literal (Int 20)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut], 
+       size: 6.0pt), 
+  text(body: [
+], size: 6.0pt), 
+  align(alignment: center, 
+        body: raw(align: right, 
+                  block: true, 
+                  lang: "typ", 
+                  text: "#let f(x) = x\n#align(center, line(length: 1em))")), 
+  text(body: [
+], size: 6.0pt), 
+  text(body: [Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut], 
+       size: 6.0pt), 
+  parbreak() }
diff --git a/test/out/text/raw-align-02.out b/test/out/text/raw-align-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-align-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/raw-code-00.out b/test/out/text/raw-code-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-code-00.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-code-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-code-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-code-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, SoftBreak
+, RawBlock
+    "typ"
+    "= Chapter 1\n#lorem(100)\n\n#let hi = \"Hello World\"\n#show heading: emph\n"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], size: 6.0pt), 
+  raw(block: true, 
+      lang: "typ", 
+      text: "= Chapter 1\n#lorem(100)\n\n#let hi = \"Hello World\"\n#show heading: emph\n"), 
+  parbreak() }
diff --git a/test/out/text/raw-code-01.out b/test/out/text/raw-code-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-code-01.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-code-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-code-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-code-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, ParBreak
+, RawBlock
+    "rust"
+    "/// A carefully designed state machine.\n#[derive(Debug)]\nenum State<'a> { A(u8), B(&'a str) }\n\nfn advance(state: State<'_>) -> State<'_> {\n    unimplemented!(\"state machine\")\n}\n"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  raw(block: true, 
+      lang: "rust", 
+      text: "/// A carefully designed state machine.\n#[derive(Debug)]\nenum State<'a> { A(u8), B(&'a str) }\n\nfn advance(state: State<'_>) -> State<'_> {\n    unimplemented!(\"state machine\")\n}\n"), 
+  parbreak() }
diff --git a/test/out/text/raw-code-02.out b/test/out/text/raw-code-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-code-02.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-code-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-code-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-code-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-02.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, ParBreak
+, RawBlock "py" "import this\n\ndef hi():\n  print(\"Hi!\")\n"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  raw(block: true, 
+      lang: "py", 
+      text: "import this\n\ndef hi():\n  print(\"Hi!\")\n"), 
+  parbreak() }
diff --git a/test/out/text/raw-code-03.out b/test/out/text/raw-code-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-code-03.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-code-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-code-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-code-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-03.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, ParBreak
+, RawBlock
+    "cpp"
+    "#include <iostream>\n\nint main() {\n  std::cout << \"Hello, world!\";\n}\n"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  raw(block: true, 
+      lang: "cpp", 
+      text: "#include <iostream>\n\nint main() {\n  std::cout << \"Hello, world!\";\n}\n"), 
+  parbreak() }
diff --git a/test/out/text/raw-code-04.out b/test/out/text/raw-code-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/raw-code-04.out
@@ -0,0 +1,102 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/raw-code-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/raw-code-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/raw-code-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-04.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 180.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/text/raw-code-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 6.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/text/raw-code-04.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg
+           (Identifier "inset")
+           (Dict
+              [ ( Identifier "x" , Literal (Numeric 4.0 Pt) )
+              , ( Identifier "y" , Literal (Numeric 5.0 Pt) )
+              ])
+       , KeyValArg (Identifier "radius") (Literal (Numeric 4.0 Pt))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (Int 239))
+              , NormalArg (Literal (Int 241))
+              , NormalArg (Literal (Int 243))
+              ])
+       , BlockArg
+           [ SoftBreak
+           , RawBlock
+               "html"
+               "<!DOCTYPE html>\n  <html>\n    <head>\n      <meta charset=\"utf-8\">\n    </head>\n    <body>\n      <h1>Topic</h1>\n      <p>The Hypertext Markup Language.</p>\n      <script>\n        function foo(a, b) {\n          return a + b + \"string\";\n        }\n      </script>\n    </body>\n  </html>\n  "
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  rect(body: { text(body: [
+], 
+                    size: 6.0pt), 
+               raw(block: true, 
+                   lang: "html", 
+                   text: "<!DOCTYPE html>\n  <html>\n    <head>\n      <meta charset=\"utf-8\">\n    </head>\n    <body>\n      <h1>Topic</h1>\n      <p>The Hypertext Markup Language.</p>\n      <script>\n        function foo(a, b) {\n          return a + b + \"string\";\n        }\n      </script>\n    </body>\n  </html>\n  "), 
+               parbreak() }, 
+       fill: rgb(93%,94%,95%,100%), 
+       inset: (x: 4.0pt, y: 5.0pt), 
+       radius: 4.0pt), 
+  parbreak() }
diff --git a/test/out/text/shaping-00.out b/test/out/text/shaping-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/shaping-00.out
@@ -0,0 +1,71 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/shaping-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/shaping-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/shaping-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "ABC\2309\2346\2366\2352\2381\2335\2350\2375\2306\2335"
+, ParBreak
+, Comment
+, Text "\2309\2346\2366\2352\2381\2335\2350\2375\2306\2335"
+, ParBreak
+, Comment
+, Comment
+, Text "\2309"
+, Space
+, Text "\2346\2366"
+, Space
+, Text "\2352\2381"
+, Space
+, Text "\2335"
+, Space
+, Text "\2350\2375\2306"
+, Space
+, Text "\2335"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [ABCअपार्टमेंट]), 
+  parbreak(), 
+  text(body: [अपार्टमेंट]), 
+  parbreak(), 
+  text(body: [अ पा र् ट में ट]), 
+  parbreak() }
diff --git a/test/out/text/shaping-01.out b/test/out/text/shaping-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/shaping-01.out
@@ -0,0 +1,69 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/shaping-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/shaping-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/shaping-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/text/shaping-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "rtl"))
+       , KeyValArg
+           (Identifier "font") (Literal (String "Noto Serif Hebrew"))
+       ])
+, SoftBreak
+, HardBreak
+, Text "\1496"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       dir: rtl, 
+       font: "Noto Serif Hebrew"), 
+  linebreak(), 
+  text(body: [ט], 
+       dir: rtl, 
+       font: "Noto Serif Hebrew"), 
+  parbreak() }
diff --git a/test/out/text/shift-00.out b/test/out/text/shift-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/shift-00.out
@@ -0,0 +1,163 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/shift-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/shift-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/shift-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/shift-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 3))
+       , NormalArg (Block (Content [ Text "Typo" , Text "." ]))
+       , NormalArg (Block (Content [ Text "Fallb" , Text "." ]))
+       , NormalArg (Block (Content [ Text "Synth" ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "x"
+                 , Code
+                     "test/typ/text/shift-00.typ"
+                     ( line 5 , column 6 )
+                     (FuncCall (Ident (Identifier "super")) [ BlockArg [ Text "1" ] ])
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "x"
+                 , Code
+                     "test/typ/text/shift-00.typ"
+                     ( line 5 , column 20 )
+                     (FuncCall (Ident (Identifier "super")) [ BlockArg [ Text "5n" ] ])
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "x"
+                 , Code
+                     "test/typ/text/shift-00.typ"
+                     ( line 5 , column 35 )
+                     (FuncCall
+                        (Ident (Identifier "super"))
+                        [ BlockArg
+                            [ Text "2"
+                            , Space
+                            , Code
+                                "test/typ/text/shift-00.typ"
+                                ( line 5 , column 44 )
+                                (FuncCall
+                                   (Ident (Identifier "box"))
+                                   [ NormalArg
+                                       (FuncCall
+                                          (Ident (Identifier "square"))
+                                          [ KeyValArg (Identifier "size") (Literal (Numeric 6.0 Pt))
+                                          ])
+                                   ])
+                            ]
+                        ])
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "x"
+                 , Code
+                     "test/typ/text/shift-00.typ"
+                     ( line 6 , column 6 )
+                     (FuncCall (Ident (Identifier "sub")) [ BlockArg [ Text "1" ] ])
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "x"
+                 , Code
+                     "test/typ/text/shift-00.typ"
+                     ( line 6 , column 18 )
+                     (FuncCall (Ident (Identifier "sub")) [ BlockArg [ Text "5n" ] ])
+                 ]))
+       , NormalArg
+           (Block
+              (Content
+                 [ Text "x"
+                 , Code
+                     "test/typ/text/shift-00.typ"
+                     ( line 6 , column 31 )
+                     (FuncCall
+                        (Ident (Identifier "sub"))
+                        [ BlockArg
+                            [ Text "2"
+                            , Space
+                            , Code
+                                "test/typ/text/shift-00.typ"
+                                ( line 6 , column 38 )
+                                (FuncCall
+                                   (Ident (Identifier "box"))
+                                   [ NormalArg
+                                       (FuncCall
+                                          (Ident (Identifier "square"))
+                                          [ KeyValArg (Identifier "size") (Literal (Numeric 6.0 Pt))
+                                          ])
+                                   ])
+                            ]
+                        ])
+                 ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  table(children: (text(body: [Typo.]), 
+                   text(body: [Fallb.]), 
+                   text(body: [Synth]), 
+                   { text(body: [x]), 
+                     super(body: text(body: [1])) }, 
+                   { text(body: [x]), 
+                     super(body: text(body: [5n])) }, 
+                   { text(body: [x]), 
+                     super(body: { text(body: [2 ]), 
+                                   box(body: square(size: 6.0pt)) }) }, 
+                   { text(body: [x]), 
+                     sub(body: text(body: [1])) }, 
+                   { text(body: [x]), 
+                     sub(body: text(body: [5n])) }, 
+                   { text(body: [x]), 
+                     sub(body: { text(body: [2 ]), 
+                                 box(body: square(size: 6.0pt)) }) }), 
+        columns: 3), 
+  parbreak() }
diff --git a/test/out/text/shift-01.out b/test/out/text/shift-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/shift-01.out
@@ -0,0 +1,92 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/shift-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/shift-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/shift-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/shift-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "super"))
+       [ KeyValArg (Identifier "typographic") (Literal (Boolean False))
+       , KeyValArg
+           (Identifier "baseline") (Negated (Literal (Numeric 0.25 Em)))
+       , KeyValArg (Identifier "size") (Literal (Numeric 0.7 Em))
+       ])
+, SoftBreak
+, Text "n"
+, Code
+    "test/typ/text/shift-01.typ"
+    ( line 3 , column 3 )
+    (FuncCall (Ident (Identifier "super")) [ BlockArg [ Text "1" ] ])
+, Text ","
+, Space
+, Text "n"
+, Code
+    "test/typ/text/shift-01.typ"
+    ( line 3 , column 15 )
+    (FuncCall (Ident (Identifier "sub")) [ BlockArg [ Text "2" ] ])
+, Text ","
+, Space
+, Ellipsis
+, Space
+, Text "n"
+, Code
+    "test/typ/text/shift-01.typ"
+    ( line 3 , column 29 )
+    (FuncCall (Ident (Identifier "super")) [ BlockArg [ Text "N" ] ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+n]), 
+  super(baseline: -0.25em, 
+        body: text(body: [1]), 
+        size: 0.7em, 
+        typographic: false), 
+  text(body: [, n]), 
+  sub(body: text(body: [2])), 
+  text(body: [, … n]), 
+  super(baseline: -0.25em, 
+        body: text(body: [N]), 
+        size: 0.7em, 
+        typographic: false), 
+  parbreak() }
diff --git a/test/out/text/shift-02.out b/test/out/text/shift-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/shift-02.out
@@ -0,0 +1,155 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/shift-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/shift-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/shift-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/shift-02.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "underline"))
+       [ KeyValArg (Identifier "stroke") (Literal (Numeric 0.5 Pt))
+       , KeyValArg (Identifier "offset") (Literal (Numeric 0.15 Em))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/shift-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "underline"))
+       [ BlockArg
+           [ Text "The"
+           , Space
+           , Text "claim"
+           , Code
+               "test/typ/text/shift-02.typ"
+               ( line 3 , column 22 )
+               (FuncCall
+                  (Ident (Identifier "super"))
+                  [ BlockArg [ Text "[" , Text "4" , Text "]" ] ])
+           ]
+       ])
+, Space
+, Text "has"
+, Space
+, Text "been"
+, Space
+, Text "disputed"
+, Text "."
+, Space
+, HardBreak
+, Text "The"
+, Space
+, Text "claim"
+, Code
+    "test/typ/text/shift-02.typ"
+    ( line 4 , column 11 )
+    (FuncCall
+       (Ident (Identifier "super"))
+       [ BlockArg
+           [ Code
+               "test/typ/text/shift-02.typ"
+               ( line 4 , column 18 )
+               (FuncCall
+                  (Ident (Identifier "underline"))
+                  [ BlockArg [ Text "[" , Text "4" , Text "]" ] ])
+           ]
+       ])
+, Space
+, Text "has"
+, Space
+, Text "been"
+, Space
+, Text "disputed"
+, Text "."
+, Space
+, HardBreak
+, Text "It"
+, Space
+, Text "really"
+, Space
+, Text "has"
+, Space
+, Text "been"
+, Code
+    "test/typ/text/shift-02.typ"
+    ( line 5 , column 20 )
+    (FuncCall
+       (Ident (Identifier "super"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "box"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "text"))
+                     [ KeyValArg (Identifier "baseline") (Literal (Numeric 0.0 Pt))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "underline"))
+                            [ BlockArg [ Text "[" , Text "4" , Text "]" ] ])
+                     ])
+              ])
+       ])
+, Space
+, HardBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  underline(body: { text(body: [The claim]), 
+                    super(body: text(body: [[4]])) }, 
+            offset: 0.15em, 
+            stroke: 0.5pt), 
+  text(body: [ has been disputed. ]), 
+  linebreak(), 
+  text(body: [The claim]), 
+  super(body: underline(body: text(body: [[4]]), 
+                        offset: 0.15em, 
+                        stroke: 0.5pt)), 
+  text(body: [ has been disputed. ]), 
+  linebreak(), 
+  text(body: [It really has been]), 
+  super(body: box(body: text(baseline: 0.0pt, 
+                             body: underline(body: text(body: [[4]]), 
+                                             offset: 0.15em, 
+                                             stroke: 0.5pt)))), 
+  text(body: [ ]), 
+  linebreak() }
diff --git a/test/out/text/space-00.out b/test/out/text/space-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/space-00.out
@@ -0,0 +1,245 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/space-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/space-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/space-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 3 , column 3 )
+    (Let (BasicBind (Just (Identifier "x"))) (Literal (Int 1)))
+, Text "B"
+, Space
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 3 , column 17 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Int 1))
+       ])
+, Space
+, HardBreak
+, Text "C"
+, Space
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 4 , column 4 )
+    (Let (BasicBind (Just (Identifier "x"))) (Literal (Int 2)))
+, Text "D"
+, Space
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 4 , column 17 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg (Ident (Identifier "x"))
+       , NormalArg (Literal (Int 2))
+       ])
+, Space
+, HardBreak
+, Text "E"
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 5 , column 3 )
+    (If [ ( Literal (Boolean True) , Block (Content [ Text "F" ]) ) ])
+, Text "G"
+, Space
+, HardBreak
+, Text "H"
+, Space
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 6 , column 4 )
+    (If
+       [ ( Literal (Boolean True)
+         , Block (CodeBlock [ Literal (String "I") ])
+         )
+       ])
+, Space
+, Text "J"
+, Space
+, HardBreak
+, Text "K"
+, Space
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 7 , column 4 )
+    (If
+       [ ( Literal (Boolean True) , Block (Content [ Text "L" ]) )
+       , ( Literal (Boolean True) , Block (Content []) )
+       ])
+, Text "M"
+, Space
+, HardBreak
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 8 , column 2 )
+    (Let (BasicBind (Just (Identifier "c"))) (Literal (Boolean True)))
+, Space
+, Text "N"
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 8 , column 18 )
+    (While
+       (Ident (Identifier "c"))
+       (Block
+          (Content
+             [ Code
+                 "test/typ/text/space-00.typ"
+                 ( line 8 , column 28 )
+                 (Assign
+                    (Binding (BasicBind (Just (Identifier "c"))))
+                    (Literal (Boolean False)))
+             , Text "O"
+             ])))
+, Space
+, Text "P"
+, Space
+, HardBreak
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 9 , column 2 )
+    (Let (BasicBind (Just (Identifier "c"))) (Literal (Boolean True)))
+, Space
+, Text "Q"
+, Space
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 9 , column 19 )
+    (While
+       (Ident (Identifier "c"))
+       (Block
+          (CodeBlock
+             [ Assign
+                 (Binding (BasicBind (Just (Identifier "c"))))
+                 (Literal (Boolean False))
+             , Literal (String "R")
+             ])))
+, Space
+, Text "S"
+, Space
+, HardBreak
+, Text "T"
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 10 , column 3 )
+    (For
+       (BasicBind Nothing)
+       (Array [ Literal None ])
+       (Block (CodeBlock [ Literal (String "U") ])))
+, Text "V"
+, SoftBreak
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 11 , column 2 )
+    (Let (BasicBind (Just (Identifier "foo"))) (Literal (String "A")))
+, Space
+, HardBreak
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 12 , column 2 )
+    (Ident (Identifier "foo"))
+, Text "B"
+, Space
+, HardBreak
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 13 , column 2 )
+    (Ident (Identifier "foo"))
+, Space
+, Text "B"
+, Space
+, HardBreak
+, Code
+    "test/typ/text/space-00.typ"
+    ( line 14 , column 2 )
+    (Ident (Identifier "foo"))
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [B ]), 
+  text(body: [✅]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [C ]), 
+  text(body: [D ]), 
+  text(body: [✅]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [E]), 
+  text(body: [F]), 
+  text(body: [G ]), 
+  linebreak(), 
+  text(body: [H ]), 
+  text(body: [I]), 
+  text(body: [ J ]), 
+  linebreak(), 
+  text(body: [K ]), 
+  text(body: [L]), 
+  text(body: [M ]), 
+  linebreak(), 
+  text(body: [ N]), 
+  text(body: [O]), 
+  text(body: [ P ]), 
+  linebreak(), 
+  text(body: [ Q ]), 
+  text(body: [R]), 
+  text(body: [ S ]), 
+  linebreak(), 
+  text(body: [T]), 
+  text(body: [U]), 
+  text(body: [V
+]), 
+  text(body: [ ]), 
+  linebreak(), 
+  text(body: [A]), 
+  text(body: [B ]), 
+  linebreak(), 
+  text(body: [A]), 
+  text(body: [ B ]), 
+  linebreak(), 
+  text(body: [A]), 
+  text(body: [B]), 
+  parbreak() }
diff --git a/test/out/text/space-01.out b/test/out/text/space-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/space-01.out
@@ -0,0 +1,82 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/space-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/space-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/space-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Comment
+, Text "B"
+, Comment
+, Text "C"
+, Space
+, HardBreak
+, Text "A"
+, Space
+, Comment
+, Space
+, Text "B"
+, Comment
+, Text "C"
+, Space
+, HardBreak
+, Text "A"
+, Space
+, Comment
+, Text "B"
+, Comment
+, Space
+, Text "C"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [B]), 
+  text(body: [C ]), 
+  linebreak(), 
+  text(body: [A ]), 
+  text(body: [ B]), 
+  text(body: [C ]), 
+  linebreak(), 
+  text(body: [A ]), 
+  text(body: [B]), 
+  text(body: [ C]), 
+  parbreak() }
diff --git a/test/out/text/space-02.out b/test/out/text/space-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/space-02.out
@@ -0,0 +1,62 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/space-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/space-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/space-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Code
+    "test/typ/text/space-02.typ"
+    ( line 3 , column 3 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "IBM Plex Serif"))
+       , BlockArg [ Space ]
+       ])
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A]), 
+  text(body: text(body: [ ]), 
+       font: "IBM Plex Serif"), 
+  text(body: [B]), 
+  parbreak() }
diff --git a/test/out/text/space-03.out b/test/out/text/space-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/space-03.out
@@ -0,0 +1,63 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/space-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/space-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/space-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "Left"
+, Space
+, Code
+    "test/typ/text/space-03.typ"
+    ( line 3 , column 7 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "IBM Plex Serif"))
+       , BlockArg [ Text "Right" ]
+       ])
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [Left ]), 
+  text(body: text(body: [Right]), 
+       font: "IBM Plex Serif"), 
+  text(body: [.]), 
+  parbreak() }
diff --git a/test/out/text/space-04.out b/test/out/text/space-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/space-04.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/space-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/space-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/space-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/space-04.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , BlockArg
+           [ Text "A"
+           , Space
+           , HardBreak
+           , Text "B"
+           , Space
+           , HardBreak
+           , Text "C"
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  align(alignment: center, 
+        body: { text(body: [A ]), 
+                linebreak(), 
+                text(body: [B ]), 
+                linebreak(), 
+                text(body: [C]) }), 
+  parbreak() }
diff --git a/test/out/text/space-05.out b/test/out/text/space-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/space-05.out
@@ -0,0 +1,59 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/space-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/space-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/space-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Code
+    "test/typ/text/space-05.typ"
+    ( line 3 , column 3 )
+    (Literal (String "\n"))
+, Space
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A]), 
+  text(body: [
+]), 
+  text(body: [ B]), 
+  parbreak() }
diff --git a/test/out/text/space-06.out b/test/out/text/space-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/space-06.out
@@ -0,0 +1,55 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/space-06.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/space-06.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/space-06.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "LLLLLLLLLLLLLLLLLL"
+, Space
+, Text "R"
+, Space
+, Emph [ Text "L" ]
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [LLLLLLLLLLLLLLLLLL R ]), 
+  emph(body: text(body: [L])), 
+  parbreak() }
diff --git a/test/out/text/symbol-00.out b/test/out/text/symbol-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/symbol-00.out
@@ -0,0 +1,164 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/symbol-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/symbol-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/symbol-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 2 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "face")) (Ident (Identifier "emoji")))
+, SoftBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 3 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "old"))
+       (FieldAccess
+          (Ident (Identifier "woman")) (Ident (Identifier "emoji"))))
+, SoftBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 4 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "turtle")) (Ident (Identifier "emoji")))
+, ParBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 6 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font") (Literal (String "New Computer Modern Math"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 7 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "arrow")) (Ident (Identifier "sym")))
+, SoftBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 8 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "l"))
+       (FieldAccess
+          (Ident (Identifier "arrow")) (Ident (Identifier "sym"))))
+, SoftBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 9 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "squiggly"))
+       (FieldAccess
+          (Ident (Identifier "r"))
+          (FieldAccess
+             (Ident (Identifier "arrow")) (Ident (Identifier "sym")))))
+, SoftBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 10 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "hook"))
+       (FieldAccess
+          (Ident (Identifier "tr"))
+          (FieldAccess
+             (Ident (Identifier "arrow")) (Ident (Identifier "sym")))))
+, ParBreak
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 12 , column 2 )
+    (FieldAccess
+       (Ident (Identifier "r"))
+       (FieldAccess
+          (Ident (Identifier "arrow")) (Ident (Identifier "sym"))))
+, Text "this"
+, Space
+, Text "and"
+, Space
+, Text "this"
+, Code
+    "test/typ/text/symbol-00.typ"
+    ( line 12 , column 28 )
+    (FieldAccess
+       (Ident (Identifier "l"))
+       (FieldAccess
+          (Ident (Identifier "arrow")) (Ident (Identifier "sym"))))
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [😀]), 
+  text(body: [
+]), 
+  text(body: [👵]), 
+  text(body: [
+]), 
+  text(body: [🐢]), 
+  parbreak(), 
+  text(body: [
+], 
+       font: "New Computer Modern Math"), 
+  text(body: [→], 
+       font: "New Computer Modern Math"), 
+  text(body: [
+], 
+       font: "New Computer Modern Math"), 
+  text(body: [←], 
+       font: "New Computer Modern Math"), 
+  text(body: [
+], 
+       font: "New Computer Modern Math"), 
+  text(body: [⇝], 
+       font: "New Computer Modern Math"), 
+  text(body: [
+], 
+       font: "New Computer Modern Math"), 
+  text(body: [⤤], 
+       font: "New Computer Modern Math"), 
+  parbreak(), 
+  text(body: [→], 
+       font: "New Computer Modern Math"), 
+  text(body: [this and this], 
+       font: "New Computer Modern Math"), 
+  text(body: [←], 
+       font: "New Computer Modern Math"), 
+  parbreak() }
diff --git a/test/out/text/symbol-01.out b/test/out/text/symbol-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/symbol-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/text/tracking-spacing-00.out b/test/out/text/tracking-spacing-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/tracking-spacing-00.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/tracking-spacing-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/tracking-spacing-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/tracking-spacing-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/tracking-spacing-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "tracking") (Negated (Literal (Numeric 1.0e-2 Em)))
+       ])
+, SoftBreak
+, Text "I"
+, Space
+, Text "saw"
+, Space
+, Text "Zoe"
+, Space
+, Text "y\1243sterday,"
+, Space
+, Text "on"
+, Space
+, Text "the"
+, Space
+, Text "tram"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+I saw Zoe yӛsterday, on the tram.], 
+       tracking: -1.0e-2em), 
+  parbreak() }
diff --git a/test/out/text/tracking-spacing-01.out b/test/out/text/tracking-spacing-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/tracking-spacing-01.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/tracking-spacing-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/tracking-spacing-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/tracking-spacing-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "I"
+, Quote '\''
+, Text "m"
+, Space
+, Text "in"
+, Code
+    "test/typ/text/tracking-spacing-01.typ"
+    ( line 3 , column 8 )
+    (FuncCall
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "tracking")
+           (Plus (Literal (Numeric 0.15 Em)) (Literal (Numeric 1.5 Pt)))
+       , BlockArg [ Space , Text "spaace" ]
+       ])
+, Text "!"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [I’m in]), 
+  text(body: text(body: [ spaace]), 
+       tracking: 0.15em + 1.5pt), 
+  text(body: [!]), 
+  parbreak() }
diff --git a/test/out/text/tracking-spacing-02.out b/test/out/text/tracking-spacing-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/tracking-spacing-02.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/tracking-spacing-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/tracking-spacing-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/tracking-spacing-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/tracking-spacing-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "font")
+           (Array
+              [ Literal (String "PT Sans")
+              , Literal (String "Noto Serif Hebrew")
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/text/tracking-spacing-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "tracking") (Literal (Numeric 0.3 Em)) ])
+, SoftBreak
+, Text "\1496\1462\1511\1505\1496"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       font: ("PT Sans", 
+              "Noto Serif Hebrew")), 
+  text(body: [
+טֶקסט], 
+       font: ("PT Sans", 
+              "Noto Serif Hebrew"), 
+       tracking: 0.3em), 
+  parbreak() }
diff --git a/test/out/text/tracking-spacing-03.out b/test/out/text/tracking-spacing-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/tracking-spacing-03.out
@@ -0,0 +1,59 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/tracking-spacing-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/tracking-spacing-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/tracking-spacing-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/tracking-spacing-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "tracking") (Literal (Numeric 0.3 Em)) ])
+, SoftBreak
+, Text "\1575\1604\1606\1589"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+النص], 
+       tracking: 0.3em), 
+  parbreak() }
diff --git a/test/out/text/tracking-spacing-04.out b/test/out/text/tracking-spacing-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/tracking-spacing-04.out
@@ -0,0 +1,66 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/tracking-spacing-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/tracking-spacing-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/tracking-spacing-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/tracking-spacing-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Em)) ])
+, SoftBreak
+, Text "My"
+, Space
+, Text "text"
+, Space
+, Text "has"
+, Space
+, Text "spaces"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+My text has spaces.], 
+       spacing: 1.0em), 
+  parbreak() }
diff --git a/test/out/text/tracking-spacing-05.out b/test/out/text/tracking-spacing-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/text/tracking-spacing-05.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/text/tracking-spacing-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/text/tracking-spacing-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/text/tracking-spacing-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/text/tracking-spacing-05.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg
+           (Identifier "spacing")
+           (Plus (Literal (Numeric 50.0 Percent)) (Literal (Numeric 1.0 Pt)))
+       ])
+, SoftBreak
+, Text "This"
+, Space
+, Text "is"
+, Space
+, Text "tight"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+This is tight.], 
+       spacing: 1.0pt + 50%), 
+  parbreak() }
diff --git a/test/out/visualize/image-00.out b/test/out/visualize/image-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-00.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/image-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/image-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/image-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/image-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "image"))
+       [ NormalArg (Literal (String "test/assets/files/rhino.png")) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/image-00.typ"
+    ( line 8 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/image-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "image"))
+       [ NormalArg (Literal (String "test/assets/files/tiger.jpg")) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  image(path: "test/assets/files/rhino.png"), 
+  parbreak(), 
+  text(body: [
+]), 
+  image(path: "test/assets/files/tiger.jpg"), 
+  parbreak() }
diff --git a/test/out/visualize/image-01.out b/test/out/visualize/image-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-01.out
@@ -0,0 +1,122 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/image-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/image-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/image-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/image-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/rhino.png"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 30.0 Pt))
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/image-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/rhino.png"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 30.0 Pt))
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/image-01.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "image"))
+       [ NormalArg (Literal (String "test/assets/files/monkey.svg"))
+       , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "fit") (Literal (String "stretch"))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/image-01.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg
+           (Plus (Ident (Identifier "bottom")) (Ident (Identifier "right")))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 40.0 Pt))
+              , KeyValArg (Identifier "alt") (Literal (String "A tiger"))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  box(body: image(path: "test/assets/files/rhino.png", 
+                  width: 30.0pt)), 
+  text(body: [
+]), 
+  box(body: image(height: 30.0pt, 
+                  path: "test/assets/files/rhino.png")), 
+  parbreak(), 
+  image(fit: "stretch", 
+        height: 20.0pt, 
+        path: "test/assets/files/monkey.svg", 
+        width: 100%), 
+  parbreak(), 
+  align(alignment: Axes(right, bottom), 
+        body: image(alt: "A tiger", 
+                    path: "test/assets/files/tiger.jpg", 
+                    width: 40.0pt)), 
+  parbreak() }
diff --git a/test/out/visualize/image-02.out b/test/out/visualize/image-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-02.out
@@ -0,0 +1,115 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/image-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/image-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/image-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/image-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 50.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/image-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array
+              [ Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              , Literal (Numeric 1.0 Fr)
+              ])
+       , KeyValArg (Identifier "rows") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "gutter") (Literal (Numeric 3.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fit") (Literal (String "contain"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fit") (Literal (String "cover"))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/monkey.svg"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "fit") (Literal (String "stretch"))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  grid(children: (image(fit: "contain", 
+                        height: 100%, 
+                        path: "test/assets/files/tiger.jpg", 
+                        width: 100%), 
+                  image(fit: "cover", 
+                        height: 100%, 
+                        path: "test/assets/files/tiger.jpg", 
+                        width: 100%), 
+                  image(fit: "stretch", 
+                        height: 100%, 
+                        path: "test/assets/files/monkey.svg", 
+                        width: 100%)), 
+       columns: (1.0fr, 
+                 1.0fr, 
+                 1.0fr), 
+       gutter: 3.0pt, 
+       rows: 100%), 
+  parbreak() }
diff --git a/test/out/visualize/image-03.out b/test/out/visualize/image-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-03.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/image-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/image-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/image-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/image-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Text "Stuff"
+, SoftBreak
+, Code
+    "test/typ/visualize/image-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "image"))
+       [ NormalArg (Literal (String "test/assets/files/rhino.png")) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+Stuff
+]), 
+  image(path: "test/assets/files/rhino.png"), 
+  parbreak() }
diff --git a/test/out/visualize/image-04.out b/test/out/visualize/image-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-04.out
@@ -0,0 +1,70 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/image-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/image-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/image-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Text "A"
+, Space
+, Code
+    "test/typ/visualize/image-04.typ"
+    ( line 3 , column 4 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/tiger.jpg"))
+              , KeyValArg (Identifier "height") (Literal (Numeric 1.0 Cm))
+              , KeyValArg (Identifier "width") (Literal (Numeric 80.0 Percent))
+              ])
+       ])
+, Space
+, Text "B"
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [A ]), 
+  box(body: image(height: 1.0cm, 
+                  path: "test/assets/files/tiger.jpg", 
+                  width: 80%)), 
+  text(body: [ B]), 
+  parbreak() }
diff --git a/test/out/visualize/image-05.out b/test/out/visualize/image-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-05.out
@@ -0,0 +1,55 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/image-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/image-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/image-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/image-05.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "image"))
+       [ NormalArg (Literal (String "test/assets/files/pattern.svg")) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  image(path: "test/assets/files/pattern.svg"), 
+  parbreak() }
diff --git a/test/out/visualize/image-06.out b/test/out/visualize/image-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/image-07.out b/test/out/visualize/image-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-07.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/image-08.out b/test/out/visualize/image-08.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/image-08.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/line-00.out b/test/out/visualize/line-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/line-00.out
@@ -0,0 +1,139 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/line-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/line-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/line-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/visualize/line-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/line-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (Block
+              (CodeBlock
+                 [ Set
+                     (Ident (Identifier "line"))
+                     [ KeyValArg (Identifier "stroke") (Literal (Numeric 0.75 Pt)) ]
+                 , FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg
+                                (Identifier "end")
+                                (Array [ Literal (Numeric 0.4 Em) , Literal (Numeric 0.0 Pt) ])
+                            ])
+                     ]
+                 , FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg
+                                (Identifier "start")
+                                (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 0.4 Em) ])
+                            , KeyValArg
+                                (Identifier "end")
+                                (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 0.0 Pt) ])
+                            ])
+                     ]
+                 , FuncCall
+                     (Ident (Identifier "line"))
+                     [ KeyValArg
+                         (Identifier "end")
+                         (Array [ Literal (Numeric 0.6 Em) , Literal (Numeric 0.6 Em) ])
+                     ]
+                 ]))
+       ])
+, Space
+, Text "Hello"
+, Space
+, Code
+    "test/typ/visualize/line-00.typ"
+    ( line 8 , column 11 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "line"))
+              [ KeyValArg (Identifier "length") (Literal (Numeric 1.0 Cm)) ])
+       ])
+, Text "!"
+, ParBreak
+, Code
+    "test/typ/visualize/line-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg
+           (Identifier "end")
+           (Array
+              [ Literal (Numeric 70.0 Percent)
+              , Literal (Numeric 50.0 Percent)
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  box(body: { place(body: line(end: (0.4em, 
+                                     0.0pt), 
+                               stroke: 0.75pt)), 
+              place(body: line(end: (0.0pt, 
+                                     0.0pt), 
+                               start: (0.0pt, 0.4em), 
+                               stroke: 0.75pt)), 
+              line(end: (0.6em, 0.6em), 
+                   stroke: 0.75pt) }), 
+  text(body: [ Hello ]), 
+  box(body: line(length: 1.0cm)), 
+  text(body: [!]), 
+  parbreak(), 
+  line(end: (70%, 50%)), 
+  parbreak() }
diff --git a/test/out/visualize/line-01.out b/test/out/visualize/line-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/line-01.out
@@ -0,0 +1,1178 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/line-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/line-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/line-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/visualize/line-01.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (String "0B1026")) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/line-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "stroke") (Ident (Identifier "white")) ])
+, ParBreak
+, Code
+    "test/typ/visualize/line-01.typ"
+    ( line 7 , column 2 )
+    (LetFunc
+       (Identifier "star")
+       [ NormalParam (Identifier "size")
+       , SinkParam (Just (Identifier "args"))
+       ]
+       (FuncCall
+          (Ident (Identifier "box"))
+          [ KeyValArg (Identifier "width") (Ident (Identifier "size"))
+          , KeyValArg (Identifier "height") (Ident (Identifier "size"))
+          , BlockArg
+              [ SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 8 , column 4 )
+                  (Set
+                     (Ident (Identifier "text"))
+                     [ KeyValArg (Identifier "spacing") (Literal (Numeric 0.0 Percent))
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 9 , column 4 )
+                  (Set
+                     (Ident (Identifier "line"))
+                     [ SpreadArg (Ident (Identifier "args")) ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 10 , column 4 )
+                  (Set
+                     (Ident (Identifier "align"))
+                     [ NormalArg (Ident (Identifier "left")) ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 11 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "v"))
+                     [ NormalArg (Literal (Numeric 30.0 Percent)) ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 12 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 9.0 Percent)
+                                   , Literal (Numeric 2.0 Percent)
+                                   ])
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 13 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 38.7 Percent)
+                                   , Literal (Numeric 2.0 Percent)
+                                   ])
+                            , KeyValArg
+                                (Identifier "angle") (Negated (Literal (Numeric 72.0 Deg)))
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 14 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 57.5 Percent)
+                                   , Literal (Numeric 2.0 Percent)
+                                   ])
+                            , KeyValArg (Identifier "angle") (Literal (Numeric 252.0 Deg))
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 15 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 57.3 Percent)
+                                   , Literal (Numeric 2.0 Percent)
+                                   ])
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 16 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg
+                                (Identifier "length") (Negated (Literal (Numeric 30.0 Percent)))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 88.0 Percent)
+                                   , Literal (Numeric 2.0 Percent)
+                                   ])
+                            , KeyValArg
+                                (Identifier "angle") (Negated (Literal (Numeric 36.0 Deg)))
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 17 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 73.3 Percent)
+                                   , Literal (Numeric 48.0 Percent)
+                                   ])
+                            , KeyValArg (Identifier "angle") (Literal (Numeric 252.0 Deg))
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 18 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg
+                                (Identifier "length") (Negated (Literal (Numeric 30.0 Percent)))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 73.5 Percent)
+                                   , Literal (Numeric 48.0 Percent)
+                                   ])
+                            , KeyValArg (Identifier "angle") (Literal (Numeric 36.0 Deg))
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 19 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 25.4 Percent)
+                                   , Literal (Numeric 48.0 Percent)
+                                   ])
+                            , KeyValArg
+                                (Identifier "angle") (Negated (Literal (Numeric 36.0 Deg)))
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 20 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 25.6 Percent)
+                                   , Literal (Numeric 48.0 Percent)
+                                   ])
+                            , KeyValArg
+                                (Identifier "angle") (Negated (Literal (Numeric 72.0 Deg)))
+                            ])
+                     ])
+              , SoftBreak
+              , Code
+                  "test/typ/visualize/line-01.typ"
+                  ( line 21 , column 4 )
+                  (FuncCall
+                     (Ident (Identifier "place"))
+                     [ NormalArg
+                         (FuncCall
+                            (Ident (Identifier "line"))
+                            [ KeyValArg (Identifier "length") (Literal (Numeric 32.0 Percent))
+                            , KeyValArg
+                                (Identifier "start")
+                                (Array
+                                   [ Literal (Numeric 8.5 Percent)
+                                   , Literal (Numeric 2.0 Percent)
+                                   ])
+                            , KeyValArg (Identifier "angle") (Literal (Numeric 34.0 Deg))
+                            ])
+                     ])
+              , ParBreak
+              ]
+          ]))
+, ParBreak
+, Code
+    "test/typ/visualize/line-01.typ"
+    ( line 24 , column 2 )
+    (FuncCall
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "center"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "grid"))
+              [ KeyValArg (Identifier "columns") (Literal (Int 3))
+              , KeyValArg
+                  (Identifier "column-gutter") (Literal (Numeric 10.0 Pt))
+              , SpreadArg
+                  (Times
+                     (Array
+                        [ FuncCall
+                            (Ident (Identifier "star"))
+                            [ NormalArg (Literal (Numeric 20.0 Pt))
+                            , KeyValArg (Identifier "stroke") (Literal (Numeric 0.5 Pt))
+                            ]
+                        ])
+                     (Literal (Int 9)))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  parbreak(), 
+  align(alignment: center, 
+        body: grid(children: (box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt), 
+                              box(body: { text(body: [
+]), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          v(amount: 30%), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (9%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (38%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(length: 30%, 
+                                                           start: (57%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: -30%, 
+                                                           start: (88%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 252.0deg, 
+                                                           length: 30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 36.0deg, 
+                                                           length: -30%, 
+                                                           start: (73%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -36.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: -72.0deg, 
+                                                           length: 30%, 
+                                                           start: (25%, 
+                                                                   48%), 
+                                                           stroke: 0.5pt)), 
+                                          text(body: [
+], 
+                                               spacing: 0%), 
+                                          place(body: line(angle: 34.0deg, 
+                                                           length: 32%, 
+                                                           start: (8%, 
+                                                                   2%), 
+                                                           stroke: 0.5pt)), 
+                                          parbreak() }, 
+                                  height: 20.0pt, 
+                                  width: 20.0pt)), 
+                   column-gutter: 10.0pt, 
+                   columns: 3)), 
+  parbreak() }
diff --git a/test/out/visualize/line-02.out b/test/out/visualize/line-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/line-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/line-03.out b/test/out/visualize/line-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/line-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/path-00.out b/test/out/visualize/path-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/path-00.out
@@ -0,0 +1,210 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/path-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/path-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/path-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/visualize/path-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 200.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/path-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array [ Literal (Numeric 1.0 Fr) , Literal (Numeric 1.0 Fr) ])
+       , KeyValArg
+           (Identifier "rows")
+           (Array [ Literal (Numeric 1.0 Fr) , Literal (Numeric 1.0 Fr) ])
+       , KeyValArg
+           (Identifier "align")
+           (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "path"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              , KeyValArg (Identifier "closed") (Literal (Boolean True))
+              , NormalArg
+                  (Array
+                     [ Array
+                         [ Literal (Numeric 0.0 Percent) , Literal (Numeric 0.0 Percent) ]
+                     , Array
+                         [ Literal (Numeric 4.0 Percent)
+                         , Negated (Literal (Numeric 4.0 Percent))
+                         ]
+                     ])
+              , NormalArg
+                  (Array
+                     [ Array
+                         [ Literal (Numeric 50.0 Percent) , Literal (Numeric 50.0 Percent) ]
+                     , Array
+                         [ Literal (Numeric 4.0 Percent)
+                         , Negated (Literal (Numeric 4.0 Percent))
+                         ]
+                     ])
+              , NormalArg
+                  (Array
+                     [ Array
+                         [ Literal (Numeric 0.0 Percent) , Literal (Numeric 50.0 Percent) ]
+                     , Array
+                         [ Literal (Numeric 4.0 Percent) , Literal (Numeric 4.0 Percent) ]
+                     ])
+              , NormalArg
+                  (Array
+                     [ Array
+                         [ Literal (Numeric 50.0 Percent) , Literal (Numeric 0.0 Percent) ]
+                     , Array
+                         [ Literal (Numeric 4.0 Percent) , Literal (Numeric 4.0 Percent) ]
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "path"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "purple"))
+              , KeyValArg (Identifier "stroke") (Literal (Numeric 1.0 Pt))
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 30.0 Pt) , Literal (Numeric 30.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 30.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 30.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "path"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+              , KeyValArg (Identifier "stroke") (Literal (Numeric 1.0 Pt))
+              , KeyValArg (Identifier "closed") (Literal (Boolean True))
+              , NormalArg
+                  (Array
+                     [ Array
+                         [ Literal (Numeric 30.0 Percent) , Literal (Numeric 0.0 Percent) ]
+                     , Array
+                         [ Literal (Numeric 35.0 Percent) , Literal (Numeric 30.0 Percent) ]
+                     , Array
+                         [ Negated (Literal (Numeric 20.0 Percent))
+                         , Literal (Numeric 0.0 Percent)
+                         ]
+                     ])
+              , NormalArg
+                  (Array
+                     [ Array
+                         [ Literal (Numeric 30.0 Percent) , Literal (Numeric 60.0 Percent) ]
+                     , Array
+                         [ Negated (Literal (Numeric 20.0 Percent))
+                         , Literal (Numeric 0.0 Percent)
+                         ]
+                     , Array
+                         [ Literal (Numeric 0.0 Percent) , Literal (Numeric 0.0 Percent) ]
+                     ])
+              , NormalArg
+                  (Array
+                     [ Array
+                         [ Literal (Numeric 50.0 Percent) , Literal (Numeric 30.0 Percent) ]
+                     , Array
+                         [ Literal (Numeric 60.0 Percent)
+                         , Negated (Literal (Numeric 30.0 Percent))
+                         ]
+                     , Array
+                         [ Literal (Numeric 60.0 Percent) , Literal (Numeric 0.0 Percent) ]
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "path"))
+              [ KeyValArg (Identifier "stroke") (Literal (Numeric 5.0 Pt))
+              , KeyValArg (Identifier "closed") (Literal (Boolean True))
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 30.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 30.0 Pt) , Literal (Numeric 30.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  table(align: Axes(center, horizon), 
+        children: (path(closed: true, 
+                        fill: rgb(100%,25%,21%,100%), 
+                        vertices: (((0%, 0%), 
+                                    (4%, -4%)), 
+                                   ((50%, 50%), (4%, -4%)), 
+                                   ((0%, 50%), (4%, 4%)), 
+                                   ((50%, 0%), (4%, 4%)))), 
+                   path(fill: rgb(69%,5%,78%,100%), 
+                        stroke: 1.0pt, 
+                        vertices: ((0.0pt, 0.0pt), 
+                                   (30.0pt, 30.0pt), 
+                                   (0.0pt, 30.0pt), 
+                                   (30.0pt, 0.0pt))), 
+                   path(closed: true, 
+                        fill: rgb(0%,45%,85%,100%), 
+                        stroke: 1.0pt, 
+                        vertices: (((30%, 0%), 
+                                    (35%, 30%), 
+                                    (-20%, 0%)), 
+                                   ((30%, 60%), 
+                                    (-20%, 0%), 
+                                    (0%, 0%)), 
+                                   ((50%, 30%), 
+                                    (60%, -30%), 
+                                    (60%, 0%)))), 
+                   path(closed: true, 
+                        stroke: 5.0pt, 
+                        vertices: ((0.0pt, 30.0pt), 
+                                   (30.0pt, 30.0pt), 
+                                   (15.0pt, 0.0pt)))), 
+        columns: (1.0fr, 1.0fr), 
+        rows: (1.0fr, 1.0fr)), 
+  parbreak() }
diff --git a/test/out/visualize/path-01.out b/test/out/visualize/path-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/path-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/path-02.out b/test/out/visualize/path-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/path-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/path-03.out b/test/out/visualize/path-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/path-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/polygon-00.out b/test/out/visualize/polygon-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/polygon-00.out
@@ -0,0 +1,264 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/polygon-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/polygon-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "polygon"))
+       [ KeyValArg (Identifier "stroke") (Literal (Numeric 0.75 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall (Ident (Identifier "polygon")) [])
+, SoftBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ NormalArg
+           (Array [ Literal (Numeric 0.0 Em) , Literal (Numeric 0.0 Pt) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 10.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       ])
+, ParBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ NormalArg
+           (Array [ Literal (Numeric 5.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 10.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 5.0 Pt) , Literal (Numeric 5.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 10.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 5.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 5.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 16 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ KeyValArg (Identifier "stroke") (Literal None)
+       , NormalArg
+           (Array [ Literal (Numeric 5.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 10.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ KeyValArg (Identifier "stroke") (Literal (Numeric 3.0 Pt))
+       , KeyValArg (Identifier "fill") (Literal None)
+       , NormalArg
+           (Array [ Literal (Numeric 5.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 10.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 20 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array
+              [ Literal (Numeric 100.0 Percent) , Literal (Numeric 5.0 Pt) ])
+       , NormalArg
+           (Array
+              [ Literal (Numeric 50.0 Percent) , Literal (Numeric 10.0 Pt) ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 23 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 5.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 5.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 5.0 Pt) , Literal (Numeric 15.0 Pt) ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/polygon-00.typ"
+    ( line 26 , column 2 )
+    (FuncCall
+       (Ident (Identifier "polygon"))
+       [ NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 10.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 30.0 Pt) , Literal (Numeric 20.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 30.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 20.0 Pt) , Literal (Numeric 0.0 Pt) ])
+       , NormalArg
+           (Array [ Literal (Numeric 20.0 Pt) , Literal (Numeric 35.0 Pt) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ()), 
+  text(body: [
+]), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ((0.0em, 0.0pt))), 
+  text(body: [
+]), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ((0.0pt, 0.0pt), 
+                     (10.0pt, 0.0pt))), 
+  parbreak(), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ((5.0pt, 0.0pt), 
+                     (0.0pt, 10.0pt), 
+                     (10.0pt, 10.0pt))), 
+  text(body: [
+]), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ((0.0pt, 0.0pt), 
+                     (5.0pt, 5.0pt), 
+                     (10.0pt, 0.0pt), 
+                     (15.0pt, 5.0pt), 
+                     (5.0pt, 10.0pt))), 
+  text(body: [
+]), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: none, 
+          vertices: ((5.0pt, 0.0pt), 
+                     (0.0pt, 10.0pt), 
+                     (10.0pt, 10.0pt))), 
+  text(body: [
+]), 
+  polygon(fill: none, 
+          stroke: 3.0pt, 
+          vertices: ((5.0pt, 0.0pt), 
+                     (0.0pt, 10.0pt), 
+                     (10.0pt, 10.0pt))), 
+  parbreak(), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ((0.0pt, 0.0pt), 
+                     (100%, 5.0pt), 
+                     (50%, 10.0pt))), 
+  parbreak(), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ((0.0pt, 5.0pt), 
+                     (5.0pt, 0.0pt), 
+                     (0.0pt, 10.0pt), 
+                     (5.0pt, 15.0pt))), 
+  parbreak(), 
+  polygon(fill: rgb(0%,45%,85%,100%), 
+          stroke: 0.75pt, 
+          vertices: ((0.0pt, 10.0pt), 
+                     (30.0pt, 20.0pt), 
+                     (0.0pt, 30.0pt), 
+                     (20.0pt, 0.0pt), 
+                     (20.0pt, 35.0pt))), 
+  parbreak() }
diff --git a/test/out/visualize/polygon-01.out b/test/out/visualize/polygon-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/polygon-01.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/shape-aspect-00.out b/test/out/visualize/shape-aspect-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-aspect-00.out
@@ -0,0 +1,130 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-aspect-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-aspect-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-aspect-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Comment
+, Code
+    "test/typ/visualize/shape-aspect-00.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 120.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 70.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-00.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg (Ident (Identifier "bottom")) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-00.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "centered")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "align")))
+          [ NormalArg
+              (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 50.0 Percent))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "centered")) [ BlockArg [ Text "A" ] ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 50.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "stack"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "square"))
+                     [ KeyValArg (Identifier "size") (Literal (Numeric 10.0 Pt)) ])
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "square"))
+                     [ KeyValArg (Identifier "size") (Literal (Numeric 20.0 Pt))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "centered")) [ BlockArg [ Text "B" ] ])
+                     ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  stack(children: (square(body: align(alignment: bottom, 
+                                      body: text(body: [A])), 
+                          width: 50%), 
+                   square(height: 50%), 
+                   stack(children: (square(size: 10.0pt), 
+                                    square(body: align(alignment: bottom, 
+                                                       body: text(body: [B])), 
+                                           size: 20.0pt)))), 
+        dir: ltr, 
+        spacing: 1.0fr), 
+  parbreak() }
diff --git a/test/out/visualize/shape-aspect-01.out b/test/out/visualize/shape-aspect-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-aspect-01.out
@@ -0,0 +1,122 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-aspect-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-aspect-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-aspect-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-aspect-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "inset") (Literal (Numeric 4.0 Pt))
+              , BlockArg
+                  [ SoftBreak
+                  , Text "Hey"
+                  , Space
+                  , Text "there,"
+                  , Space
+                  , Code
+                      "test/typ/visualize/shape-aspect-01.typ"
+                      ( line 5 , column 15 )
+                      (FuncCall
+                         (Ident (Identifier "align"))
+                         [ NormalArg
+                             (Plus (Ident (Identifier "center")) (Ident (Identifier "bottom")))
+                         , NormalArg
+                             (FuncCall
+                                (Ident (Identifier "rotate"))
+                                [ NormalArg (Literal (Numeric 180.0 Deg))
+                                , NormalArg (Block (Content [ Text "you!" ]))
+                                ])
+                         ])
+                  , ParBreak
+                  ]
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "align"))
+                     [ NormalArg
+                         (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+                     , NormalArg (Block (Content [ Text "Hey" , Text "." ]))
+                     ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], size: 8.0pt), 
+  box(body: square(body: { text(body: [
+Hey there, ], 
+                                size: 8.0pt), 
+                           align(alignment: Axes(center, bottom), 
+                                 body: rotate(angle: 180.0deg, 
+                                              body: text(body: [you!], 
+                                                         size: 8.0pt))), 
+                           parbreak() }, 
+                   inset: 4.0pt)), 
+  text(body: [
+], size: 8.0pt), 
+  box(body: circle(body: align(alignment: Axes(center, horizon), 
+                               body: text(body: [Hey.], 
+                                          size: 8.0pt)))), 
+  parbreak() }
diff --git a/test/out/visualize/shape-aspect-02.out b/test/out/visualize/shape-aspect-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-aspect-02.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-aspect-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-aspect-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-aspect-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-aspect-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 2.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Pt))
+              , KeyValArg (Identifier "height") (Literal (Numeric 40.0 Pt))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  stack(children: (square(height: 40.0pt, 
+                          width: 20.0pt), 
+                   circle(height: 100.0pt, 
+                          width: 20%)), 
+        dir: ltr, 
+        spacing: 2.0pt), 
+  parbreak() }
diff --git a/test/out/visualize/shape-aspect-03.out b/test/out/visualize/shape-aspect-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-aspect-03.out
@@ -0,0 +1,78 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-aspect-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-aspect-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-aspect-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-aspect-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "red")) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "square"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "green")) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  stack(children: (square(fill: rgb(100%,25%,21%,100%)), 
+                   square(fill: rgb(18%,80%,25%,100%))), 
+        dir: ltr), 
+  parbreak() }
diff --git a/test/out/visualize/shape-aspect-04.out b/test/out/visualize/shape-aspect-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-aspect-04.out
@@ -0,0 +1,86 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-aspect-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-aspect-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-aspect-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-aspect-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 120.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 40.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 2.0 Pt))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg (Identifier "radius") (Literal (Numeric 5.0 Pt)) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 10.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 50.0 Percent))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  stack(children: (circle(radius: 5.0pt), 
+                   circle(width: 10%), 
+                   circle(height: 50%)), 
+        dir: ltr, 
+        spacing: 2.0pt), 
+  parbreak() }
diff --git a/test/out/visualize/shape-aspect-05.out b/test/out/visualize/shape-aspect-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-aspect-05.out
@@ -0,0 +1,81 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-aspect-05.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-aspect-05.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-aspect-05.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-aspect-05.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 40.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 25.0 Pt))
+       , KeyValArg (Identifier "margin") (Literal (Numeric 5.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-05.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-aspect-05.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , BlockArg [ Text "Hello" , Space , Text "there" ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  square(width: 100%), 
+  text(body: [
+]), 
+  square(body: text(body: [Hello there]), 
+         width: 100%), 
+  parbreak() }
diff --git a/test/out/visualize/shape-aspect-06.out b/test/out/visualize/shape-aspect-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-aspect-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/shape-circle-00.out b/test/out/visualize/shape-circle-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-circle-00.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-circle-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-circle-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-circle-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-circle-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg (FuncCall (Ident (Identifier "circle")) []) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "circle")) [ BlockArg [ Text "Hey" ] ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  box(body: circle()), 
+  text(body: [
+]), 
+  box(body: circle(body: text(body: [Hey]))), 
+  parbreak() }
diff --git a/test/out/visualize/shape-circle-01.out b/test/out/visualize/shape-circle-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-circle-01.out
@@ -0,0 +1,249 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-circle-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-circle-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-circle-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-circle-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "circle"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt)) ])
+, ParBreak
+, Text "Auto"
+, Text "-"
+, Text "sized"
+, Space
+, Text "circle"
+, Text "."
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "circle"))
+       [ KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (String "eb5278")) ])
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 2.0 Pt)) (Ident (Identifier "black")))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg
+                  (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+              , BlockArg [ Text "But," , Space , Text "soft!" ]
+              ])
+       ])
+, ParBreak
+, Text "Center"
+, Text "-"
+, Text "aligned"
+, Space
+, Text "rect"
+, Space
+, Text "in"
+, Space
+, Text "auto"
+, Text "-"
+, Text "sized"
+, Space
+, Text "circle"
+, Text "."
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-01.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "circle"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , KeyValArg (Identifier "stroke") (Ident (Identifier "green"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg
+                  (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                     , KeyValArg (Identifier "inset") (Literal (Numeric 5.0 Pt))
+                     , BlockArg [ Text "But," , Space , Text "soft!" ]
+                     ])
+              ])
+       ])
+, ParBreak
+, Text "Rect"
+, Space
+, Text "in"
+, Space
+, Text "auto"
+, Text "-"
+, Text "sized"
+, Space
+, Text "circle"
+, Text "."
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-01.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "circle"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+              , KeyValArg (Identifier "stroke") (Ident (Identifier "white"))
+              , KeyValArg (Identifier "inset") (Literal (Numeric 4.0 Pt))
+              , BlockArg
+                  [ SoftBreak
+                  , Code
+                      "test/typ/visualize/shape-circle-01.typ"
+                      ( line 20 , column 6 )
+                      (Set
+                         (Ident (Identifier "text"))
+                         [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+                  , SoftBreak
+                  , Text "But,"
+                  , Space
+                  , Text "soft!"
+                  , Space
+                  , Text "what"
+                  , Space
+                  , Text "light"
+                  , Space
+                  , Text "through"
+                  , Space
+                  , Text "yonder"
+                  , Space
+                  , Text "window"
+                  , Space
+                  , Text "breaks?"
+                  , ParBreak
+                  ]
+              ])
+       ])
+, ParBreak
+, Text "Expanded"
+, Space
+, Text "by"
+, Space
+, Text "height"
+, Text "."
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-01.typ"
+    ( line 26 , column 2 )
+    (FuncCall
+       (Ident (Identifier "circle"))
+       [ KeyValArg (Identifier "stroke") (Ident (Identifier "black"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg (Ident (Identifier "center"))
+              , BlockArg
+                  [ Text "A"
+                  , Space
+                  , HardBreak
+                  , Text "B"
+                  , Space
+                  , HardBreak
+                  , Text "C"
+                  ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [Auto-sized circle.
+]), 
+  circle(body: align(alignment: Axes(center, horizon), 
+                     body: text(body: [But, soft!])), 
+         fill: rgb(92%,32%,47%,100%), 
+         inset: 0.0pt, 
+         stroke: (thickness: 2.0pt,
+                  color: rgb(0%,0%,0%,100%))), 
+  parbreak(), 
+  text(body: [Center-aligned rect in auto-sized circle.
+]), 
+  circle(body: align(alignment: Axes(center, horizon), 
+                     body: rect(body: text(body: [But, soft!]), 
+                                fill: rgb(18%,80%,25%,100%), 
+                                inset: 5.0pt)), 
+         fill: rgb(100%,25%,21%,100%), 
+         inset: 0.0pt, 
+         stroke: rgb(18%,80%,25%,100%)), 
+  parbreak(), 
+  text(body: [Rect in auto-sized circle.
+]), 
+  circle(body: rect(body: { text(body: [
+]), 
+                            text(body: [
+But, soft! what light through yonder window breaks?], 
+                                 size: 8.0pt), 
+                            parbreak() }, 
+                    fill: rgb(18%,80%,25%,100%), 
+                    inset: 4.0pt, 
+                    stroke: rgb(100%,100%,100%,100%)), 
+         fill: rgb(100%,25%,21%,100%), 
+         inset: 0.0pt), 
+  parbreak(), 
+  text(body: [Expanded by height.
+], 
+       size: 8.0pt), 
+  circle(body: align(alignment: center, 
+                     body: { text(body: [A ], 
+                                  size: 8.0pt), 
+                             linebreak(), 
+                             text(body: [B ], 
+                                  size: 8.0pt), 
+                             linebreak(), 
+                             text(body: [C], 
+                                  size: 8.0pt) }), 
+         inset: 0.0pt, 
+         stroke: rgb(0%,0%,0%,100%)), 
+  parbreak() }
diff --git a/test/out/visualize/shape-circle-02.out b/test/out/visualize/shape-circle-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-circle-02.out
@@ -0,0 +1,65 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-circle-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-circle-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-circle-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-circle-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 40.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 30.0 Pt))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "green")) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  rect(body: circle(fill: rgb(18%,80%,25%,100%)), 
+       fill: rgb(100%,25%,21%,100%), 
+       height: 30.0pt, 
+       width: 40.0pt), 
+  parbreak() }
diff --git a/test/out/visualize/shape-circle-03.out b/test/out/visualize/shape-circle-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-circle-03.out
@@ -0,0 +1,143 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-circle-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-circle-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-circle-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-circle-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "white")) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-03.typ"
+    ( line 4 , column 2 )
+    (Show
+       Nothing
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "rect")))
+          [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Pt))
+          , KeyValArg (Identifier "height") (Literal (Numeric 50.0 Pt))
+          , KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt))
+          , KeyValArg
+              (Identifier "fill")
+              (FuncCall
+                 (Ident (Identifier "rgb")) [ NormalArg (Literal (String "aaa")) ])
+          ]))
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-03.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "align"))
+       [ NormalArg
+           (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-circle-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Fr))
+       , NormalArg (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg (Identifier "radius") (Literal (Numeric 10.0 Pt))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              , NormalArg (Block (Content [ Text "A" ]))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 60.0 Percent))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              , NormalArg (Block (Content [ Text "B" ]))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "circle"))
+              [ KeyValArg
+                  (Identifier "width")
+                  (Plus (Literal (Numeric 20.0 Percent)) (Literal (Numeric 20.0 Pt)))
+              , KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+              , NormalArg (Block (Content [ Text "C" ]))
+              ])
+       , NormalArg (Literal (Numeric 1.0 Fr))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+], 
+       fill: rgb(100%,100%,100%,100%)), 
+  rect(body: { text(body: [
+], 
+                    fill: rgb(100%,100%,100%,100%)), 
+               text(body: [
+], 
+                    fill: rgb(100%,100%,100%,100%)), 
+               stack(children: (1.0fr, 
+                                circle(body: text(body: [A], 
+                                                  fill: rgb(100%,100%,100%,100%)), 
+                                       fill: rgb(13%,61%,67%,100%), 
+                                       radius: 10.0pt), 
+                                circle(body: text(body: [B], 
+                                                  fill: rgb(100%,100%,100%,100%)), 
+                                       fill: rgb(13%,61%,67%,100%), 
+                                       height: 60%), 
+                                circle(body: text(body: [C], 
+                                                  fill: rgb(100%,100%,100%,100%)), 
+                                       fill: rgb(13%,61%,67%,100%), 
+                                       width: 20.0pt + 20%), 
+                                1.0fr), 
+                     dir: ltr, 
+                     spacing: 1.0fr), 
+               parbreak() }, 
+       fill: rgb(3%,3%,3%,100%), 
+       height: 50.0pt, 
+       inset: 0.0pt, 
+       width: 100.0pt) }
diff --git a/test/out/visualize/shape-circle-04.out b/test/out/visualize/shape-circle-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-circle-04.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/shape-ellipse-00.out b/test/out/visualize/shape-ellipse-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-ellipse-00.out
@@ -0,0 +1,53 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-ellipse-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-ellipse-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-ellipse-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-ellipse-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall (Ident (Identifier "ellipse")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  ellipse(), 
+  parbreak() }
diff --git a/test/out/visualize/shape-ellipse-01.out b/test/out/visualize/shape-ellipse-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-ellipse-01.out
@@ -0,0 +1,235 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-ellipse-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-ellipse-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-ellipse-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-ellipse-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-ellipse-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "ellipse"))
+       [ KeyValArg (Identifier "inset") (Literal (Numeric 0.0 Pt)) ])
+, ParBreak
+, Text "Rect"
+, Space
+, Text "in"
+, Space
+, Text "ellipse"
+, Space
+, Text "in"
+, Space
+, Text "fixed"
+, Space
+, Text "rect"
+, Text "."
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-ellipse-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 3.0 Cm))
+       , KeyValArg (Identifier "height") (Literal (Numeric 2.0 Cm))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (String "2a631a")) ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "ellipse"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+              , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Percent))
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "rect"))
+                     [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                     , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+                     , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Percent))
+                     , NormalArg
+                         (FuncCall
+                            (Ident (Identifier "align"))
+                            [ NormalArg
+                                (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+                            , BlockArg
+                                [ SoftBreak
+                                , Text "Stuff"
+                                , Space
+                                , Text "inside"
+                                , Space
+                                , Text "an"
+                                , Space
+                                , Text "ellipse!"
+                                , ParBreak
+                                ]
+                            ])
+                     ])
+              ])
+       ])
+, ParBreak
+, Text "Auto"
+, Text "-"
+, Text "sized"
+, Space
+, Text "ellipse"
+, Text "."
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-ellipse-01.typ"
+    ( line 17 , column 2 )
+    (FuncCall
+       (Ident (Identifier "ellipse"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 3.0 Pt)) (Ident (Identifier "red")))
+       , KeyValArg (Identifier "inset") (Literal (Numeric 3.0 Pt))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/visualize/shape-ellipse-01.typ"
+               ( line 18 , column 4 )
+               (Set
+                  (Ident (Identifier "text"))
+                  [ NormalArg (Literal (Numeric 8.0 Pt)) ])
+           , SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , Text "yonder"
+           , Space
+           , Text "window"
+           , Space
+           , Text "breaks?"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+, Text "An"
+, Space
+, Text "inline"
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-ellipse-01.typ"
+    ( line 24 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "ellipse"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 8.0 Pt))
+              , KeyValArg (Identifier "height") (Literal (Numeric 6.0 Pt))
+              , KeyValArg
+                  (Identifier "outset")
+                  (Dict
+                     [ ( Identifier "top" , Literal (Numeric 3.0 Pt) )
+                     , ( Identifier "rest" , Literal (Numeric 5.5 Pt) )
+                     ])
+              ])
+       ])
+, SoftBreak
+, Text "ellipse"
+, Text "."
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  text(body: [Rect in ellipse in fixed rect.
+]), 
+  rect(body: ellipse(body: rect(body: align(alignment: Axes(center, horizon), 
+                                            body: { text(body: [
+Stuff inside an ellipse!]), 
+                                                    parbreak() }), 
+                                fill: rgb(18%,80%,25%,100%), 
+                                height: 100%, 
+                                inset: 0.0pt, 
+                                width: 100%), 
+                     fill: rgb(100%,25%,21%,100%), 
+                     height: 100%, 
+                     inset: 0.0pt, 
+                     width: 100%), 
+       fill: rgb(16%,38%,10%,100%), 
+       height: 2.0cm, 
+       inset: 0.0pt, 
+       width: 3.0cm), 
+  parbreak(), 
+  text(body: [Auto-sized ellipse.
+]), 
+  ellipse(body: { text(body: [
+]), 
+                  text(body: [
+But, soft! what light through yonder window breaks?], 
+                       size: 8.0pt), 
+                  parbreak() }, 
+          fill: rgb(18%,80%,25%,100%), 
+          inset: 3.0pt, 
+          stroke: (thickness: 3.0pt,
+                   color: rgb(100%,25%,21%,100%))), 
+  parbreak(), 
+  text(body: [An inline
+], 
+       size: 8.0pt), 
+  box(body: ellipse(height: 6.0pt, 
+                    inset: 0.0pt, 
+                    outset: (top: 3.0pt,
+                             rest: 5.5pt), 
+                    width: 8.0pt)), 
+  text(body: [
+ellipse.], 
+       size: 8.0pt), 
+  parbreak() }
diff --git a/test/out/visualize/shape-fill-stroke-00.out b/test/out/visualize/shape-fill-stroke-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-fill-stroke-00.out
@@ -0,0 +1,264 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-fill-stroke-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-fill-stroke-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-fill-stroke-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-00.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "variant")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "with")) (Ident (Identifier "rect")))
+          [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Pt))
+          , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+          ]))
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "items")))
+       (For
+          (DestructuringBind
+             [ Simple (Just (Identifier "i"))
+             , Simple (Just (Identifier "item"))
+             ])
+          (FuncCall
+             (FieldAccess
+                (Ident (Identifier "enumerate"))
+                (Array
+                   [ FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "stroke") (Literal None) ]
+                   , FuncCall (Ident (Identifier "variant")) []
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "fill") (Literal None) ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "stroke") (Literal (Numeric 2.0 Pt)) ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "stroke") (Ident (Identifier "eastern")) ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg
+                           (Identifier "stroke")
+                           (Plus (Ident (Identifier "eastern")) (Literal (Numeric 2.0 Pt)))
+                       ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern")) ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+                       , KeyValArg (Identifier "stroke") (Literal None)
+                       ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                       , KeyValArg (Identifier "stroke") (Literal None)
+                       ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                       , KeyValArg (Identifier "stroke") (Ident (Identifier "green"))
+                       ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                       , KeyValArg
+                           (Identifier "stroke")
+                           (Plus (Ident (Identifier "black")) (Literal (Numeric 2.0 Pt)))
+                       ]
+                   , FuncCall
+                       (Ident (Identifier "variant"))
+                       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+                       , KeyValArg
+                           (Identifier "stroke")
+                           (Plus (Ident (Identifier "green")) (Literal (Numeric 2.0 Pt)))
+                       ]
+                   ]))
+             [])
+          (Block
+             (CodeBlock
+                [ Array
+                    [ FuncCall
+                        (Ident (Identifier "align"))
+                        [ NormalArg (Ident (Identifier "horizon"))
+                        , BlockArg
+                            [ Code
+                                "test/typ/visualize/shape-fill-stroke-00.typ"
+                                ( line 17 , column 20 )
+                                (Plus (Ident (Identifier "i")) (Literal (Int 1)))
+                            , Text "."
+                            ]
+                        ]
+                    , Ident (Identifier "item")
+                    , Block (Content [])
+                    ]
+                ]))))
+, ParBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-00.typ"
+    ( line 20 , column 2 )
+    (FuncCall
+       (Ident (Identifier "grid"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array
+              [ Literal Auto
+              , Literal Auto
+              , Literal (Numeric 1.0 Fr)
+              , Literal Auto
+              , Literal Auto
+              , Literal (Numeric 0.0 Fr)
+              ])
+       , KeyValArg (Identifier "gutter") (Literal (Numeric 5.0 Pt))
+       , SpreadArg (Ident (Identifier "items"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  parbreak(), 
+  grid(children: (align(alignment: horizon, 
+                        body: { text(body: [1]), 
+                                text(body: [.]) }), 
+                  rect(height: 10.0pt, 
+                       stroke: none, 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [2]), 
+                                text(body: [.]) }), 
+                  rect(height: 10.0pt, 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [3]), 
+                                text(body: [.]) }), 
+                  rect(fill: none, 
+                       height: 10.0pt, 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [4]), 
+                                text(body: [.]) }), 
+                  rect(height: 10.0pt, 
+                       stroke: 2.0pt, 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [5]), 
+                                text(body: [.]) }), 
+                  rect(height: 10.0pt, 
+                       stroke: rgb(13%,61%,67%,100%), 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [6]), 
+                                text(body: [.]) }), 
+                  rect(height: 10.0pt, 
+                       stroke: (thickness: 2.0pt,
+                                color: rgb(13%,61%,67%,100%)), 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [7]), 
+                                text(body: [.]) }), 
+                  rect(fill: rgb(13%,61%,67%,100%), 
+                       height: 10.0pt, 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [8]), 
+                                text(body: [.]) }), 
+                  rect(fill: rgb(13%,61%,67%,100%), 
+                       height: 10.0pt, 
+                       stroke: none, 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [9]), 
+                                text(body: [.]) }), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 10.0pt, 
+                       stroke: none, 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [10]), 
+                                text(body: [.]) }), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 10.0pt, 
+                       stroke: rgb(18%,80%,25%,100%), 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [11]), 
+                                text(body: [.]) }), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 10.0pt, 
+                       stroke: (thickness: 2.0pt,
+                                color: rgb(0%,0%,0%,100%)), 
+                       width: 20.0pt), 
+                  {  }, 
+                  align(alignment: horizon, 
+                        body: { text(body: [12]), 
+                                text(body: [.]) }), 
+                  rect(fill: rgb(100%,25%,21%,100%), 
+                       height: 10.0pt, 
+                       stroke: (thickness: 2.0pt,
+                                color: rgb(18%,80%,25%,100%)), 
+                       width: 20.0pt), 
+                  {  }), 
+       columns: (auto, 
+                 auto, 
+                 1.0fr, 
+                 auto, 
+                 auto, 
+                 0.0fr), 
+       gutter: 5.0pt), 
+  parbreak() }
diff --git a/test/out/visualize/shape-fill-stroke-01.out b/test/out/visualize/shape-fill-stroke-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-fill-stroke-01.out
@@ -0,0 +1,163 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-fill-stroke-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-fill-stroke-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 3 , column 2 )
+    (LetFunc
+       (Identifier "sq")
+       [ SinkParam (Just (Identifier "args")) ]
+       (FuncCall
+          (Ident (Identifier "box"))
+          [ NormalArg
+              (FuncCall
+                 (Ident (Identifier "square"))
+                 [ KeyValArg (Identifier "size") (Literal (Numeric 10.0 Pt))
+                 , SpreadArg (Ident (Identifier "args"))
+                 ])
+          ]))
+, ParBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 5 , column 2 )
+    (Set
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "stroke") (Literal None) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall (Ident (Identifier "sq")) [])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 7 , column 2 )
+    (Set
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "stroke") (Literal Auto) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 8 , column 2 )
+    (FuncCall (Ident (Identifier "sq")) [])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "sq"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "teal")) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "sq"))
+       [ KeyValArg (Identifier "stroke") (Literal (Numeric 2.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "sq"))
+       [ KeyValArg (Identifier "stroke") (Ident (Identifier "blue")) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "sq"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "teal"))
+       , KeyValArg (Identifier "stroke") (Ident (Identifier "blue"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-01.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "sq"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "teal"))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 2.0 Pt)) (Ident (Identifier "blue")))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  text(body: [
+]), 
+  box(body: square(size: 10.0pt, 
+                   stroke: none)), 
+  text(body: [
+]), 
+  text(body: [
+]), 
+  box(body: square(size: 10.0pt, 
+                   stroke: auto)), 
+  text(body: [
+]), 
+  box(body: square(fill: rgb(22%,80%,80%,100%), 
+                   size: 10.0pt, 
+                   stroke: auto)), 
+  text(body: [
+]), 
+  box(body: square(size: 10.0pt, 
+                   stroke: 2.0pt)), 
+  text(body: [
+]), 
+  box(body: square(size: 10.0pt, 
+                   stroke: rgb(0%,45%,85%,100%))), 
+  text(body: [
+]), 
+  box(body: square(fill: rgb(22%,80%,80%,100%), 
+                   size: 10.0pt, 
+                   stroke: rgb(0%,45%,85%,100%))), 
+  text(body: [
+]), 
+  box(body: square(fill: rgb(22%,80%,80%,100%), 
+                   size: 10.0pt, 
+                   stroke: (thickness: 2.0pt,
+                            color: rgb(0%,45%,85%,100%)))), 
+  parbreak() }
diff --git a/test/out/visualize/shape-fill-stroke-02.out b/test/out/visualize/shape-fill-stroke-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-fill-stroke-02.out
@@ -0,0 +1,99 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-fill-stroke-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-fill-stroke-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-fill-stroke-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-fill-stroke-02.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "stroke") (Literal (Numeric 4.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-02.typ"
+    ( line 4 , column 2 )
+    (Set
+       (Ident (Identifier "text"))
+       [ KeyValArg (Identifier "font") (Literal (String "Roboto")) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-fill-stroke-02.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "left" , Ident (Identifier "red") )
+              , ( Identifier "top" , Ident (Identifier "yellow") )
+              , ( Identifier "right" , Ident (Identifier "green") )
+              , ( Identifier "bottom" , Ident (Identifier "blue") )
+              ])
+       , KeyValArg (Identifier "radius") (Literal (Numeric 100.0 Percent))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "align"))
+              [ NormalArg
+                  (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+              , BlockArg [ Strong [ Text "G" ] ]
+              ])
+       , KeyValArg (Identifier "inset") (Literal (Numeric 8.0 Pt))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  text(body: [
+], 
+       font: "Roboto"), 
+  square(body: align(alignment: Axes(center, horizon), 
+                     body: strong(body: text(body: [G], 
+                                             font: "Roboto"))), 
+         inset: 8.0pt, 
+         radius: 100%, 
+         stroke: (left: rgb(100%,25%,21%,100%),
+                  top: rgb(100%,86%,0%,100%),
+                  right: rgb(18%,80%,25%,100%),
+                  bottom: rgb(0%,45%,85%,100%))), 
+  parbreak() }
diff --git a/test/out/visualize/shape-rect-00.out b/test/out/visualize/shape-rect-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-rect-00.out
@@ -0,0 +1,53 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-rect-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-rect-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-rect-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rect-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall (Ident (Identifier "rect")) [])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  rect(), 
+  parbreak() }
diff --git a/test/out/visualize/shape-rect-01.out b/test/out/visualize/shape-rect-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-rect-01.out
@@ -0,0 +1,295 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-rect-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-rect-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 150.0 Pt)) ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , BlockArg [ Text "Textbox" ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "block"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "height") (Literal (Numeric 15.0 Pt))
+              , KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "46b3c2")) ])
+              , KeyValArg
+                  (Identifier "stroke")
+                  (Plus
+                     (Literal (Numeric 2.0 Pt))
+                     (FuncCall
+                        (Ident (Identifier "rgb"))
+                        [ NormalArg (Literal (String "234994")) ]))
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 2.0 Cm))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (String "9650d6")) ])
+       , BlockArg
+           [ Text "Fixed" , Space , Text "and" , Space , Text "padded" ]
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 18 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 1.0 Cm))
+       , KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg
+           (Identifier "fill")
+           (FuncCall
+              (Ident (Identifier "rgb"))
+              [ NormalArg (Literal (String "734ced")) ])
+       , BlockArg [ Text "Topleft" ]
+       ])
+, ParBreak
+, Comment
+, Text "{"
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 21 , column 3 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 0.5 In))
+              , KeyValArg (Identifier "height") (Literal (Numeric 7.0 Pt))
+              , KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "d6cd67")) ])
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 22 , column 3 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 0.5 In))
+              , KeyValArg (Identifier "height") (Literal (Numeric 7.0 Pt))
+              , KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "edd466")) ])
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 23 , column 3 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 0.5 In))
+              , KeyValArg (Identifier "height") (Literal (Numeric 7.0 Pt))
+              , KeyValArg
+                  (Identifier "fill")
+                  (FuncCall
+                     (Ident (Identifier "rgb"))
+                     [ NormalArg (Literal (String "e3be62")) ])
+              ])
+       ])
+, Text "}"
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 26 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Fr))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 2.0 Cm))
+              , KeyValArg (Identifier "radius") (Literal (Numeric 60.0 Percent))
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 1.0 Cm))
+              , KeyValArg
+                  (Identifier "radius")
+                  (Dict
+                     [ ( Identifier "left" , Literal (Numeric 10.0 Pt) )
+                     , ( Identifier "right" , Literal (Numeric 5.0 Pt) )
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "rect"))
+              [ KeyValArg (Identifier "width") (Literal (Numeric 1.25 Cm))
+              , KeyValArg
+                  (Identifier "radius")
+                  (Dict
+                     [ ( Identifier "top-left" , Literal (Numeric 2.0 Pt) )
+                     , ( Identifier "top-right" , Literal (Numeric 5.0 Pt) )
+                     , ( Identifier "bottom-right" , Literal (Numeric 8.0 Pt) )
+                     , ( Identifier "bottom-left" , Literal (Numeric 11.0 Pt) )
+                     ])
+              ])
+       ])
+, ParBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 40 , column 2 )
+    (Set
+       (Ident (Identifier "rect"))
+       [ KeyValArg
+           (Identifier "stroke")
+           (Dict [ ( Identifier "right" , Ident (Identifier "red") ) ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-rect-01.typ"
+    ( line 41 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Percent))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "lime"))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "x" , Literal (Numeric 5.0 Pt) )
+              , ( Identifier "y" , Literal (Numeric 1.0 Pt) )
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  rect(body: text(body: [Textbox]), 
+       fill: rgb(18%,80%,25%,100%)), 
+  parbreak(), 
+  block(body: rect(fill: rgb(27%,70%,76%,100%), 
+                   height: 15.0pt, 
+                   stroke: (thickness: 2.0pt,
+                            color: rgb(13%,28%,58%,100%)))), 
+  parbreak(), 
+  rect(body: text(body: [Fixed and padded]), 
+       fill: rgb(58%,31%,83%,100%), 
+       width: 2.0cm), 
+  parbreak(), 
+  rect(body: text(body: [Topleft]), 
+       fill: rgb(45%,29%,92%,100%), 
+       height: 1.0cm, 
+       width: 100%), 
+  parbreak(), 
+  text(body: [{]), 
+  box(body: rect(fill: rgb(83%,80%,40%,100%), 
+                 height: 7.0pt, 
+                 width: 0.5in)), 
+  text(body: [
+]), 
+  box(body: rect(fill: rgb(92%,83%,40%,100%), 
+                 height: 7.0pt, 
+                 width: 0.5in)), 
+  text(body: [
+]), 
+  box(body: rect(fill: rgb(89%,74%,38%,100%), 
+                 height: 7.0pt, 
+                 width: 0.5in)), 
+  text(body: [}]), 
+  parbreak(), 
+  stack(children: (rect(radius: 60%, 
+                        width: 2.0cm), 
+                   rect(radius: (left: 10.0pt,
+                                 right: 5.0pt), 
+                        width: 1.0cm), 
+                   rect(radius: (top-left: 2.0pt,
+                                 top-right: 5.0pt,
+                                 bottom-right: 8.0pt,
+                                 bottom-left: 11.0pt), 
+                        width: 1.25cm)), 
+        dir: ltr, 
+        spacing: 1.0fr), 
+  parbreak(), 
+  text(body: [
+]), 
+  rect(fill: rgb(0%,100%,43%,100%), 
+       stroke: (x: 5.0pt, y: 1.0pt), 
+       width: 100%), 
+  parbreak() }
diff --git a/test/out/visualize/shape-rect-02.out b/test/out/visualize/shape-rect-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-rect-02.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/shape-rect-03.out b/test/out/visualize/shape-rect-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-rect-03.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/shape-rounded-00.out b/test/out/visualize/shape-rounded-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-rounded-00.out
@@ -0,0 +1,67 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-rounded-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-rounded-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-rounded-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-rounded-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg
+           (Identifier "radius") (Negated (Literal (Numeric 20.0 Pt)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-rounded-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "radius") (Literal (Numeric 30.0 Pt)) ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  rect(radius: -20.0pt), 
+  text(body: [
+]), 
+  square(radius: 30.0pt), 
+  parbreak() }
diff --git a/test/out/visualize/shape-square-00.out b/test/out/visualize/shape-square-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-square-00.out
@@ -0,0 +1,68 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-square-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-square-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-square-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-square-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg (FuncCall (Ident (Identifier "square")) []) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-square-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "box"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "square")) [ BlockArg [ Text "hey!" ] ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  box(body: square()), 
+  text(body: [
+]), 
+  box(body: square(body: text(body: [hey!]))), 
+  parbreak() }
diff --git a/test/out/visualize/shape-square-01.out b/test/out/visualize/shape-square-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-square-01.out
@@ -0,0 +1,77 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-square-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-square-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-square-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-square-01.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/visualize/shape-square-01.typ"
+               ( line 4 , column 4 )
+               (Set
+                  (Ident (Identifier "text"))
+                  [ KeyValArg (Identifier "fill") (Ident (Identifier "white"))
+                  , KeyValArg (Identifier "weight") (Literal (String "bold"))
+                  ])
+           , SoftBreak
+           , Text "Typst"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  square(body: { text(body: [
+]), 
+                 text(body: [
+Typst], 
+                      fill: rgb(100%,100%,100%,100%), 
+                      weight: "bold"), 
+                 parbreak() }, 
+         fill: rgb(13%,61%,67%,100%)), 
+  parbreak() }
diff --git a/test/out/visualize/shape-square-02.out b/test/out/visualize/shape-square-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-square-02.out
@@ -0,0 +1,90 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-square-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-square-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-square-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-square-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "eastern"))
+       , BlockArg
+           [ SoftBreak
+           , Code
+               "test/typ/visualize/shape-square-02.typ"
+               ( line 4 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "rect"))
+                  [ KeyValArg (Identifier "width") (Literal (Numeric 10.0 Pt))
+                  , KeyValArg (Identifier "height") (Literal (Numeric 5.0 Pt))
+                  , KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+                  ])
+           , SoftBreak
+           , Code
+               "test/typ/visualize/shape-square-02.typ"
+               ( line 5 , column 4 )
+               (FuncCall
+                  (Ident (Identifier "rect"))
+                  [ KeyValArg (Identifier "width") (Literal (Numeric 40.0 Percent))
+                  , KeyValArg (Identifier "height") (Literal (Numeric 5.0 Pt))
+                  , KeyValArg (Identifier "stroke") (Ident (Identifier "green"))
+                  ])
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  square(body: { text(body: [
+]), 
+                 rect(fill: rgb(18%,80%,25%,100%), 
+                      height: 5.0pt, 
+                      width: 10.0pt), 
+                 text(body: [
+]), 
+                 rect(height: 5.0pt, 
+                      stroke: rgb(18%,80%,25%,100%), 
+                      width: 40%), 
+                 parbreak() }, 
+         fill: rgb(13%,61%,67%,100%)), 
+  parbreak() }
diff --git a/test/out/visualize/shape-square-03.out b/test/out/visualize/shape-square-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-square-03.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-square-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-square-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-square-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-square-03.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 75.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 100.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-square-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , BlockArg
+           [ SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , Text "yonder"
+           , Space
+           , Text "window"
+           , Space
+           , Text "breaks?"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  square(body: { text(body: [
+But, soft! what light through yonder window breaks?]), 
+                 parbreak() }, 
+         fill: rgb(18%,80%,25%,100%)), 
+  parbreak() }
diff --git a/test/out/visualize/shape-square-04.out b/test/out/visualize/shape-square-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-square-04.out
@@ -0,0 +1,89 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/shape-square-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/shape-square-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/shape-square-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/shape-square-04.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 100.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 75.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/shape-square-04.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "square"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "green"))
+       , BlockArg
+           [ SoftBreak
+           , Text "But,"
+           , Space
+           , Text "soft!"
+           , Space
+           , Text "what"
+           , Space
+           , Text "light"
+           , Space
+           , Text "through"
+           , Space
+           , Text "yonder"
+           , Space
+           , Text "window"
+           , Space
+           , Text "breaks?"
+           , ParBreak
+           ]
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  square(body: { text(body: [
+But, soft! what light through yonder window breaks?]), 
+                 parbreak() }, 
+         fill: rgb(18%,80%,25%,100%)), 
+  parbreak() }
diff --git a/test/out/visualize/shape-square-05.out b/test/out/visualize/shape-square-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/shape-square-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/stroke-00.out b/test/out/visualize/stroke-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-00.out
@@ -0,0 +1,165 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/stroke-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/stroke-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg (Identifier "stroke") (Ident (Identifier "red"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg (Identifier "stroke") (Literal (Numeric 2.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Ident (Identifier "blue")) (Literal (Numeric 1.5 Pt)))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 1.0 Pt) )
+              , ( Identifier "dash" , Literal (String "dashed") )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 4.0 Pt) )
+              , ( Identifier "cap" , Literal (String "round") )
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: rgb(100%,25%,21%,100%)), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: 2.0pt), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (thickness: 1.5pt,
+                color: rgb(0%,45%,85%,100%))), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 1.0pt,
+                dash: "dashed")), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 4.0pt,
+                cap: "round")), 
+  parbreak() }
diff --git a/test/out/visualize/stroke-01.out b/test/out/visualize/stroke-01.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-01.out
@@ -0,0 +1,122 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/stroke-01.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/stroke-01.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/stroke-01.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/stroke-01.typ"
+    ( line 3 , column 2 )
+    (Set
+       (Ident (Identifier "line"))
+       [ KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 1.0 Pt) )
+              , ( Identifier "cap" , Literal (String "butt") )
+              , ( Identifier "dash" , Literal (String "dash-dotted") )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-01.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-01.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-01.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg (Identifier "stroke") (Ident (Identifier "blue"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-01.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-01.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict [ ( Identifier "dash" , Literal None ) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 1.0pt,
+                cap: "butt",
+                dash: "dash-dotted")), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: rgb(0%,45%,85%,100%)), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (dash: none)), 
+  parbreak() }
diff --git a/test/out/visualize/stroke-02.out b/test/out/visualize/stroke-02.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-02.out
@@ -0,0 +1,126 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/stroke-02.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/stroke-02.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/stroke-02.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/stroke-02.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "stroke") (Ident (Identifier "red"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-02.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-02.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "rest" , Ident (Identifier "red") )
+              , ( Identifier "top"
+                , Dict
+                    [ ( Identifier "paint" , Ident (Identifier "blue") )
+                    , ( Identifier "dash" , Literal (String "dashed") )
+                    ]
+                )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-02.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-02.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 20.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 20.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "thickness" , Literal (Numeric 5.0 Pt) )
+              , ( Identifier "join" , Literal (String "round") )
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  rect(height: 20.0pt, 
+       stroke: rgb(100%,25%,21%,100%), 
+       width: 20.0pt), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  rect(height: 20.0pt, 
+       stroke: (rest: rgb(100%,25%,21%,100%),
+                top: (paint: rgb(0%,45%,85%,100%),
+                      dash: "dashed")), 
+       width: 20.0pt), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  rect(height: 20.0pt, 
+       stroke: (thickness: 5.0pt,
+                join: "round"), 
+       width: 20.0pt), 
+  parbreak() }
diff --git a/test/out/visualize/stroke-03.out b/test/out/visualize/stroke-03.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-03.out
@@ -0,0 +1,222 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/stroke-03.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/stroke-03.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 1.0 Pt) )
+              , ( Identifier "dash"
+                , Array [ Literal (String "dot") , Literal (Numeric 1.0 Pt) ]
+                )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 1.0 Pt) )
+              , ( Identifier "dash"
+                , Array
+                    [ Literal (String "dot")
+                    , Literal (Numeric 1.0 Pt)
+                    , Literal (Numeric 4.0 Pt)
+                    , Literal (Numeric 2.0 Pt)
+                    ]
+                )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 1.0 Pt) )
+              , ( Identifier "dash"
+                , Dict
+                    [ ( Identifier "array"
+                      , Array
+                          [ Literal (String "dot")
+                          , Literal (Numeric 1.0 Pt)
+                          , Literal (Numeric 4.0 Pt)
+                          , Literal (Numeric 2.0 Pt)
+                          ]
+                      )
+                    , ( Identifier "phase" , Literal (Numeric 5.0 Pt) )
+                    ]
+                )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 1.0 Pt) )
+              , ( Identifier "dash" , Array [] )
+              ])
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "v")) [ NormalArg (Literal (Numeric 3.0 Pt)) ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-03.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 60.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 1.0 Pt) )
+              , ( Identifier "dash"
+                , Array
+                    [ Literal (Numeric 1.0 Pt)
+                    , Literal (Numeric 3.0 Pt)
+                    , Literal (Numeric 9.0 Pt)
+                    ]
+                )
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 1.0pt,
+                dash: ("dot", 1.0pt))), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 1.0pt,
+                dash: ("dot", 
+                       1.0pt, 
+                       4.0pt, 
+                       2.0pt))), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 1.0pt,
+                dash: (array: ("dot", 
+                               1.0pt, 
+                               4.0pt, 
+                               2.0pt),
+                       phase: 5.0pt))), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 1.0pt,
+                dash: ())), 
+  text(body: [
+]), 
+  v(amount: 3.0pt), 
+  text(body: [
+]), 
+  line(length: 60.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 1.0pt,
+                dash: (1.0pt, 
+                       3.0pt, 
+                       9.0pt))), 
+  parbreak() }
diff --git a/test/out/visualize/stroke-04.out b/test/out/visualize/stroke-04.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-04.out
@@ -0,0 +1,164 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/stroke-04.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/stroke-04.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/stroke-04.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/visualize/stroke-04.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "stack"))
+       [ KeyValArg (Identifier "dir") (Ident (Identifier "ltr"))
+       , KeyValArg (Identifier "spacing") (Literal (Numeric 1.0 Em))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "polygon"))
+              [ KeyValArg
+                  (Identifier "stroke")
+                  (Dict
+                     [ ( Identifier "thickness" , Literal (Numeric 4.0 Pt) )
+                     , ( Identifier "paint" , Ident (Identifier "blue") )
+                     , ( Identifier "join" , Literal (String "round") )
+                     ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 20.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 40.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 45.0 Pt) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "polygon"))
+              [ KeyValArg
+                  (Identifier "stroke")
+                  (Dict
+                     [ ( Identifier "thickness" , Literal (Numeric 4.0 Pt) )
+                     , ( Identifier "paint" , Ident (Identifier "blue") )
+                     , ( Identifier "join" , Literal (String "bevel") )
+                     ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 20.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 40.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 45.0 Pt) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "polygon"))
+              [ KeyValArg
+                  (Identifier "stroke")
+                  (Dict
+                     [ ( Identifier "thickness" , Literal (Numeric 4.0 Pt) )
+                     , ( Identifier "paint" , Ident (Identifier "blue") )
+                     , ( Identifier "join" , Literal (String "miter") )
+                     ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 20.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 40.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 45.0 Pt) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "polygon"))
+              [ KeyValArg
+                  (Identifier "stroke")
+                  (Dict
+                     [ ( Identifier "thickness" , Literal (Numeric 4.0 Pt) )
+                     , ( Identifier "paint" , Ident (Identifier "blue") )
+                     , ( Identifier "join" , Literal (String "miter") )
+                     , ( Identifier "miter-limit" , Literal (Float 20.0) )
+                     ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 20.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 0.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 0.0 Pt) , Literal (Numeric 40.0 Pt) ])
+              , NormalArg
+                  (Array [ Literal (Numeric 15.0 Pt) , Literal (Numeric 45.0 Pt) ])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  stack(children: (polygon(stroke: (thickness: 4.0pt,
+                                    paint: rgb(0%,45%,85%,100%),
+                                    join: "round"), 
+                           vertices: ((0.0pt, 20.0pt), 
+                                      (15.0pt, 0.0pt), 
+                                      (0.0pt, 40.0pt), 
+                                      (15.0pt, 45.0pt))), 
+                   polygon(stroke: (thickness: 4.0pt,
+                                    paint: rgb(0%,45%,85%,100%),
+                                    join: "bevel"), 
+                           vertices: ((0.0pt, 20.0pt), 
+                                      (15.0pt, 0.0pt), 
+                                      (0.0pt, 40.0pt), 
+                                      (15.0pt, 45.0pt))), 
+                   polygon(stroke: (thickness: 4.0pt,
+                                    paint: rgb(0%,45%,85%,100%),
+                                    join: "miter"), 
+                           vertices: ((0.0pt, 20.0pt), 
+                                      (15.0pt, 0.0pt), 
+                                      (0.0pt, 40.0pt), 
+                                      (15.0pt, 45.0pt))), 
+                   polygon(stroke: (thickness: 4.0pt,
+                                    paint: rgb(0%,45%,85%,100%),
+                                    join: "miter",
+                                    miter-limit: 20.0), 
+                           vertices: ((0.0pt, 20.0pt), 
+                                      (15.0pt, 0.0pt), 
+                                      (0.0pt, 40.0pt), 
+                                      (15.0pt, 45.0pt)))), 
+        dir: ltr, 
+        spacing: 1.0em), 
+  parbreak() }
diff --git a/test/out/visualize/stroke-05.out b/test/out/visualize/stroke-05.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-05.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/stroke-06.out b/test/out/visualize/stroke-06.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-06.out
@@ -0,0 +1,2 @@
+--- skipped ---
+
diff --git a/test/out/visualize/stroke-07.out b/test/out/visualize/stroke-07.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/stroke-07.out
@@ -0,0 +1,285 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/stroke-07.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/stroke-07.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "stroke") (Literal None)
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "stroke") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "stroke") (Literal None)
+       , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "rect"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 10.0 Pt))
+       , KeyValArg (Identifier "height") (Literal (Numeric 10.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 0.0 Pt)) (Ident (Identifier "red")))
+       , KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+       ])
+, ParBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Pt))
+       , KeyValArg (Identifier "stroke") (Literal (Numeric 0.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "line"))
+       [ KeyValArg (Identifier "length") (Literal (Numeric 30.0 Pt))
+       , KeyValArg
+           (Identifier "stroke")
+           (Dict
+              [ ( Identifier "paint" , Ident (Identifier "red") )
+              , ( Identifier "thickness" , Literal (Numeric 0.0 Pt) )
+              , ( Identifier "dash"
+                , Array [ Literal (String "dot") , Literal (Numeric 1.0 Pt) ]
+                )
+              ])
+       ])
+, ParBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 2))
+       , KeyValArg (Identifier "stroke") (Literal None)
+       , BlockArg [ Text "A" ]
+       , BlockArg [ Text "B" ]
+       ])
+, SoftBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 13 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg (Identifier "columns") (Literal (Int 2))
+       , KeyValArg (Identifier "stroke") (Literal (Numeric 0.0 Pt))
+       , BlockArg [ Text "A" ]
+       , BlockArg [ Text "B" ]
+       ])
+, ParBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 15 , column 2 )
+    (FuncCall
+       (Ident (Identifier "path"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , KeyValArg (Identifier "stroke") (Literal None)
+       , KeyValArg (Identifier "closed") (Literal (Boolean True))
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 0.0 Percent) , Literal (Numeric 0.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent)
+                  , Negated (Literal (Numeric 4.0 Percent))
+                  ]
+              ])
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 50.0 Percent) , Literal (Numeric 50.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent)
+                  , Negated (Literal (Numeric 4.0 Percent))
+                  ]
+              ])
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 0.0 Percent) , Literal (Numeric 50.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent) , Literal (Numeric 4.0 Percent) ]
+              ])
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 50.0 Percent) , Literal (Numeric 0.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent) , Literal (Numeric 4.0 Percent) ]
+              ])
+       ])
+, ParBreak
+, Code
+    "test/typ/visualize/stroke-07.typ"
+    ( line 25 , column 2 )
+    (FuncCall
+       (Ident (Identifier "path"))
+       [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+       , KeyValArg (Identifier "stroke") (Literal (Numeric 0.0 Pt))
+       , KeyValArg (Identifier "closed") (Literal (Boolean True))
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 0.0 Percent) , Literal (Numeric 0.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent)
+                  , Negated (Literal (Numeric 4.0 Percent))
+                  ]
+              ])
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 50.0 Percent) , Literal (Numeric 50.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent)
+                  , Negated (Literal (Numeric 4.0 Percent))
+                  ]
+              ])
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 0.0 Percent) , Literal (Numeric 50.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent) , Literal (Numeric 4.0 Percent) ]
+              ])
+       , NormalArg
+           (Array
+              [ Array
+                  [ Literal (Numeric 50.0 Percent) , Literal (Numeric 0.0 Percent) ]
+              , Array
+                  [ Literal (Numeric 4.0 Percent) , Literal (Numeric 4.0 Percent) ]
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  text(body: [
+]), 
+  rect(height: 10.0pt, 
+       stroke: none, 
+       width: 10.0pt), 
+  text(body: [
+]), 
+  rect(height: 10.0pt, 
+       stroke: 0.0pt, 
+       width: 10.0pt), 
+  text(body: [
+]), 
+  rect(fill: rgb(0%,45%,85%,100%), 
+       height: 10.0pt, 
+       stroke: none, 
+       width: 10.0pt), 
+  text(body: [
+]), 
+  rect(fill: rgb(0%,45%,85%,100%), 
+       height: 10.0pt, 
+       stroke: (thickness: 0.0pt,
+                color: rgb(100%,25%,21%,100%)), 
+       width: 10.0pt), 
+  parbreak(), 
+  line(length: 30.0pt, 
+       stroke: 0.0pt), 
+  text(body: [
+]), 
+  line(length: 30.0pt, 
+       stroke: (paint: rgb(100%,25%,21%,100%),
+                thickness: 0.0pt,
+                dash: ("dot", 1.0pt))), 
+  parbreak(), 
+  table(children: (text(body: [A]), 
+                   text(body: [B])), 
+        columns: 2, 
+        stroke: none), 
+  text(body: [
+]), 
+  table(children: (text(body: [A]), 
+                   text(body: [B])), 
+        columns: 2, 
+        stroke: 0.0pt), 
+  parbreak(), 
+  path(closed: true, 
+       fill: rgb(100%,25%,21%,100%), 
+       stroke: none, 
+       vertices: (((0%, 0%), 
+                   (4%, -4%)), 
+                  ((50%, 50%), (4%, -4%)), 
+                  ((0%, 50%), (4%, 4%)), 
+                  ((50%, 0%), (4%, 4%)))), 
+  parbreak(), 
+  path(closed: true, 
+       fill: rgb(100%,25%,21%,100%), 
+       stroke: 0.0pt, 
+       vertices: (((0%, 0%), 
+                   (4%, -4%)), 
+                  ((50%, 50%), (4%, -4%)), 
+                  ((0%, 50%), (4%, 4%)), 
+                  ((50%, 0%), (4%, 4%)))), 
+  parbreak() }
diff --git a/test/out/visualize/svg-text-00.out b/test/out/visualize/svg-text-00.out
new file mode 100644
--- /dev/null
+++ b/test/out/visualize/svg-text-00.out
@@ -0,0 +1,72 @@
+--- parse tree ---
+[ Code
+    "test/typ/visualize/svg-text-00.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/visualize/svg-text-00.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/visualize/svg-text-00.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/visualize/svg-text-00.typ"
+    ( line 2 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "width") (Literal (Numeric 250.0 Pt)) ])
+, ParBreak
+, Code
+    "test/typ/visualize/svg-text-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "figure"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "image"))
+              [ NormalArg (Literal (String "test/assets/files/diagram.svg")) ])
+       , KeyValArg
+           (Identifier "caption")
+           (Block
+              (Content
+                 [ Text "A" , Space , Text "textful" , Space , Text "diagram" ]))
+       ])
+, ParBreak
+]
+--- evaluated ---
+{ text(body: [
+]), 
+  parbreak(), 
+  figure(body: image(path: "test/assets/files/diagram.svg"), 
+         caption: text(body: [A textful diagram])), 
+  parbreak() }
diff --git a/test/typ/bugs/args-sink-00.typ b/test/typ/bugs/args-sink-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/args-sink-00.typ
@@ -0,0 +1,2 @@
+#let foo(..body) = repr(body.pos())
+#foo(a: "1", b: "2", 1, 2, 3, 4, 5, 6)
diff --git a/test/typ/bugs/args-underscore-00.typ b/test/typ/bugs/args-underscore-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/args-underscore-00.typ
@@ -0,0 +1,1 @@
+#test((1, 2, 3).map(_ => {}).len(), 3)
diff --git a/test/typ/bugs/columns-1-00.typ b/test/typ/bugs/columns-1-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/columns-1-00.typ
@@ -0,0 +1,9 @@
+#set page(height: 70pt)
+
+Hallo
+#columns(2)[
+  = A
+  Text
+  = B
+  Text
+]
diff --git a/test/typ/bugs/flow-1-00.typ b/test/typ/bugs/flow-1-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/flow-1-00.typ
@@ -0,0 +1,6 @@
+#set page(height: 70pt)
+#block[This file tests a bug where an almost empty page occurs.]
+#block[
+  The text in this second block was torn apart and split up for
+  some reason beyond my knowledge.
+]
diff --git a/test/typ/bugs/flow-2-00.typ b/test/typ/bugs/flow-2-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/flow-2-00.typ
@@ -0,0 +1,6 @@
+#set page(height: 60pt)
+#v(19pt)
+#block[
+  But, soft! what light through yonder window breaks?
+  It is the east, and Juliet is the sun.
+]
diff --git a/test/typ/bugs/flow-3-00.typ b/test/typ/bugs/flow-3-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/flow-3-00.typ
@@ -0,0 +1,8 @@
+#set page(height: 60pt)
+#rect(inset: 0pt, columns(2)[
+  Text
+  #v(12pt)
+  Hi
+  #v(10pt, weak: true)
+  At column break.
+])
diff --git a/test/typ/bugs/flow-4-00.typ b/test/typ/bugs/flow-4-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/flow-4-00.typ
@@ -0,0 +1,2 @@
+#set page(height: 105pt)
+#block(lorem(20))
diff --git a/test/typ/bugs/grid-1-00.typ b/test/typ/bugs/grid-1-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/grid-1-00.typ
@@ -0,0 +1,9 @@
+#set page(height: 150pt)
+#table(
+  columns: (1.5cm, auto),
+  rows: (auto, auto),
+  rect(width: 100%, fill: red),
+  rect(width: 100%, fill: blue),
+  rect(width: 100%, height: 50%, fill: green),
+)
+
diff --git a/test/typ/bugs/grid-1-01.typ b/test/typ/bugs/grid-1-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/grid-1-01.typ
@@ -0,0 +1,3 @@
+#rect(width: 100%, height: 1em)
+- #rect(width: 100%, height: 1em)
+  - #rect(width: 100%, height: 1em)
diff --git a/test/typ/bugs/grid-2-00.typ b/test/typ/bugs/grid-2-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/grid-2-00.typ
@@ -0,0 +1,12 @@
+#set page(height: 100pt)
+#grid(
+  columns: (2cm, auto),
+  rows: (auto, auto),
+  rect(width: 100%, fill: red),
+  rect(width: 100%, fill: blue),
+  rect(width: 100%, height: 80%, fill: green),
+  [hello \ darkness #parbreak my \ old \ friend \ I],
+  rect(width: 100%, height: 20%, fill: blue),
+  polygon(fill: red, (0%, 0%), (100%, 0%), (100%, 20%))
+)
+
diff --git a/test/typ/bugs/grid-2-01.typ b/test/typ/bugs/grid-2-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/grid-2-01.typ
@@ -0,0 +1,3 @@
+#set page(height: 60pt)
+#lorem(5)
+- #lorem(5)
diff --git a/test/typ/bugs/grid-3-00.typ b/test/typ/bugs/grid-3-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/grid-3-00.typ
@@ -0,0 +1,5 @@
+#set page(height: 70pt)
+#v(40pt)
+The following:
++ A
++ B
diff --git a/test/typ/bugs/math-realize-00.typ b/test/typ/bugs/math-realize-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/math-realize-00.typ
@@ -0,0 +1,12 @@
+#let my = $pi$
+#let f1 = box(baseline: 10pt, [f])
+#let f2 = style(sty => f1)
+#show math.vec: [nope]
+
+$ pi a $
+$ my a $
+$ 1 + sqrt(x/2) + sqrt(#hide($x/2$)) $
+$ a x #link("url", $+ b$) $
+$ f f1 f2 $
+$ vec(1,2) * 2 $
+
diff --git a/test/typ/bugs/math-realize-01.typ b/test/typ/bugs/math-realize-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/math-realize-01.typ
@@ -0,0 +1,4 @@
+$ x^2 #hide[$(>= phi.alt) union y^2 0$] z^2 $
+Hello #hide[there $x$]
+and #hide[$ f(x) := x^2 $]
+
diff --git a/test/typ/bugs/math-realize-02.typ b/test/typ/bugs/math-realize-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/math-realize-02.typ
@@ -0,0 +1,25 @@
+// Test equations can embed equation pieces built by functions
+#let foo(v1, v2) = {
+  // Return an equation piece that would've been rendered in
+  // inline style if the piece is not embedded
+  $v1 v2^2$
+}
+#let bar(v1, v2) = {
+  // Return an equation piece that would've been rendered in
+  // block style if the piece is not embedded
+  $ v1 v2^2 $
+}
+#let baz(..sink) = {
+  // Return an equation piece built by joining arrays
+  sink.pos().map(x => $hat(#x)$).join(sym.and)
+}
+
+Inline $2 foo(alpha, (M+foo(a, b)))$.
+
+Inline $2 bar(alpha, (M+foo(a, b)))$.
+
+Inline $2 baz(x,y,baz(u, v))$.
+
+$ 2 foo(alpha, (M+foo(a, b))) $
+$ 2 bar(alpha, (M+foo(a, b))) $
+$ 2 baz(x,y,baz(u, v)) $
diff --git a/test/typ/bugs/parameter-pattern-00.typ b/test/typ/bugs/parameter-pattern-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/parameter-pattern-00.typ
@@ -0,0 +1,1 @@
+#test((1, 2, 3).zip((1, 2, 3)).map(((_, x)) => x), (1, 2, 3))
diff --git a/test/typ/bugs/place-base-00.typ b/test/typ/bugs/place-base-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/place-base-00.typ
@@ -0,0 +1,4 @@
+#set page(height: 80pt, margin: 0pt)
+#place(right, dx: -70%, dy: 20%, [First])
+#place(left, dx: 20%, dy: 60%, [Second])
+#place(center + horizon, dx: 25%, dy: 25%, [Third])
diff --git a/test/typ/bugs/smartquotes-in-outline-00.typ b/test/typ/bugs/smartquotes-in-outline-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/smartquotes-in-outline-00.typ
@@ -0,0 +1,4 @@
+#set page(width: 15em)
+#outline()
+
+= "This" "is" "a" "test"
diff --git a/test/typ/bugs/square-base-00.typ b/test/typ/bugs/square-base-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/bugs/square-base-00.typ
@@ -0,0 +1,2 @@
+#set page(height: 80pt)
+#square(width: 40%, rect(width: 60%, height: 80%))
diff --git a/test/typ/coma-00.typ b/test/typ/coma-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/coma-00.typ
@@ -0,0 +1,24 @@
+#set page(width: 450pt, margin: 1cm)
+
+*Technische Universität Berlin* #h(1fr) *WiSe 2019/2020* \
+*Fakultät II, Institut for Mathematik* #h(1fr) Woche 3 \
+Sekretariat MA \
+Dr. Max Mustermann \
+Ola Nordmann, John Doe
+
+#v(3mm)
+#align(center)[
+  #set par(leading: 3mm)
+  #text(1.2em)[*3. Übungsblatt Computerorientierte Mathematik II*] \
+  *Abgabe: 03.05.2019* (bis 10:10 Uhr in MA 001) \
+  *Alle Antworten sind zu beweisen.*
+]
+
+*1. Aufgabe* #h(1fr) (1 + 1 + 2 Punkte)
+
+Ein _Binärbaum_ ist ein Wurzelbaum, in dem jeder Knoten ≤ 2 Kinder hat.
+Die Tiefe eines Knotens _v_ ist die Länge des eindeutigen Weges von der Wurzel
+zu _v_, und die Höhe von _v_ ist die Länge eines längsten (absteigenden) Weges
+von _v_ zu einem Blatt. Die Höhe des Baumes ist die Höhe der Wurzel.
+
+#align(center, image("/graph.png", width: 75%))
diff --git a/test/typ/compiler/array-00.typ b/test/typ/compiler/array-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-00.typ
@@ -0,0 +1,21 @@
+// Ref: true
+
+#set page(width: 150pt)
+
+// Empty.
+#()
+
+// Not an array, just a parenthesized expression.
+#(1)
+
+// One item and trailing comma.
+#(-1,)
+
+// No trailing comma.
+#(true, false)
+
+// Multiple lines and items and trailing comma.
+#("1"
+    , rgb("002")
+    ,)
+
diff --git a/test/typ/compiler/array-01.typ b/test/typ/compiler/array-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-01.typ
@@ -0,0 +1,4 @@
+// Test the `len` method.
+#test(().len(), 0)
+#test(("A", "B", "C").len(), 3)
+
diff --git a/test/typ/compiler/array-02.typ b/test/typ/compiler/array-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-02.typ
@@ -0,0 +1,7 @@
+// Test lvalue and rvalue access.
+#{
+  let array = (1, 2)
+  array.at(1) += 5 + array.at(0)
+  test(array, (1, 8))
+}
+
diff --git a/test/typ/compiler/array-03.typ b/test/typ/compiler/array-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-03.typ
@@ -0,0 +1,8 @@
+// Test different lvalue method.
+#{
+  let array = (1, 2, 3)
+  array.first() = 7
+  array.at(1) *= 8
+  test(array, (7, 16, 3))
+}
+
diff --git a/test/typ/compiler/array-04.typ b/test/typ/compiler/array-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-04.typ
@@ -0,0 +1,4 @@
+// Test rvalue out of bounds.
+// Error: 2-17 array index out of bounds (index: 5, len: 3) and no default value was specified
+#(1, 2, 3).at(5)
+
diff --git a/test/typ/compiler/array-05.typ b/test/typ/compiler/array-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-05.typ
@@ -0,0 +1,7 @@
+// Test lvalue out of bounds.
+#{
+  let array = (1, 2, 3)
+  // Error: 3-14 array index out of bounds (index: 3, len: 3) and no default value was specified
+  array.at(3) = 5
+}
+
diff --git a/test/typ/compiler/array-06.typ b/test/typ/compiler/array-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-06.typ
@@ -0,0 +1,4 @@
+// Test default value.
+#test((1, 2, 3).at(2, default: 5), 3)
+#test((1, 2, 3).at(3, default: 5), 5)
+
diff --git a/test/typ/compiler/array-07.typ b/test/typ/compiler/array-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-07.typ
@@ -0,0 +1,5 @@
+// Test bad lvalue.
+// Error: 2:3-2:14 cannot mutate a temporary value
+#let array = (1, 2, 3)
+#(array.len() = 4)
+
diff --git a/test/typ/compiler/array-08.typ b/test/typ/compiler/array-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-08.typ
@@ -0,0 +1,5 @@
+// Test bad lvalue.
+// Error: 2:3-2:15 type array has no method `yolo`
+#let array = (1, 2, 3)
+#(array.yolo() = 4)
+
diff --git a/test/typ/compiler/array-09.typ b/test/typ/compiler/array-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-09.typ
@@ -0,0 +1,10 @@
+// Test negative indices.
+#{
+  let array = (1, 2, 3, 4)
+  test(array.at(0), 1)
+  test(array.at(-1), 4)
+  test(array.at(-2), 3)
+  test(array.at(-3), 2)
+  test(array.at(-4), 1)
+}
+
diff --git a/test/typ/compiler/array-10.typ b/test/typ/compiler/array-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-10.typ
@@ -0,0 +1,6 @@
+// The the `first` and `last` methods.
+#test((1,).first(), 1)
+#test((2,).last(), 2)
+#test((1, 2, 3).first(), 1)
+#test((1, 2, 3).last(), 3)
+
diff --git a/test/typ/compiler/array-11.typ b/test/typ/compiler/array-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-11.typ
@@ -0,0 +1,3 @@
+// Error: 2-12 array is empty
+#().first()
+
diff --git a/test/typ/compiler/array-12.typ b/test/typ/compiler/array-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-12.typ
@@ -0,0 +1,3 @@
+// Error: 2-11 array is empty
+#().last()
+
diff --git a/test/typ/compiler/array-13.typ b/test/typ/compiler/array-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-13.typ
@@ -0,0 +1,9 @@
+// Test the `push` and `pop` methods.
+#{
+  let tasks = (a: (1, 2, 3), b: (4, 5, 6))
+  test(tasks.at("a").pop(), 3)
+  tasks.b.push(7)
+  test(tasks.a, (1, 2))
+  test(tasks.at("b"), (4, 5, 6, 7))
+}
+
diff --git a/test/typ/compiler/array-14.typ b/test/typ/compiler/array-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-14.typ
@@ -0,0 +1,9 @@
+// Test the `insert` and `remove` methods.
+#{
+  let array = (0, 1, 2, 4, 5)
+  array.insert(3, 3)
+  test(array, range(6))
+  array.remove(1)
+  test(array, (0, 2, 3, 4, 5))
+}
+
diff --git a/test/typ/compiler/array-15.typ b/test/typ/compiler/array-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-15.typ
@@ -0,0 +1,4 @@
+// Error: 2:16-2:18 missing argument: index
+#let numbers = ()
+#numbers.insert()
+
diff --git a/test/typ/compiler/array-16.typ b/test/typ/compiler/array-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-16.typ
@@ -0,0 +1,10 @@
+// Test the `slice` method.
+#test((1, 2, 3, 4).slice(2), (3, 4))
+#test(range(10).slice(2, 6), (2, 3, 4, 5))
+#test(range(10).slice(4, count: 3), (4, 5, 6))
+#test(range(10).slice(-5, count: 2), (5, 6))
+#test((1, 2, 3).slice(2, -2), ())
+#test((1, 2, 3).slice(-2, 2), (2,))
+#test((1, 2, 3).slice(-3, 2), (1, 2))
+#test("ABCD".split("").slice(1, -1).join("-"), "A-B-C-D")
+
diff --git a/test/typ/compiler/array-17.typ b/test/typ/compiler/array-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-17.typ
@@ -0,0 +1,3 @@
+// Error: 2-30 array index out of bounds (index: 12, len: 10)
+#range(10).slice(9, count: 3)
+
diff --git a/test/typ/compiler/array-18.typ b/test/typ/compiler/array-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-18.typ
@@ -0,0 +1,3 @@
+// Error: 2-24 array index out of bounds (index: -4, len: 3)
+#(1, 2, 3).slice(0, -4)
+
diff --git a/test/typ/compiler/array-19.typ b/test/typ/compiler/array-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-19.typ
@@ -0,0 +1,5 @@
+// Test the `position` method.
+#test(("Hi", "❤️", "Love").position(s => s == "❤️"), 1)
+#test(("Bye", "💘", "Apart").position(s => s == "❤️"), none)
+#test(("A", "B", "CDEF", "G").position(v => v.len() > 2), 2)
+
diff --git a/test/typ/compiler/array-20.typ b/test/typ/compiler/array-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-20.typ
@@ -0,0 +1,5 @@
+// Test the `filter` method.
+#test(().filter(calc.even), ())
+#test((1, 2, 3, 4).filter(calc.even), (2, 4))
+#test((7, 3, 2, 5, 1).filter(x => x < 5), (3, 2, 1))
+
diff --git a/test/typ/compiler/array-21.typ b/test/typ/compiler/array-21.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-21.typ
@@ -0,0 +1,4 @@
+// Test the `map` method.
+#test(().map(x => x * 2), ())
+#test((2, 3).map(x => x * 2), (4, 6))
+
diff --git a/test/typ/compiler/array-22.typ b/test/typ/compiler/array-22.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-22.typ
@@ -0,0 +1,4 @@
+// Test the `fold` method.
+#test(().fold("hi", grid), "hi")
+#test((1, 2, 3, 4).fold(0, (s, x) => s + x), 10)
+
diff --git a/test/typ/compiler/array-23.typ b/test/typ/compiler/array-23.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-23.typ
@@ -0,0 +1,3 @@
+// Error: 20-22 unexpected argument
+#(1, 2, 3).fold(0, () => none)
+
diff --git a/test/typ/compiler/array-24.typ b/test/typ/compiler/array-24.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-24.typ
@@ -0,0 +1,5 @@
+// Test the `sum` method.
+#test(().sum(default: 0), 0)
+#test(().sum(default: []), [])
+#test((1, 2, 3).sum(), 6)
+
diff --git a/test/typ/compiler/array-25.typ b/test/typ/compiler/array-25.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-25.typ
@@ -0,0 +1,3 @@
+// Error: 2-10 cannot calculate sum of empty array with no default
+#().sum()
+
diff --git a/test/typ/compiler/array-26.typ b/test/typ/compiler/array-26.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-26.typ
@@ -0,0 +1,6 @@
+// Test the `product` method.
+#test(().product(default: 0), 0)
+#test(().product(default: []), [])
+#test(([ab], 3).product(), [ab]*3)
+#test((1, 2, 3).product(), 6)
+
diff --git a/test/typ/compiler/array-27.typ b/test/typ/compiler/array-27.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-27.typ
@@ -0,0 +1,3 @@
+// Error: 2-14 cannot calculate product of empty array with no default
+#().product()
+
diff --git a/test/typ/compiler/array-28.typ b/test/typ/compiler/array-28.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-28.typ
@@ -0,0 +1,3 @@
+// Test the `rev` method.
+#test(range(3).rev(), (2, 1, 0))
+
diff --git a/test/typ/compiler/array-29.typ b/test/typ/compiler/array-29.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-29.typ
@@ -0,0 +1,6 @@
+// Test the `join` method.
+#test(().join(), none)
+#test((1,).join(), 1)
+#test(("a", "b", "c").join(), "abc")
+#test("(" + ("a", "b", "c").join(", ") + ")", "(a, b, c)")
+
diff --git a/test/typ/compiler/array-30.typ b/test/typ/compiler/array-30.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-30.typ
@@ -0,0 +1,3 @@
+// Error: 2-22 cannot join boolean with boolean
+#(true, false).join()
+
diff --git a/test/typ/compiler/array-31.typ b/test/typ/compiler/array-31.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-31.typ
@@ -0,0 +1,3 @@
+// Error: 2-20 cannot join string with integer
+#("a", "b").join(1)
+
diff --git a/test/typ/compiler/array-32.typ b/test/typ/compiler/array-32.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-32.typ
@@ -0,0 +1,4 @@
+// Test joining content.
+// Ref: true
+#([One], [Two], [Three]).join([, ], last: [ and ]).
+
diff --git a/test/typ/compiler/array-33.typ b/test/typ/compiler/array-33.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-33.typ
@@ -0,0 +1,11 @@
+// Test the `sorted` method.
+#test(().sorted(), ())
+#test(().sorted(key: x => x), ())
+#test(((true, false) * 10).sorted(), (false,) * 10 + (true,) * 10)
+#test(("it", "the", "hi", "text").sorted(), ("hi", "it", "text", "the"))
+#test(("I", "the", "hi", "text").sorted(key: x => x), ("I", "hi", "text", "the"))
+#test(("I", "the", "hi", "text").sorted(key: x => x.len()), ("I", "hi", "the", "text"))
+#test((2, 1, 3, 10, 5, 8, 6, -7, 2).sorted(), (-7, 1, 2, 2, 3, 5, 6, 8, 10))
+#test((2, 1, 3, -10, -5, 8, 6, -7, 2).sorted(key: x => x), (-10, -7, -5, 1, 2, 2, 3, 6, 8))
+#test((2, 1, 3, -10, -5, 8, 6, -7, 2).sorted(key: x => x * x), (1, 2, 2, 3, -5, 6, -7, 8, -10))
+
diff --git a/test/typ/compiler/array-34.typ b/test/typ/compiler/array-34.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-34.typ
@@ -0,0 +1,10 @@
+// Test the `zip` method.
+#test(().zip(()), ())
+#test((1,).zip(()), ())
+#test((1,).zip((2,)), ((1, 2),))
+#test((1, 2).zip((3, 4)), ((1, 3), (2, 4)))
+#test((1, 2, 3, 4).zip((5, 6)), ((1, 5), (2, 6)))
+#test(((1, 2), 3).zip((4, 5)), (((1, 2), 4), (3, 5)))
+#test((1, "hi").zip((true, false)), ((1, true), ("hi", false)))
+
+
diff --git a/test/typ/compiler/array-35.typ b/test/typ/compiler/array-35.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-35.typ
@@ -0,0 +1,3 @@
+// Error: 32-37 cannot divide by zero
+#(1, 2, 0, 3).sorted(key: x => 5 / x)
+
diff --git a/test/typ/compiler/array-36.typ b/test/typ/compiler/array-36.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-36.typ
@@ -0,0 +1,3 @@
+// Error: 2-26 cannot order content and content
+#([Hi], [There]).sorted()
+
diff --git a/test/typ/compiler/array-37.typ b/test/typ/compiler/array-37.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-37.typ
@@ -0,0 +1,3 @@
+// Error: 2-18 array index out of bounds (index: -4, len: 3) and no default value was specified
+#(1, 2, 3).at(-4)
+
diff --git a/test/typ/compiler/array-38.typ b/test/typ/compiler/array-38.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/array-38.typ
@@ -0,0 +1,26 @@
+// Error: 4 expected closing paren
+#{(}
+
+// Error: 3-4 unexpected closing paren
+#{)}
+
+// Error: 4-6 unexpected end of block comment
+#(1*/2)
+
+// Error: 6-8 invalid number suffix: u
+#(1, 1u 2)
+
+// Error: 3-4 unexpected comma
+#(,1)
+
+// Missing expression makes named pair incomplete, making this an empty array.
+// Error: 5 expected expression
+#(a:)
+
+// Named pair after this is already identified as an array.
+// Error: 6-10 expected expression, found named pair
+#(1, b: 2)
+
+// Keyed pair after this is already identified as an array.
+// Error: 6-14 expected expression, found keyed pair
+#(1, "key": 2)
diff --git a/test/typ/compiler/bench-00.typ b/test/typ/compiler/bench-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/bench-00.typ
@@ -0,0 +1,47 @@
+// Ref: false
+
+// Configuration with `page` and `font` functions.
+#set page(width: 450pt, margin: 1cm)
+
+// There are variables and they can take normal values like strings, ...
+#let city = "Berlin"
+
+// ... but also "content" values. While these contain markup,
+// they are also values and can be summed, stored in arrays etc.
+// There are also more standard control flow structures, like #if and #for.
+#let university = [*Technische Universität #city*]
+#let faculty = [*Fakultät II, Institut for Mathematik*]
+
+// The `box` function just places content into a rectangular container. When
+// the only argument to a function is a content block, the parentheses can be
+// omitted (i.e. `f[a]` is the same as `f([a])`).
+#box[
+  // Backslash adds a forced line break.
+  #university \
+  #faculty \
+  Sekretariat MA \
+  Dr. Max Mustermann \
+  Ola Nordmann, John Doe
+]
+#align(right, box[*WiSe 2019/2020* \ Woche 3])
+
+// Adds vertical spacing.
+#v(6mm)
+
+// If the last argument to a function is a content block, we can also place it
+// behind the parentheses.
+#align(center)[
+  // Markdown-like syntax for headings.
+  ==== 3. Übungsblatt Computerorientierte Mathematik II #v(4mm)
+  *Abgabe: 03.05.2019* (bis 10:10 Uhr in MA 001) #v(4mm)
+  *Alle Antworten sind zu beweisen.*
+]
+
+*1. Aufgabe* #align(right)[(1 + 1 + 2 Punkte)]
+
+Ein _Binärbaum_ ist ein Wurzelbaum, in dem jeder Knoten ≤ 2 Kinder hat.
+Die Tiefe eines Knotens _v_ ist die Länge des eindeutigen Weges von der Wurzel
+zu _v_, und die Höhe von _v_ ist die Länge eines längsten (absteigenden) Weges
+von _v_ zu einem Blatt. Die Höhe des Baumes ist die Höhe der Wurzel.
+
+#v(6mm)
diff --git a/test/typ/compiler/block-00.typ b/test/typ/compiler/block-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-00.typ
@@ -0,0 +1,20 @@
+// Ref: true
+
+// Evaluates to join of none, [My ] and the two loop bodies.
+#{
+  let parts = ("my fri", "end.")
+  [Hello, ]
+  for s in parts [#s]
+}
+
+// Evaluates to join of the content and strings.
+#{
+  [How]
+  if true {
+    " are"
+  }
+  [ ]
+  if false [Nope]
+  [you] + "?"
+}
+
diff --git a/test/typ/compiler/block-01.typ b/test/typ/compiler/block-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-01.typ
@@ -0,0 +1,25 @@
+// Nothing evaluates to none.
+#test({}, none)
+
+// Let evaluates to none.
+#test({ let v = 0 }, none)
+
+// Evaluates to single expression.
+#test({ "hello" }, "hello")
+
+// Evaluates to string.
+#test({ let x = "m"; x + "y" }, "my")
+
+// Evaluated to int.
+#test({
+  let x = 1
+  let y = 2
+  x + y
+}, 3)
+
+// String is joined with trailing none, evaluates to string.
+#test({
+  type("")
+  none
+}, "string")
+
diff --git a/test/typ/compiler/block-02.typ b/test/typ/compiler/block-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-02.typ
@@ -0,0 +1,8 @@
+// Some things can't be joined.
+#{
+  [A]
+  // Error: 3-4 cannot join content with integer
+  1
+  [B]
+}
+
diff --git a/test/typ/compiler/block-03.typ b/test/typ/compiler/block-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-03.typ
@@ -0,0 +1,6 @@
+// Block directly in markup also creates a scope.
+#{ let x = 1 }
+
+// Error: 7-8 unknown variable: x
+#test(x, 1)
+
diff --git a/test/typ/compiler/block-04.typ b/test/typ/compiler/block-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-04.typ
@@ -0,0 +1,11 @@
+// Block in expression does create a scope.
+#let a = {
+  let b = 1
+  b
+}
+
+#test(a, 1)
+
+// Error: 3-4 unknown variable: b
+#{b}
+
diff --git a/test/typ/compiler/block-05.typ b/test/typ/compiler/block-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-05.typ
@@ -0,0 +1,9 @@
+// Double block creates a scope.
+#{{
+  import "module.typ": b
+  test(b, 1)
+}}
+
+// Error: 2-3 unknown variable: b
+#b
+
diff --git a/test/typ/compiler/block-06.typ b/test/typ/compiler/block-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-06.typ
@@ -0,0 +1,15 @@
+// Multiple nested scopes.
+#{
+  let a = "a1"
+  {
+    let a = "a2"
+    {
+      test(a, "a2")
+      let a = "a3"
+      test(a, "a3")
+    }
+    test(a, "a2")
+  }
+  test(a, "a1")
+}
+
diff --git a/test/typ/compiler/block-07.typ b/test/typ/compiler/block-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-07.typ
@@ -0,0 +1,6 @@
+// Content blocks also create a scope.
+#[#let x = 1]
+
+// Error: 2-3 unknown variable: x
+#x
+
diff --git a/test/typ/compiler/block-08.typ b/test/typ/compiler/block-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-08.typ
@@ -0,0 +1,27 @@
+// Multiple unseparated expressions in one line.
+
+// Error: 2-4 invalid number suffix: u
+#1u
+
+// Should output `1`.
+// Error: 4 expected semicolon or line break
+#{1 2}
+
+// Should output `2`.
+// Error: 13 expected semicolon or line break
+// Error: 23 expected semicolon or line break
+#{let x = -1 let y = 3 x + y}
+
+// Should output `3`.
+#{
+  // Error: 6 expected identifier
+  // Error: 10 expected block
+  for "v"
+
+  // Error: 8 expected keyword `in`
+  // Error: 22 expected block
+  for v let z = 1 + 2
+
+  z
+}
+
diff --git a/test/typ/compiler/block-09.typ b/test/typ/compiler/block-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-09.typ
@@ -0,0 +1,3 @@
+// Error: 3 expected closing brace
+#{
+
diff --git a/test/typ/compiler/block-10.typ b/test/typ/compiler/block-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/block-10.typ
@@ -0,0 +1,2 @@
+// Error: 2-3 unexpected closing brace
+#}
diff --git a/test/typ/compiler/break-continue-00.typ b/test/typ/compiler/break-continue-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-00.typ
@@ -0,0 +1,16 @@
+// Test break.
+
+#let var = 0
+#let error = false
+
+#for i in range(10) {
+  var += i
+  if i > 5 {
+    break
+    error = true
+  }
+}
+
+#test(var, 21)
+#test(error, false)
+
diff --git a/test/typ/compiler/break-continue-01.typ b/test/typ/compiler/break-continue-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-01.typ
@@ -0,0 +1,14 @@
+// Test joining with break.
+
+#let i = 0
+#let x = while true {
+  i += 1
+  str(i)
+  if i >= 5 {
+    "."
+    break
+  }
+}
+
+#test(x, "12345.")
+
diff --git a/test/typ/compiler/break-continue-02.typ b/test/typ/compiler/break-continue-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-02.typ
@@ -0,0 +1,16 @@
+// Test continue.
+
+#let i = 0
+#let x = 0
+
+#while x < 8 {
+  i += 1
+  if calc.rem(i, 3) == 0 {
+    continue
+  }
+  x += i
+}
+
+// If continue did not work, this would equal 10.
+#test(x, 12)
+
diff --git a/test/typ/compiler/break-continue-03.typ b/test/typ/compiler/break-continue-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-03.typ
@@ -0,0 +1,13 @@
+// Test joining with continue.
+
+#let x = for i in range(5) {
+  "a"
+  if calc.rem(i, 3) == 0 {
+    "_"
+    continue
+  }
+  str(i)
+}
+
+#test(x, "a_a1a2a_a4")
+
diff --git a/test/typ/compiler/break-continue-04.typ b/test/typ/compiler/break-continue-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-04.typ
@@ -0,0 +1,10 @@
+// Test break outside of loop.
+#let f() = {
+  // Error: 3-8 cannot break outside of loop
+  break
+}
+
+#for i in range(1) {
+  f()
+}
+
diff --git a/test/typ/compiler/break-continue-05.typ b/test/typ/compiler/break-continue-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-05.typ
@@ -0,0 +1,13 @@
+// Test break in function call.
+#let identity(x) = x
+#let out = for i in range(5) {
+  "A"
+  identity({
+    "B"
+    break
+  })
+  "C"
+}
+
+#test(out, "AB")
+
diff --git a/test/typ/compiler/break-continue-06.typ b/test/typ/compiler/break-continue-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-06.typ
@@ -0,0 +1,5 @@
+// Test continue outside of loop.
+
+// Error: 12-20 cannot continue outside of loop
+#let x = { continue }
+
diff --git a/test/typ/compiler/break-continue-07.typ b/test/typ/compiler/break-continue-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-07.typ
@@ -0,0 +1,3 @@
+// Error: 2-10 cannot continue outside of loop
+#continue
+
diff --git a/test/typ/compiler/break-continue-08.typ b/test/typ/compiler/break-continue-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-08.typ
@@ -0,0 +1,10 @@
+// Ref: true
+// Should output `Hello World 🌎`.
+#for _ in range(10) {
+  [Hello ]
+  [World #{
+    [🌎]
+    break
+  }]
+}
+
diff --git a/test/typ/compiler/break-continue-09.typ b/test/typ/compiler/break-continue-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-09.typ
@@ -0,0 +1,14 @@
+// Ref: true
+// Should output `Some` in red, `Some` in blue and `Last` in green.
+// Everything should be in smallcaps.
+#for color in (red, blue, green, yellow) [
+  #set text(font: "Roboto")
+  #show: it => text(fill: color, it)
+  #smallcaps(if color != green [
+    Some
+  ] else [
+    Last
+    #break
+  ])
+]
+
diff --git a/test/typ/compiler/break-continue-10.typ b/test/typ/compiler/break-continue-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-10.typ
@@ -0,0 +1,9 @@
+// Ref: true
+// Test break in set rule.
+// Should output `Hi` in blue.
+#for i in range(10) {
+  [Hello]
+  set text(blue, ..break)
+  [Not happening]
+}
+
diff --git a/test/typ/compiler/break-continue-11.typ b/test/typ/compiler/break-continue-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/break-continue-11.typ
@@ -0,0 +1,9 @@
+// Test second block during break flow.
+// Ref: true
+
+#for i in range(10) {
+  table(
+    { [A]; break },
+    for _ in range(3) [B]
+  )
+}
diff --git a/test/typ/compiler/call-00.typ b/test/typ/compiler/call-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-00.typ
@@ -0,0 +1,23 @@
+// Ref: true
+
+// Omitted space.
+#let f() = {}
+#[#f()*Bold*]
+
+// Call return value of function with body.
+#let f(x, body) = (y) => [#x] + body + [#y]
+#f(1)[2](3)
+
+// Don't parse this as a function.
+#test (it)
+
+#let f(body) = body
+#f[A]
+#f()[A]
+#f([A])
+
+#let g(a, b) = a + b
+#g[A][B]
+#g([A], [B])
+#g()[A][B]
+
diff --git a/test/typ/compiler/call-01.typ b/test/typ/compiler/call-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-01.typ
@@ -0,0 +1,17 @@
+// Trailing comma.
+#test(1 + 1, 2,)
+
+// Call function assigned to variable.
+#let alias = type
+#test(alias(alias), "function")
+
+// Callee expressions.
+#{
+  // Wrapped in parens.
+  test((type)("hi"), "string")
+
+  // Call the return value of a function.
+  let adder(dx) = x => x + dx
+  test(adder(2)(5), 7)
+}
+
diff --git a/test/typ/compiler/call-02.typ b/test/typ/compiler/call-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-02.typ
@@ -0,0 +1,3 @@
+// Error: 26-30 duplicate argument: font
+#set text(font: "Arial", font: "Helvetica")
+
diff --git a/test/typ/compiler/call-03.typ b/test/typ/compiler/call-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-03.typ
@@ -0,0 +1,3 @@
+// Error: 2-6 expected function, found boolean
+#true()
+
diff --git a/test/typ/compiler/call-04.typ b/test/typ/compiler/call-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-04.typ
@@ -0,0 +1,5 @@
+#let x = "x"
+
+// Error: 2-3 expected function, found string
+#x()
+
diff --git a/test/typ/compiler/call-05.typ b/test/typ/compiler/call-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-05.typ
@@ -0,0 +1,5 @@
+#let f(x) = x
+
+// Error: 2-6 expected function, found integer
+#f(1)(2)
+
diff --git a/test/typ/compiler/call-06.typ b/test/typ/compiler/call-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-06.typ
@@ -0,0 +1,5 @@
+#let f(x) = x
+
+// Error: 2-6 expected function, found content
+#f[1](2)
+
diff --git a/test/typ/compiler/call-07.typ b/test/typ/compiler/call-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-07.typ
@@ -0,0 +1,23 @@
+// Error: 7 expected expression
+// Error: 8 expected expression
+#func(:)
+
+// Error: 10-12 unexpected end of block comment
+#func(a:1*/)
+
+// Error: 8 expected comma
+#func(1 2)
+
+// Error: 7-8 expected identifier, found integer
+// Error: 9 expected expression
+#func(1:)
+
+// Error: 7-8 expected identifier, found integer
+#func(1:2)
+
+// Error: 7-12 expected identifier, found string
+#func("abc": 2)
+
+// Error: 7-10 expected identifier, found group
+#func((x):1)
+
diff --git a/test/typ/compiler/call-08.typ b/test/typ/compiler/call-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-08.typ
@@ -0,0 +1,3 @@
+// Error: 2:1 expected closing bracket
+#func[`a]`
+
diff --git a/test/typ/compiler/call-09.typ b/test/typ/compiler/call-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-09.typ
@@ -0,0 +1,3 @@
+// Error: 8 expected closing paren
+#{func(}
+
diff --git a/test/typ/compiler/call-10.typ b/test/typ/compiler/call-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/call-10.typ
@@ -0,0 +1,2 @@
+// Error: 2:1 expected quote
+#func("]
diff --git a/test/typ/compiler/closure-00.typ b/test/typ/compiler/closure-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-00.typ
@@ -0,0 +1,8 @@
+// Don't parse closure directly in content.
+// Ref: true
+
+#let x = "x"
+
+// Should output `x => y`.
+#x => y
+
diff --git a/test/typ/compiler/closure-01.typ b/test/typ/compiler/closure-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-01.typ
@@ -0,0 +1,6 @@
+// Basic closure without captures.
+#{
+  let adder = (x, y) => x + y
+  test(adder(2, 3), 5)
+}
+
diff --git a/test/typ/compiler/closure-02.typ b/test/typ/compiler/closure-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-02.typ
@@ -0,0 +1,10 @@
+// Pass closure as argument and return closure.
+// Also uses shorthand syntax for a single argument.
+#{
+  let chain = (f, g) => (x) => f(g(x))
+  let f = x => x + 1
+  let g = x => 2 * x
+  let h = chain(f, g)
+  test(h(2), 5)
+}
+
diff --git a/test/typ/compiler/closure-03.typ b/test/typ/compiler/closure-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-03.typ
@@ -0,0 +1,17 @@
+// Capture environment.
+#{
+  let mark = "!"
+  let greet = {
+    let hi = "Hi"
+    name => {
+        hi + ", " + name + mark
+    }
+  }
+
+  test(greet("Typst"), "Hi, Typst!")
+
+  // Changing the captured variable after the closure definition has no effect.
+  mark = "?"
+  test(greet("Typst"), "Hi, Typst!")
+}
+
diff --git a/test/typ/compiler/closure-04.typ b/test/typ/compiler/closure-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-04.typ
@@ -0,0 +1,10 @@
+// Redefined variable.
+#{
+  let x = 1
+  let f() = {
+    let x = x + 2
+    x
+  }
+  test(f(), 3)
+}
+
diff --git a/test/typ/compiler/closure-05.typ b/test/typ/compiler/closure-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-05.typ
@@ -0,0 +1,10 @@
+// Import bindings.
+#{
+  let b = "module.typ"
+  let f() = {
+    import b: b
+    b
+  }
+  test(f(), 1)
+}
+
diff --git a/test/typ/compiler/closure-06.typ b/test/typ/compiler/closure-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-06.typ
@@ -0,0 +1,11 @@
+// For loop bindings.
+#{
+  let v = (1, 2, 3)
+  let f() = {
+    let s = 0
+    for v in v { s += v }
+    s
+  }
+  test(f(), 6)
+}
+
diff --git a/test/typ/compiler/closure-07.typ b/test/typ/compiler/closure-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-07.typ
@@ -0,0 +1,10 @@
+// Let + closure bindings.
+#{
+  let g = "hi"
+  let f() = {
+    let g() = "bye"
+    g()
+  }
+  test(f(), "bye")
+}
+
diff --git a/test/typ/compiler/closure-08.typ b/test/typ/compiler/closure-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-08.typ
@@ -0,0 +1,11 @@
+// Parameter bindings.
+#{
+  let x = 5
+  let g() = {
+    let f(x, y: x) = x + y
+    f
+  }
+
+  test(g()(8), 13)
+}
+
diff --git a/test/typ/compiler/closure-09.typ b/test/typ/compiler/closure-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-09.typ
@@ -0,0 +1,8 @@
+// Don't leak environment.
+#{
+  // Error: 16-17 unknown variable: x
+  let func() = x
+  let x = "hi"
+  func()
+}
+
diff --git a/test/typ/compiler/closure-10.typ b/test/typ/compiler/closure-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-10.typ
@@ -0,0 +1,9 @@
+// Too few arguments.
+#{
+  let types(x, y) = "[" + type(x) + ", " + type(y) + "]"
+  test(types(14%, 12pt), "[ratio, length]")
+
+  // Error: 13-21 missing argument: y
+  test(types("nope"), "[string, none]")
+}
+
diff --git a/test/typ/compiler/closure-11.typ b/test/typ/compiler/closure-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-11.typ
@@ -0,0 +1,8 @@
+// Too many arguments.
+#{
+  let f(x) = x + 1
+
+  // Error: 8-13 unexpected argument
+  f(1, "two", () => x)
+}
+
diff --git a/test/typ/compiler/closure-12.typ b/test/typ/compiler/closure-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-12.typ
@@ -0,0 +1,13 @@
+// Named arguments.
+#{
+  let greet(name, birthday: false) = {
+    if birthday { "Happy Birthday, " } else { "Hey, " } + name + "!"
+  }
+
+  test(greet("Typst"), "Hey, Typst!")
+  test(greet("Typst", birthday: true), "Happy Birthday, Typst!")
+
+  // Error: 23-35 unexpected argument: whatever
+  test(greet("Typst", whatever: 10))
+}
+
diff --git a/test/typ/compiler/closure-13.typ b/test/typ/compiler/closure-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-13.typ
@@ -0,0 +1,22 @@
+// Parameter unpacking.
+#let f((a, b), ..c) = (a, b, c)
+#test(f((1, 2), 3, 4), (1, 2, (3, 4)))
+
+#let f((k: a, b), c: 3, (d,)) = (a, b, c, d)
+#test(f((k: 1, b: 2), (4,)), (1, 2, 3, 4))
+
+// Error: 22-23 duplicate parameter: a
+#let f((a: b), (c,), a) = none
+
+// Error: 8-14 expected identifier, found array
+#let f((a, b): 0) = none
+
+// Error: 10-19 expected identifier, found destructuring pattern
+#let f(..(a, b: c)) = none
+
+// Error: 10-16 expected identifier, found array
+#let f(..(a, b)) = none
+
+// Error: 10-19 expected identifier, found destructuring pattern
+#let f(..(a, b: c)) = none
+
diff --git a/test/typ/compiler/closure-14.typ b/test/typ/compiler/closure-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-14.typ
@@ -0,0 +1,3 @@
+// Error: 11-12 duplicate parameter: x
+#let f(x, x) = none
+
diff --git a/test/typ/compiler/closure-15.typ b/test/typ/compiler/closure-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-15.typ
@@ -0,0 +1,5 @@
+// Error: 14-15 duplicate parameter: a
+// Error: 23-24 duplicate parameter: b
+// Error: 35-36 duplicate parameter: b
+#let f(a, b, a: none, b: none, c, b) = none
+
diff --git a/test/typ/compiler/closure-16.typ b/test/typ/compiler/closure-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-16.typ
@@ -0,0 +1,3 @@
+// Error: 13-14 duplicate parameter: a
+#let f(a, ..a) = none
+
diff --git a/test/typ/compiler/closure-17.typ b/test/typ/compiler/closure-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-17.typ
@@ -0,0 +1,3 @@
+// Error: 7-17 expected identifier, named pair or argument sink, found keyed pair
+#((a, "named": b) => none)
+
diff --git a/test/typ/compiler/closure-18.typ b/test/typ/compiler/closure-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-18.typ
@@ -0,0 +1,3 @@
+// Error: 10-15 expected identifier, found string
+#let foo("key": b) = key
+
diff --git a/test/typ/compiler/closure-19.typ b/test/typ/compiler/closure-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-19.typ
@@ -0,0 +1,3 @@
+// Error: 10-14 expected identifier, found `none`
+#let foo(none: b) = key
+
diff --git a/test/typ/compiler/closure-20.typ b/test/typ/compiler/closure-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/closure-20.typ
@@ -0,0 +1,2 @@
+// Error: 11 expected comma
+#let foo(_: 3) = none
diff --git a/test/typ/compiler/color-00.typ b/test/typ/compiler/color-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/color-00.typ
@@ -0,0 +1,17 @@
+// Test CMYK color conversion.
+#let c = cmyk(50%, 64%, 16%, 17%)
+#stack(
+  dir: ltr,
+  spacing: 1fr,
+  rect(width: 1cm, fill: cmyk(69%, 11%, 69%, 41%)),
+  rect(width: 1cm, fill: c),
+  rect(width: 1cm, fill: c.negate()),
+)
+
+#for x in range(0, 11) {
+  box(square(size: 9pt, fill: c.lighten(x * 10%)))
+}
+#for x in range(0, 11) {
+  box(square(size: 9pt, fill: c.darken(x * 10%)))
+}
+
diff --git a/test/typ/compiler/color-01.typ b/test/typ/compiler/color-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/color-01.typ
@@ -0,0 +1,5 @@
+// Test gray color modification.
+// Ref: false
+#test(luma(20%).lighten(50%), luma(60%))
+#test(luma(80%).darken(20%), luma(63.9%))
+#test(luma(80%).negate(), luma(20%))
diff --git a/test/typ/compiler/comment-00.typ b/test/typ/compiler/comment-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/comment-00.typ
@@ -0,0 +1,23 @@
+// Line comment acts as spacing.
+A// you
+B
+
+// Block comment does not act as spacing, nested block comments.
+C/*
+ /* */
+*/D
+
+// Works in code.
+#test(type(/*1*/ 1) //
+, "integer")
+
+// End of block comment in line comment.
+// Hello */
+
+// Nested line comment.
+/*//*/
+Still comment.
+*/
+
+E
+
diff --git a/test/typ/compiler/comment-01.typ b/test/typ/compiler/comment-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/comment-01.typ
@@ -0,0 +1,6 @@
+// End should not appear without start.
+// Error: 7-9 unexpected end of block comment
+/* */ */
+
+// Unterminated is okay.
+/*
diff --git a/test/typ/compiler/construct-00.typ b/test/typ/compiler/construct-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/construct-00.typ
@@ -0,0 +1,5 @@
+// Ensure that constructor styles aren't passed down the tree.
+// The inner list should have no extra indent.
+#set par(leading: 2pt)
+#list(body-indent: 20pt, [First], list[A][B])
+
diff --git a/test/typ/compiler/construct-01.typ b/test/typ/compiler/construct-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/construct-01.typ
@@ -0,0 +1,8 @@
+// Ensure that constructor styles win, but not over outer styles.
+// The outer paragraph should be right-aligned,
+// but the B should be center-aligned.
+#set list(marker: [>])
+#list(marker: [--])[
+  #rect(width: 2cm, fill: green, inset: 4pt, list[A])
+]
+
diff --git a/test/typ/compiler/construct-02.typ b/test/typ/compiler/construct-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/construct-02.typ
@@ -0,0 +1,4 @@
+// The inner rectangle should also be yellow here.
+// (and therefore invisible)
+#[#set rect(fill: yellow);#text(1em, rect(inset: 5pt, rect()))]
+
diff --git a/test/typ/compiler/construct-03.typ b/test/typ/compiler/construct-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/construct-03.typ
@@ -0,0 +1,3 @@
+// The inner rectangle should not be yellow here.
+A #box(rect(fill: yellow, inset: 5pt, rect())) B
+
diff --git a/test/typ/compiler/construct-04.typ b/test/typ/compiler/construct-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/construct-04.typ
@@ -0,0 +1,4 @@
+// The constructor property should still work
+// when there are recursive show rules.
+#show enum: set text(blue)
+#enum(numbering: "(a)", [A], enum[B])
diff --git a/test/typ/compiler/content-field-00.typ b/test/typ/compiler/content-field-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/content-field-00.typ
@@ -0,0 +1,41 @@
+// Integrated test for content fields.
+
+#let compute(equation, ..vars) = {
+  let vars = vars.named()
+  let f(elem) = {
+    let func = elem.func()
+    if func == text {
+      let text = elem.text
+      if regex("^\d+$") in text {
+        int(text)
+      } else if text in vars {
+        int(vars.at(text))
+      } else {
+        panic("unknown math variable: " + text)
+      }
+    } else if func == math.attach {
+      let value = f(elem.base)
+      if elem.has("t") {
+        value = calc.pow(value, f(elem.t))
+      }
+      value
+    } else if elem.has("children") {
+      elem
+        .children
+        .filter(v => v != [ ])
+        .split[+]
+        .map(xs => xs.fold(1, (prod, v) => prod * f(v)))
+        .fold(0, (sum, v) => sum + v)
+    }
+  }
+  let result = f(equation.body)
+  [With ]
+  vars
+    .pairs()
+    .map(p => $#p.first() = #p.last()$)
+    .join(", ", last: " and ")
+  [ we have:]
+  $ equation = result $
+}
+
+#compute($x y + y^2$, x: 2, y: 3)
diff --git a/test/typ/compiler/dict-00.typ b/test/typ/compiler/dict-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-00.typ
@@ -0,0 +1,12 @@
+// Ref: true
+
+// Empty
+#(:)
+
+// Two pairs and string key.
+#let dict = (normal: 1, "spacy key": 2)
+#dict
+
+#test(dict.normal, 1)
+#test(dict.at("spacy key"), 2)
+
diff --git a/test/typ/compiler/dict-01.typ b/test/typ/compiler/dict-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-01.typ
@@ -0,0 +1,12 @@
+// Test lvalue and rvalue access.
+#{
+  let dict = (a: 1, "b b": 1)
+  dict.at("b b") += 1
+  dict.state = (ok: true, err: false)
+  test(dict, (a: 1, "b b": 2, state: (ok: true, err: false)))
+  test(dict.state.ok, true)
+  dict.at("state").ok = false
+  test(dict.state.ok, false)
+  test(dict.state.err, false)
+}
+
diff --git a/test/typ/compiler/dict-02.typ b/test/typ/compiler/dict-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-02.typ
@@ -0,0 +1,7 @@
+// Test rvalue missing key.
+#{
+  let dict = (a: 1, b: 2)
+  // Error: 11-23 dictionary does not contain key "c" and no default value was specified
+  let x = dict.at("c")
+}
+
diff --git a/test/typ/compiler/dict-03.typ b/test/typ/compiler/dict-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-03.typ
@@ -0,0 +1,4 @@
+// Test default value.
+#test((a: 1, b: 2).at("b", default: 3), 2)
+#test((a: 1, b: 2).at("c", default: 3), 3)
+
diff --git a/test/typ/compiler/dict-04.typ b/test/typ/compiler/dict-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-04.typ
@@ -0,0 +1,7 @@
+// Missing lvalue is not automatically none-initialized.
+#{
+  let dict = (:)
+  // Error: 3-9 dictionary does not contain key "b" and no default value was specified
+  dict.b += 1
+}
+
diff --git a/test/typ/compiler/dict-05.typ b/test/typ/compiler/dict-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-05.typ
@@ -0,0 +1,11 @@
+// Test dictionary methods.
+#let dict = (a: 3, c: 2, b: 1)
+#test("c" in dict, true)
+#test(dict.len(), 3)
+#test(dict.values(), (3, 2, 1))
+#test(dict.pairs().map(p => p.first() + str(p.last())).join(), "a3c2b1")
+
+#dict.remove("c")
+#test("c" in dict, false)
+#test(dict, (a: 3, b: 1))
+
diff --git a/test/typ/compiler/dict-06.typ b/test/typ/compiler/dict-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-06.typ
@@ -0,0 +1,3 @@
+// Error: 24-29 duplicate key: first
+#(first: 1, second: 2, first: 3)
+
diff --git a/test/typ/compiler/dict-07.typ b/test/typ/compiler/dict-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-07.typ
@@ -0,0 +1,3 @@
+// Error: 17-20 duplicate key: a
+#(a: 1, "b": 2, "a": 3)
+
diff --git a/test/typ/compiler/dict-08.typ b/test/typ/compiler/dict-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-08.typ
@@ -0,0 +1,14 @@
+// Simple expression after already being identified as a dictionary.
+// Error: 9-10 expected named or keyed pair, found identifier
+#(a: 1, b)
+
+// Identified as dictionary due to initial colon.
+// Error: 4-5 expected named or keyed pair, found integer
+// Error: 5 expected comma
+// Error: 12-16 expected identifier or string, found boolean
+// Error: 17 expected expression
+#(:1 b:"", true:)
+
+// Error: 3-8 expected identifier or string, found binary expression
+#(a + b: "hey")
+
diff --git a/test/typ/compiler/dict-09.typ b/test/typ/compiler/dict-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-09.typ
@@ -0,0 +1,3 @@
+// Error: 3-15 cannot mutate a temporary value
+#((key: "val").other = "some")
+
diff --git a/test/typ/compiler/dict-10.typ b/test/typ/compiler/dict-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-10.typ
@@ -0,0 +1,5 @@
+#{
+  let object = none
+  // Error: 3-9 expected dictionary, found none
+  object.property = "value"
+}
diff --git a/test/typ/compiler/field-00.typ b/test/typ/compiler/field-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-00.typ
@@ -0,0 +1,10 @@
+// Test field on dictionary.
+#let dict = (nothing: "ness", hello: "world")
+#test(dict.nothing, "ness")
+#{
+  let world = dict
+    .hello
+
+  test(world, "world")
+}
+
diff --git a/test/typ/compiler/field-01.typ b/test/typ/compiler/field-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-01.typ
@@ -0,0 +1,9 @@
+// Test fields on elements.
+#show list: it => {
+  test(it.children.len(), 3)
+}
+
+- A
+- B
+- C
+
diff --git a/test/typ/compiler/field-02.typ b/test/typ/compiler/field-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-02.typ
@@ -0,0 +1,5 @@
+// Test fields on function scopes.
+#enum.item
+#assert.eq
+#assert.ne
+
diff --git a/test/typ/compiler/field-03.typ b/test/typ/compiler/field-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-03.typ
@@ -0,0 +1,3 @@
+// Error: 9-16 function `assert` does not contain field `invalid`
+#assert.invalid
+
diff --git a/test/typ/compiler/field-04.typ b/test/typ/compiler/field-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-04.typ
@@ -0,0 +1,3 @@
+// Error: 7-14 function `enum` does not contain field `invalid`
+#enum.invalid
+
diff --git a/test/typ/compiler/field-05.typ b/test/typ/compiler/field-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-05.typ
@@ -0,0 +1,3 @@
+// Error: 7-14 function `enum` does not contain field `invalid`
+#enum.invalid()
+
diff --git a/test/typ/compiler/field-06.typ b/test/typ/compiler/field-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-06.typ
@@ -0,0 +1,5 @@
+// Closures cannot have fields.
+#let f(x) = x
+// Error: 4-11 cannot access fields on user-defined functions
+#f.invalid
+
diff --git a/test/typ/compiler/field-07.typ b/test/typ/compiler/field-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-07.typ
@@ -0,0 +1,3 @@
+// Error: 6-13 dictionary does not contain key "invalid" and no default value was specified
+#(:).invalid
+
diff --git a/test/typ/compiler/field-08.typ b/test/typ/compiler/field-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-08.typ
@@ -0,0 +1,3 @@
+// Error: 8-10 cannot access fields on type boolean
+#false.ok
+
diff --git a/test/typ/compiler/field-09.typ b/test/typ/compiler/field-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-09.typ
@@ -0,0 +1,4 @@
+// Error: 25-28 content does not contain field "fun" and no default value was specified
+#show heading: it => it.fun
+= A
+
diff --git a/test/typ/compiler/field-10.typ b/test/typ/compiler/field-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/field-10.typ
@@ -0,0 +1,2 @@
+// Error: 9-13 cannot access fields on type boolean
+#{false.true}
diff --git a/test/typ/compiler/for-00.typ b/test/typ/compiler/for-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/for-00.typ
@@ -0,0 +1,36 @@
+// Ref: true
+
+// Empty array.
+#for x in () [Nope]
+
+// Dictionary is traversed in insertion order.
+// Should output `Name: Typst. Age: 2.`.
+#for (k, v) in (Name: "Typst", Age: 2) [
+  #k: #v.
+]
+
+// Block body.
+// Should output `[1st, 2nd, 3rd, 4th]`.
+#{
+  "["
+  for v in (1, 2, 3, 4) {
+    if v > 1 [, ]
+    [#v]
+    if v == 1 [st]
+    if v == 2 [nd]
+    if v == 3 [rd]
+    if v >= 4 [th]
+   }
+   "]"
+}
+
+// Content block body.
+// Should output `2345`.
+#for v in (1, 2, 3, 4, 5, 6, 7) [#if v >= 2 and v <= 5 { repr(v) }]
+
+// Map captured arguments.
+#let f1(..args) = args.pos().map(repr)
+#let f2(..args) = args.named().pairs().map(p => repr(p.first()) + ": " + repr(p.last()))
+#let f(..args) = (f1(..args) + f2(..args)).join(", ")
+#f(1, a: 2)
+
diff --git a/test/typ/compiler/for-01.typ b/test/typ/compiler/for-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/for-01.typ
@@ -0,0 +1,39 @@
+#let out = ()
+
+// Values of array.
+#for v in (1, 2, 3) {
+  out += (v,)
+}
+
+// Indices and values of array.
+#for (i, v) in ("1", "2", "3").enumerate() {
+  test(repr(i + 1), v)
+}
+
+// Pairs of dictionary.
+#for v in (a: 4, b: 5) {
+  out += (v,)
+}
+
+// Keys and values of dictionary.
+#for (k, v) in (a: 6, b: 7) {
+  out += (k,)
+  out += (v,)
+}
+
+#test(out, (1, 2, 3, ("a", 4), ("b", 5), "a", 6, "b", 7))
+
+// Grapheme clusters of string.
+#let first = true
+#let joined = for c in "abc👩‍👩‍👦‍👦" {
+  if not first { ", " }
+  first = false
+  c
+}
+
+#test(joined, "a, b, c, 👩‍👩‍👦‍👦")
+
+// Return value.
+#test(for v in "" [], none)
+#test(type(for v in "1" []), "content")
+
diff --git a/test/typ/compiler/for-02.typ b/test/typ/compiler/for-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/for-02.typ
@@ -0,0 +1,4 @@
+// Uniterable expression.
+// Error: 11-15 cannot loop over boolean
+#for v in true {}
+
diff --git a/test/typ/compiler/for-03.typ b/test/typ/compiler/for-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/for-03.typ
@@ -0,0 +1,6 @@
+// Keys and values of strings.
+// Error: 6-12 cannot destructure values of string
+#for (k, v) in "hi" {
+  dont-care
+}
+
diff --git a/test/typ/compiler/for-04.typ b/test/typ/compiler/for-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/for-04.typ
@@ -0,0 +1,37 @@
+// Destructuring without parentheses.
+// Error: 7 expected keyword `in`. did you mean to use a destructuring pattern?
+#for k, v in (a: 4, b: 5) {
+  dont-care
+}
+
+// Error: 5 expected identifier
+#for
+
+// Error: 5 expected identifier
+#for//
+
+// Error: 6 expected identifier
+#{for}
+
+// Error: 7 expected keyword `in`
+#for v
+
+// Error: 10 expected expression
+#for v in
+
+// Error: 15 expected block
+#for v in iter
+
+// Error: 5 expected identifier
+#for
+v in iter {}
+
+// Error: 6 expected identifier
+// Error: 10 expected block
+A#for "v" thing
+
+// Error: 5 expected identifier
+#for "v" in iter {}
+
+// Error: 7 expected keyword `in`
+#for a + b in iter {}
diff --git a/test/typ/compiler/highlight-00.typ b/test/typ/compiler/highlight-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/highlight-00.typ
@@ -0,0 +1,42 @@
+#set page(width: auto)
+
+```typ
+#set hello()
+#set hello()
+#set hello.world()
+#set hello.my.world()
+#let foo(x) = x * 2
+#show heading: func
+#show module.func: func
+#show module.func: it => {}
+#foo(ident: ident)
+#hello
+#hello()
+#box[]
+#hello.world
+#hello.world()
+#hello().world()
+#hello.my.world
+#hello.my.world()
+#hello.my().world
+#hello.my().world()
+#{ hello }
+#{ hello() }
+#{ hello.world() }
+$ hello $
+$ hello() $
+$ box[] $
+$ hello.world $
+$ hello.world() $
+$ hello.my.world() $
+$ f_zeta(x), f_zeta(x)/1 $
+$ emph(hello.my.world()) $
+$ emph(hello.my().world) $
+$ emph(hello.my().world()) $
+$ #hello $
+$ #hello() $
+$ #hello.world $
+$ #hello.world() $
+$ #box[] $
+#if foo []
+```
diff --git a/test/typ/compiler/hint-00.typ b/test/typ/compiler/hint-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/hint-00.typ
@@ -0,0 +1,3 @@
+// Error: 1:17-1:19 expected length, found integer: a length needs a unit – did you mean 12pt?
+#set text(size: 12)
+
diff --git a/test/typ/compiler/hint-01.typ b/test/typ/compiler/hint-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/hint-01.typ
@@ -0,0 +1,9 @@
+#{
+  let a = 2
+  a = 1-a
+  a = a -1
+
+  // Error: 7-10 unknown variable: a-1 – if you meant to use subtraction, try adding spaces around the minus sign.
+  a = a-1
+}
+
diff --git a/test/typ/compiler/hint-02.typ b/test/typ/compiler/hint-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/hint-02.typ
@@ -0,0 +1,4 @@
+#{
+  // Error: 3-6 unknown variable: a-1 – if you meant to use subtraction, try adding spaces around the minus sign.
+  a-1 = 2
+}
diff --git a/test/typ/compiler/if-00.typ b/test/typ/compiler/if-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/if-00.typ
@@ -0,0 +1,9 @@
+// Test condition evaluation.
+#if 1 < 2 [
+  One.
+]
+
+#if true == false [
+  {Bad}, but we {dont-care}!
+]
+
diff --git a/test/typ/compiler/if-01.typ b/test/typ/compiler/if-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/if-01.typ
@@ -0,0 +1,43 @@
+// Braced condition.
+#if {true} [
+  One.
+]
+
+// Content block in condition.
+#if [] != none [
+  Two.
+]
+
+// Multi-line condition with parens.
+#if (
+  1 + 1
+    == 1
+) [
+  Nope.
+] else {
+  "Three."
+}
+
+// Multiline.
+#if false [
+  Bad.
+] else {
+  let point = "."
+  "Four" + point
+}
+
+// Content block can be argument or body depending on whitespace.
+#{
+  if "content" == type[b] [Fi] else [Nope]
+  if "content" == type [Nope] else [ve.]
+}
+
+#let i = 3
+#if i < 2 [
+  Five.
+] else if i < 4 [
+  Six.
+] else [
+  Seven.
+]
+
diff --git a/test/typ/compiler/if-02.typ b/test/typ/compiler/if-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/if-02.typ
@@ -0,0 +1,17 @@
+// Test else if.
+// Ref: false
+
+#let nth(n) = {
+  str(n)
+  if n == 1 { "st" }
+  else if n == 2 { "nd" }
+  else if n == 3 { "rd" }
+  else { "th" }
+}
+
+#test(nth(1), "1st")
+#test(nth(2), "2nd")
+#test(nth(3), "3rd")
+#test(nth(4), "4th")
+#test(nth(5), "5th")
+
diff --git a/test/typ/compiler/if-03.typ b/test/typ/compiler/if-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/if-03.typ
@@ -0,0 +1,21 @@
+// Value of if expressions.
+// Ref: false
+
+#{
+  let x = 1
+  let y = 2
+  let z
+
+  // Returns if branch.
+  z = if x < y { "ok" }
+  test(z, "ok")
+
+  // Returns else branch.
+  z = if x > y { "bad" } else { "ok" }
+  test(z, "ok")
+
+  // Missing else evaluates to none.
+  z = if x > y { "bad" }
+  test(z, none)
+}
+
diff --git a/test/typ/compiler/if-04.typ b/test/typ/compiler/if-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/if-04.typ
@@ -0,0 +1,5 @@
+// Condition must be boolean.
+// If it isn't, neither branch is evaluated.
+// Error: 5-14 expected boolean, found string
+#if "a" + "b" { nope } else { nope }
+
diff --git a/test/typ/compiler/if-05.typ b/test/typ/compiler/if-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/if-05.typ
@@ -0,0 +1,4 @@
+// Make sure that we don't complain twice.
+// Error: 5-12 cannot add integer and string
+#if 1 + "2" {}
+
diff --git a/test/typ/compiler/if-06.typ b/test/typ/compiler/if-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/if-06.typ
@@ -0,0 +1,28 @@
+// Error: 4 expected expression
+#if
+
+// Error: 5 expected expression
+#{if}
+
+// Error: 6 expected block
+#if x
+
+// Error: 2-6 unexpected keyword `else`
+#else {}
+
+// Should output `x`.
+// Error: 4 expected expression
+#if
+x {}
+
+// Should output `something`.
+// Error: 6 expected block
+#if x something
+
+// Should output `A thing.`
+// Error: 19 expected block
+A#if false {} else thing
+
+#if a []else [b]
+#if a [] else [b]
+#if a {} else [b]
diff --git a/test/typ/compiler/import-00.typ b/test/typ/compiler/import-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-00.typ
@@ -0,0 +1,15 @@
+// Test basic syntax and semantics.
+// Ref: true
+
+// Test that this will be overwritten.
+#let value = [foo]
+
+// Import multiple things.
+#import "module.typ": fn, value
+#fn[Like and Subscribe!]
+#value
+
+// Should output `bye`.
+// Stop at semicolon.
+#import "module.typ": a, c;bye
+
diff --git a/test/typ/compiler/import-01.typ b/test/typ/compiler/import-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-01.typ
@@ -0,0 +1,16 @@
+// An item import.
+#import "module.typ": item
+#test(item(1, 2), 3)
+
+// Code mode
+{
+  import "module.typ": b
+  test(b, 1)
+}
+
+// A wildcard import.
+#import "module.typ": *
+
+// It exists now!
+#test(d, 3)
+
diff --git a/test/typ/compiler/import-02.typ b/test/typ/compiler/import-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-02.typ
@@ -0,0 +1,13 @@
+// Test importing from function scopes.
+// Ref: true
+
+#import enum: item
+#import assert.with(true): *
+
+#enum(
+   item(1)[First],
+   item(5)[Fifth]
+)
+#eq(10, 10)
+#ne(5, 6)
+
diff --git a/test/typ/compiler/import-03.typ b/test/typ/compiler/import-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-03.typ
@@ -0,0 +1,6 @@
+// A module import without items.
+#import "module.typ"
+#test(module.b, 1)
+#test(module.item(1, 2), 3)
+#test(module.push(2), 3)
+
diff --git a/test/typ/compiler/import-04.typ b/test/typ/compiler/import-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-04.typ
@@ -0,0 +1,10 @@
+// Edge case for module access that isn't fixed.
+#import "module.typ"
+
+// Works because the method name isn't categorized as mutating.
+#test((module,).at(0).item(1, 2), 3)
+
+// Doesn't work because of mutating name.
+// Error: 2-11 cannot mutate a temporary value
+#(module,).at(0).push()
+
diff --git a/test/typ/compiler/import-05.typ b/test/typ/compiler/import-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-05.typ
@@ -0,0 +1,6 @@
+// Who needs whitespace anyways?
+#import"module.typ":*
+
+// Allow the trailing comma.
+#import "module.typ": a, c,
+
diff --git a/test/typ/compiler/import-06.typ b/test/typ/compiler/import-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-06.typ
@@ -0,0 +1,8 @@
+// Usual importing syntax also works for function scopes
+#import enum
+#let d = (e: enum)
+#import d.e
+#import d.e: item
+
+#item(2)[a]
+
diff --git a/test/typ/compiler/import-07.typ b/test/typ/compiler/import-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-07.typ
@@ -0,0 +1,5 @@
+// Can't import from closures.
+#let f(x) = x
+// Error: 9-10 cannot import from user-defined functions
+#import f: x
+
diff --git a/test/typ/compiler/import-08.typ b/test/typ/compiler/import-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-08.typ
@@ -0,0 +1,5 @@
+// Can't import from closures, despite modifiers.
+#let f(x) = x
+// Error: 9-18 cannot import from user-defined functions
+#import f.with(5): x
+
diff --git a/test/typ/compiler/import-09.typ b/test/typ/compiler/import-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-09.typ
@@ -0,0 +1,3 @@
+// Error: 9-18 cannot import from user-defined functions
+#import () => {5}: x
+
diff --git a/test/typ/compiler/import-10.typ b/test/typ/compiler/import-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-10.typ
@@ -0,0 +1,3 @@
+// Error: 9-10 expected path, module or function, found integer
+#import 5: something
+
diff --git a/test/typ/compiler/import-11.typ b/test/typ/compiler/import-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-11.typ
@@ -0,0 +1,3 @@
+// Error: 9-11 failed to load file (is a directory)
+#import "": name
+
diff --git a/test/typ/compiler/import-12.typ b/test/typ/compiler/import-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-12.typ
@@ -0,0 +1,3 @@
+// Error: 9-20 file not found (searched at typ/compiler/lib/0.2.1)
+#import "lib/0.2.1"
+
diff --git a/test/typ/compiler/import-13.typ b/test/typ/compiler/import-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-13.typ
@@ -0,0 +1,4 @@
+// Some non-text stuff.
+// Error: 9-21 file is not valid utf-8
+#import "/rhino.png"
+
diff --git a/test/typ/compiler/import-14.typ b/test/typ/compiler/import-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-14.typ
@@ -0,0 +1,4 @@
+// Unresolved import.
+// Error: 23-35 unresolved import
+#import "module.typ": non_existing
+
diff --git a/test/typ/compiler/import-15.typ b/test/typ/compiler/import-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-15.typ
@@ -0,0 +1,4 @@
+// Cyclic import of this very file.
+// Error: 9-23 cyclic import
+#import "./import.typ"
+
diff --git a/test/typ/compiler/import-16.typ b/test/typ/compiler/import-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-16.typ
@@ -0,0 +1,5 @@
+// Cyclic import in other file.
+#import "./modules/cycle1.typ": *
+
+This is never reached.
+
diff --git a/test/typ/compiler/import-17.typ b/test/typ/compiler/import-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-17.typ
@@ -0,0 +1,3 @@
+// Error: 8 expected expression
+#import
+
diff --git a/test/typ/compiler/import-18.typ b/test/typ/compiler/import-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-18.typ
@@ -0,0 +1,3 @@
+// Error: 26-29 unexpected string
+#import "module.typ": a, "b", c
+
diff --git a/test/typ/compiler/import-19.typ b/test/typ/compiler/import-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-19.typ
@@ -0,0 +1,3 @@
+// Error: 23-24 unexpected equals sign
+#import "module.typ": =
+
diff --git a/test/typ/compiler/import-20.typ b/test/typ/compiler/import-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-20.typ
@@ -0,0 +1,4 @@
+// An additional trailing comma.
+// Error: 31-32 unexpected comma
+#import "module.typ": a, b, c,,
+
diff --git a/test/typ/compiler/import-21.typ b/test/typ/compiler/import-21.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-21.typ
@@ -0,0 +1,4 @@
+// Error: 2:2 expected semicolon or line break
+#import "module.typ
+"stuff
+
diff --git a/test/typ/compiler/import-22.typ b/test/typ/compiler/import-22.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-22.typ
@@ -0,0 +1,4 @@
+// A star in the list.
+// Error: 26-27 unexpected star
+#import "module.typ": a, *, b
+
diff --git a/test/typ/compiler/import-23.typ b/test/typ/compiler/import-23.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-23.typ
@@ -0,0 +1,4 @@
+// An item after a star.
+// Error: 24 expected semicolon or line break
+#import "module.typ": *, a
+
diff --git a/test/typ/compiler/import-24.typ b/test/typ/compiler/import-24.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-24.typ
@@ -0,0 +1,4 @@
+// Error: 14-15 unexpected colon
+// Error: 16-17 unexpected integer
+#import "": a: 1
+
diff --git a/test/typ/compiler/import-25.typ b/test/typ/compiler/import-25.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/import-25.typ
@@ -0,0 +1,2 @@
+// Error: 14 expected comma
+#import "": a b
diff --git a/test/typ/compiler/include-00.typ b/test/typ/compiler/include-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/include-00.typ
@@ -0,0 +1,13 @@
+#set page(width: 200pt)
+
+= Document
+
+// Include a file
+#include "modules/chap1.typ"
+
+// Expression as a file name.
+#let chap2 = include "modu" + "les/chap" + "2.typ"
+
+-- _Intermission_ --
+#chap2
+
diff --git a/test/typ/compiler/include-01.typ b/test/typ/compiler/include-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/include-01.typ
@@ -0,0 +1,5 @@
+#{
+  // Error: 19-38 file not found (searched at typ/compiler/modules/chap3.typ)
+  let x = include "modules/chap3.typ"
+}
+
diff --git a/test/typ/compiler/include-02.typ b/test/typ/compiler/include-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/include-02.typ
@@ -0,0 +1,6 @@
+#include "modules/chap1.typ"
+
+// The variables of the file should not appear in this scope.
+// Error: 2-6 unknown variable: name
+#name
+
diff --git a/test/typ/compiler/include-03.typ b/test/typ/compiler/include-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/include-03.typ
@@ -0,0 +1,2 @@
+// Error: 18 expected semicolon or line break
+#include "hi.typ" Hi
diff --git a/test/typ/compiler/label-00.typ b/test/typ/compiler/label-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/label-00.typ
@@ -0,0 +1,10 @@
+// Test labelled headings.
+#show heading: set text(10pt)
+#show heading.where(label: <intro>): underline
+
+= Introduction <intro>
+The beginning.
+
+= Conclusion
+The end.
+
diff --git a/test/typ/compiler/label-01.typ b/test/typ/compiler/label-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/label-01.typ
@@ -0,0 +1,7 @@
+// Test label after expression.
+#show strong.where(label: <v>): set text(red)
+
+#let a = [*A*]
+#let b = [*B*]
+#a <v> #b
+
diff --git a/test/typ/compiler/label-02.typ b/test/typ/compiler/label-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/label-02.typ
@@ -0,0 +1,8 @@
+// Test labelled text.
+#show "t": it => {
+  set text(blue) if it.has("label") and it.label == <last>
+  it
+}
+
+This is a thing #[that <last>] happened.
+
diff --git a/test/typ/compiler/label-03.typ b/test/typ/compiler/label-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/label-03.typ
@@ -0,0 +1,6 @@
+// Test abusing dynamic labels for styling.
+#show <red>: set text(red)
+#show <blue>: set text(blue)
+
+*A* *B* <red> *C* #label("bl" + "ue") *D*
+
diff --git a/test/typ/compiler/label-04.typ b/test/typ/compiler/label-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/label-04.typ
@@ -0,0 +1,11 @@
+// Test that label ignores parbreak.
+#show <hide>: none
+
+_Hidden_
+<hide>
+
+_Hidden_
+
+<hide>
+_Visible_
+
diff --git a/test/typ/compiler/label-05.typ b/test/typ/compiler/label-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/label-05.typ
@@ -0,0 +1,5 @@
+// Test that label only works within one content block.
+#show <strike>: strike
+*This is* #[<strike>] *protected.*
+*This is not.* <strike>
+
diff --git a/test/typ/compiler/label-06.typ b/test/typ/compiler/label-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/label-06.typ
@@ -0,0 +1,2 @@
+// Test that incomplete label is text.
+1 < 2 is #if 1 < 2 [not] a label.
diff --git a/test/typ/compiler/let-00.typ b/test/typ/compiler/let-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-00.typ
@@ -0,0 +1,13 @@
+// Automatically initialized with none.
+#let x
+#test(x, none)
+
+// Manually initialized with one.
+#let z = 1
+#test(z, 1)
+
+// Syntax sugar for function definitions.
+#let fill = green
+#let f(body) = rect(width: 2cm, fill: fill, inset: 5pt, body)
+#f[Hi!]
+
diff --git a/test/typ/compiler/let-01.typ b/test/typ/compiler/let-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-01.typ
@@ -0,0 +1,17 @@
+// Termination.
+
+// Terminated by line break.
+#let v1 = 1
+One
+
+// Terminated by semicolon.
+#let v2 = 2; Two
+
+// Terminated by semicolon and line break.
+#let v3 = 3;
+Three
+
+#test(v1, 1)
+#test(v2, 2)
+#test(v3, 3)
+
diff --git a/test/typ/compiler/let-02.typ b/test/typ/compiler/let-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-02.typ
@@ -0,0 +1,4 @@
+// Test parenthesised assignments.
+// Ref: false
+#let (a) = (1, 2)
+
diff --git a/test/typ/compiler/let-03.typ b/test/typ/compiler/let-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-03.typ
@@ -0,0 +1,6 @@
+// Ref: false
+// Simple destructuring.
+#let (a, b) = (1, 2)
+#test(a, 1)
+#test(b, 2)
+
diff --git a/test/typ/compiler/let-04.typ b/test/typ/compiler/let-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-04.typ
@@ -0,0 +1,4 @@
+// Ref: false
+#let (a,) = (1,)
+#test(a, 1)
+
diff --git a/test/typ/compiler/let-05.typ b/test/typ/compiler/let-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-05.typ
@@ -0,0 +1,6 @@
+// Ref: false
+// Destructuring with multiple placeholders.
+#let (a, _, c, _) = (1, 2, 3, 4)
+#test(a, 1)
+#test(c, 3)
+
diff --git a/test/typ/compiler/let-06.typ b/test/typ/compiler/let-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-06.typ
@@ -0,0 +1,7 @@
+// Ref: false
+// Destructuring with a sink.
+#let (a, b, ..c) = (1, 2, 3, 4, 5, 6)
+#test(a, 1)
+#test(b, 2)
+#test(c, (3, 4, 5, 6))
+
diff --git a/test/typ/compiler/let-07.typ b/test/typ/compiler/let-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-07.typ
@@ -0,0 +1,7 @@
+// Ref: false
+// Destructuring with a sink in the middle.
+#let (a, ..b, c) = (1, 2, 3, 4, 5, 6)
+#test(a, 1)
+#test(b, (2, 3, 4, 5))
+#test(c, 6)
+
diff --git a/test/typ/compiler/let-08.typ b/test/typ/compiler/let-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-08.typ
@@ -0,0 +1,7 @@
+// Ref: false
+// Destructuring with an empty sink.
+#let (..a, b, c) = (1, 2)
+#test(a, ())
+#test(b, 1)
+#test(c, 2)
+
diff --git a/test/typ/compiler/let-09.typ b/test/typ/compiler/let-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-09.typ
@@ -0,0 +1,7 @@
+// Ref: false
+// Destructuring with an empty sink.
+#let (a, ..b, c) = (1, 2)
+#test(a, 1)
+#test(b, ())
+#test(c, 2)
+
diff --git a/test/typ/compiler/let-10.typ b/test/typ/compiler/let-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-10.typ
@@ -0,0 +1,7 @@
+// Ref: false
+// Destructuring with an empty sink.
+#let (a, b, ..c) = (1, 2)
+#test(a, 1)
+#test(b, 2)
+#test(c, ())
+
diff --git a/test/typ/compiler/let-11.typ b/test/typ/compiler/let-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-11.typ
@@ -0,0 +1,5 @@
+// Ref: false
+// Destructuring with an empty sink and empty array.
+#let (..a) = ()
+#test(a, ())
+
diff --git a/test/typ/compiler/let-12.typ b/test/typ/compiler/let-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-12.typ
@@ -0,0 +1,24 @@
+// Ref: false
+// Destructuring with unnamed sink.
+#let (a, .., b) = (1, 2, 3, 4)
+#test(a, 1)
+#test(b, 4)
+
+// Error: 10-11 at most one binding per identifier is allowed
+#let (a, a) = (1, 2)
+
+// Error: 12-15 at most one destructuring sink is allowed
+#let (..a, ..a) = (1, 2)
+
+// Error: 12-13 at most one binding per identifier is allowed
+#let (a, ..a) = (1, 2)
+
+// Error: 13-14 at most one binding per identifier is allowed
+#let (a: a, a) = (a: 1, b: 2)
+
+// Error: 13-20 expected identifier, found function call
+#let (a, b: b.at(0)) = (a: 1, b: 2)
+
+// Error: 7-14 expected identifier or destructuring sink, found function call
+#let (a.at(0),) = (1,)
+
diff --git a/test/typ/compiler/let-13.typ b/test/typ/compiler/let-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-13.typ
@@ -0,0 +1,3 @@
+// Error: 13-14 not enough elements to destructure
+#let (a, b, c) = (1, 2)
+
diff --git a/test/typ/compiler/let-14.typ b/test/typ/compiler/let-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-14.typ
@@ -0,0 +1,3 @@
+// Error: 6-20 not enough elements to destructure
+#let (..a, b, c, d) = (1, 2)
+
diff --git a/test/typ/compiler/let-15.typ b/test/typ/compiler/let-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-15.typ
@@ -0,0 +1,3 @@
+// Error: 6-12 cannot destructure boolean
+#let (a, b) = true
+
diff --git a/test/typ/compiler/let-16.typ b/test/typ/compiler/let-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-16.typ
@@ -0,0 +1,7 @@
+// Ref: false
+// Simple destructuring.
+#let (a: a, b, x: c) = (a: 1, b: 2, x: 3)
+#test(a, 1)
+#test(b, 2)
+#test(c, 3)
+
diff --git a/test/typ/compiler/let-17.typ b/test/typ/compiler/let-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-17.typ
@@ -0,0 +1,5 @@
+// Ref: false
+// Destructuring with a sink.
+#let (a: _, ..b) = (a: 1, b: 2, c: 3)
+#test(b, (b: 2, c: 3))
+
diff --git a/test/typ/compiler/let-18.typ b/test/typ/compiler/let-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-18.typ
@@ -0,0 +1,5 @@
+// Ref: false
+// Destructuring with a sink in the middle.
+#let (a: _, ..b, c: _) = (a: 1, b: 2, c: 3)
+#test(b, (b: 2))
+
diff --git a/test/typ/compiler/let-19.typ b/test/typ/compiler/let-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-19.typ
@@ -0,0 +1,5 @@
+// Ref: false
+// Destructuring with an empty sink.
+#let (a: _, ..b) = (a: 1)
+#test(b, (:))
+
diff --git a/test/typ/compiler/let-20.typ b/test/typ/compiler/let-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-20.typ
@@ -0,0 +1,5 @@
+// Ref: false
+// Destructuring with an empty sink and empty dict.
+#let (..a) = (:)
+#test(a, (:))
+
diff --git a/test/typ/compiler/let-21.typ b/test/typ/compiler/let-21.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-21.typ
@@ -0,0 +1,5 @@
+// Ref: false
+// Destructuring with unnamed sink.
+#let (a, ..) = (a: 1, b: 2)
+#test(a, 1)
+
diff --git a/test/typ/compiler/let-22.typ b/test/typ/compiler/let-22.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-22.typ
@@ -0,0 +1,5 @@
+// Trailing placeholders.
+// Error: 10-11 not enough elements to destructure
+#let (a, _, _, _, _) = (1,)
+#test(a, 1)
+
diff --git a/test/typ/compiler/let-23.typ b/test/typ/compiler/let-23.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-23.typ
@@ -0,0 +1,4 @@
+// Error: 10-13 expected identifier, found string
+// Error: 18-19 expected identifier, found integer
+#let (a: "a", b: 2) = (a: 1, b: 2)
+
diff --git a/test/typ/compiler/let-24.typ b/test/typ/compiler/let-24.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-24.typ
@@ -0,0 +1,3 @@
+// Error: 10-11 destructuring key not found in dictionary
+#let (a, b) = (a: 1)
+
diff --git a/test/typ/compiler/let-25.typ b/test/typ/compiler/let-25.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-25.typ
@@ -0,0 +1,3 @@
+// Error: 10-11 destructuring key not found in dictionary
+#let (a, b: b) = (a: 1)
+
diff --git a/test/typ/compiler/let-26.typ b/test/typ/compiler/let-26.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-26.typ
@@ -0,0 +1,3 @@
+// Error: 7-11 cannot destructure named elements from an array
+#let (a: a, b) = (1, 2, 3)
+
diff --git a/test/typ/compiler/let-27.typ b/test/typ/compiler/let-27.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-27.typ
@@ -0,0 +1,32 @@
+// Error: 5 expected identifier
+#let
+
+// Error: 6 expected identifier
+#{let}
+
+// Error: 5 expected identifier
+// Error: 5 expected semicolon or line break
+#let "v"
+
+// Error: 7 expected semicolon or line break
+#let v 1
+
+// Error: 9 expected expression
+#let v =
+
+// Error: 5 expected identifier
+// Error: 5 expected semicolon or line break
+#let "v" = 1
+
+// Terminated because expression ends.
+// Error: 12 expected semicolon or line break
+#let v4 = 4 Four
+
+// Terminated by semicolon even though we are in a paren group.
+// Error: 18 expected expression
+// Error: 18 expected closing paren
+#let v5 = (1, 2 + ; Five
+
+// Error: 9-13 expected identifier, found boolean
+#let (..true) = false
+
diff --git a/test/typ/compiler/let-28.typ b/test/typ/compiler/let-28.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-28.typ
@@ -0,0 +1,19 @@
+#let _ = 4
+
+#for _ in range(2) []
+
+// Error: 2-3 unexpected underscore
+#_
+
+// Error: 8-9 unexpected underscore
+#lorem(_)
+
+// Error: 3-4 expected expression, found underscore
+#(_,)
+
+// Error: 3-4 expected expression, found underscore
+#{_}
+
+// Error: 8-9 expected expression, found underscore
+#{ 1 + _ }
+
diff --git a/test/typ/compiler/let-29.typ b/test/typ/compiler/let-29.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/let-29.typ
@@ -0,0 +1,5 @@
+// Error: 13 expected equals sign
+#let func(x)
+
+// Error: 15 expected expression
+#let func(x) =
diff --git a/test/typ/compiler/methods-00.typ b/test/typ/compiler/methods-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/methods-00.typ
@@ -0,0 +1,3 @@
+// Test whitespace around dot.
+#test( "Hi there" . split() , ("Hi", "there"))
+
diff --git a/test/typ/compiler/methods-01.typ b/test/typ/compiler/methods-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/methods-01.typ
@@ -0,0 +1,7 @@
+// Test mutating indexed value.
+#{
+  let matrix = (((1,), (2,)), ((3,), (4,)))
+  matrix.at(1).at(0).push(5)
+  test(matrix, (((1,), (2,)), ((3, 5), (4,))))
+}
+
diff --git a/test/typ/compiler/methods-02.typ b/test/typ/compiler/methods-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/methods-02.typ
@@ -0,0 +1,12 @@
+// Test multiline chain in code block.
+#{
+  let rewritten = "Hello. This is a sentence. And one more."
+    .split(".")
+    .map(s => s.trim())
+    .filter(s => s != "")
+    .map(s => s + "!")
+    .join("\n ")
+
+  test(rewritten, "Hello!\n This is a sentence!\n And one more!")
+}
+
diff --git a/test/typ/compiler/methods-03.typ b/test/typ/compiler/methods-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/methods-03.typ
@@ -0,0 +1,4 @@
+// Error: 2:2-2:15 type array has no method `fun`
+#let numbers = ()
+#numbers.fun()
+
diff --git a/test/typ/compiler/methods-04.typ b/test/typ/compiler/methods-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/methods-04.typ
@@ -0,0 +1,4 @@
+// Error: 2:2-2:43 cannot mutate a temporary value
+#let numbers = (1, 2, 3)
+#numbers.map(v => v / 2).sorted().map(str).remove(4)
+
diff --git a/test/typ/compiler/methods-05.typ b/test/typ/compiler/methods-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/methods-05.typ
@@ -0,0 +1,4 @@
+// Error: 2:3-2:19 cannot mutate a temporary value
+#let numbers = (1, 2, 3)
+#(numbers.sorted() = 1)
+
diff --git a/test/typ/compiler/methods-06.typ b/test/typ/compiler/methods-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/methods-06.typ
@@ -0,0 +1,2 @@
+// Error: 2-5 cannot mutate a constant: box
+#box.push(1)
diff --git a/test/typ/compiler/module.typ b/test/typ/compiler/module.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/module.typ
@@ -0,0 +1,13 @@
+// A file to import in import / include tests.
+// Ref: false
+
+#let a
+#let b = 1
+#let c = 2
+#let d = 3
+#let value = [hi]
+#let item(a, b) = a + b
+#let push(a) = a + 1
+#let fn = rect.with(fill: green, inset: 5pt)
+
+Some _includable_ text.
diff --git a/test/typ/compiler/modules/chap1.typ b/test/typ/compiler/modules/chap1.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/modules/chap1.typ
@@ -0,0 +1,9 @@
+// Ref: false
+
+#let name = "Klaus"
+
+== Chapter 1
+#name stood in a field of wheat. There was nothing of particular interest about
+the field #name just casually surveyed for any paths on which the corn would not
+totally ruin his semi-new outdorsy jacket but then again, most of us spend
+considerable time in non-descript environments.
diff --git a/test/typ/compiler/modules/chap2.typ b/test/typ/compiler/modules/chap2.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/modules/chap2.typ
@@ -0,0 +1,11 @@
+// Ref: false
+
+#let name = "Klaus"
+
+== Chapter 2
+Their motivations, however, were pretty descript, so to speak. #name had not yet
+conceptualized their consequences, but that should change pretty quickly. #name
+approached the center of the field and picked up a 4-foot long disk made from
+what could only be cow manure. The hair on the back of #name' neck bristled as
+he stared at the unusual sight. After studying the object for a while, he
+promptly popped the question, "How much?"
diff --git a/test/typ/compiler/modules/cycle1.typ b/test/typ/compiler/modules/cycle1.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/modules/cycle1.typ
@@ -0,0 +1,6 @@
+// Ref: false
+
+#import "cycle2.typ": *
+#let inaccessible = "wow"
+
+This is the first element of an import cycle.
diff --git a/test/typ/compiler/modules/cycle2.typ b/test/typ/compiler/modules/cycle2.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/modules/cycle2.typ
@@ -0,0 +1,6 @@
+// Ref: false
+
+#import "cycle1.typ": *
+#let val = "much cycle"
+
+This is the second element of an import cycle.
diff --git a/test/typ/compiler/ops-00.typ b/test/typ/compiler/ops-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-00.typ
@@ -0,0 +1,4 @@
+// Test adding content.
+// Ref: true
+#([*Hello* ] + [world!])
+
diff --git a/test/typ/compiler/ops-01.typ b/test/typ/compiler/ops-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-01.typ
@@ -0,0 +1,26 @@
+// Test math operators.
+
+// Test plus and minus.
+#for v in (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt, 6.3fr) {
+  // Test plus.
+  test(+v, v)
+
+  // Test minus.
+  test(-v, -1 * v)
+  test(--v, v)
+
+  // Test combination.
+  test(-++ --v, -v)
+}
+
+#test(-(4 + 2), 6-12)
+
+// Addition.
+#test(2 + 4, 6)
+#test("a" + "b", "ab")
+#test("a" + if false { "b" }, "a")
+#test("a" + if true { "b" }, "ab")
+#test(13 * "a" + "bbbbbb", "aaaaaaaaaaaaabbbbbb")
+#test((1, 2) + (3, 4), (1, 2, 3, 4))
+#test((a: 1) + (b: 2, c: 3), (a: 1, b: 2, c: 3))
+
diff --git a/test/typ/compiler/ops-02.typ b/test/typ/compiler/ops-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-02.typ
@@ -0,0 +1,3 @@
+// Error: 3-26 value is too large
+#(9223372036854775807 + 1)
+
diff --git a/test/typ/compiler/ops-03.typ b/test/typ/compiler/ops-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-03.typ
@@ -0,0 +1,76 @@
+// Subtraction.
+#test(1-4, 3*-1)
+#test(4cm - 2cm, 2cm)
+#test(1e+2-1e-2, 99.99)
+
+// Multiplication.
+#test(2 * 4, 8)
+
+// Division.
+#test(12pt/.4, 30pt)
+#test(7 / 2, 3.5)
+
+// Combination.
+#test(3-4 * 5 < -10, true)
+#test({ let x; x = 1 + 4*5 >= 21 and { x = "a"; x + "b" == "ab" }; x }, true)
+
+// With block.
+#test(if true {
+  1
+} + 2, 3)
+
+// Mathematical identities.
+#let nums = (
+  1, 3.14,
+  12pt, 3em, 12pt + 3em,
+  45deg,
+  90%,
+  13% + 10pt, 5% + 1em + 3pt,
+  2.3fr,
+)
+
+#for v in nums {
+  // Test plus and minus.
+  test(v + v - v, v)
+  test(v - v - v, -v)
+
+  // Test plus/minus and multiplication.
+  test(v - v, 0 * v)
+  test(v + v, 2 * v)
+
+  // Integer addition does not give a float.
+  if type(v) != "integer" {
+    test(v + v, 2.0 * v)
+  }
+
+  if "relative" not in type(v) and ("pt" not in repr(v) or "em" not in repr(v)) {
+    test(v / v, 1.0)
+  }
+}
+
+// Make sure length, ratio and relative length
+// - can all be added to / subtracted from each other,
+// - multiplied with integers and floats,
+// - divided by integers and floats.
+#let dims = (10pt, 1em, 10pt + 1em, 30%, 50% + 3cm, 40% + 2em + 1cm)
+#for a in dims {
+  for b in dims {
+    test(type(a + b), type(a - b))
+  }
+
+  for b in (7, 3.14) {
+    test(type(a * b), type(a))
+    test(type(b * a), type(a))
+    test(type(a / b), type(a))
+  }
+}
+
+// Test division of different numeric types with zero components.
+#for a in (0pt, 0em, 0%) {
+  for b in (10pt, 10em, 10%) {
+    test((2 * b) / b, 2)
+    test((a + b * 2) / b, 2)
+    test(b / (b * 2 + a), 0.5)
+  }
+}
+
diff --git a/test/typ/compiler/ops-04.typ b/test/typ/compiler/ops-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-04.typ
@@ -0,0 +1,5 @@
+// Test numbers with alternative bases.
+#test(0x10, 16)
+#test(0b1101, 13)
+#test(0xA + 0xa, 0x14)
+
diff --git a/test/typ/compiler/ops-05.typ b/test/typ/compiler/ops-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-05.typ
@@ -0,0 +1,3 @@
+// Error: 2-7 invalid binary number: 0b123
+#0b123
+
diff --git a/test/typ/compiler/ops-06.typ b/test/typ/compiler/ops-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-06.typ
@@ -0,0 +1,3 @@
+// Error: 2-8 invalid hexadecimal number: 0x123z
+#0x123z
+
diff --git a/test/typ/compiler/ops-07.typ b/test/typ/compiler/ops-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-07.typ
@@ -0,0 +1,22 @@
+// Test boolean operators.
+
+// Test not.
+#test(not true, false)
+#test(not false, true)
+
+// And.
+#test(false and false, false)
+#test(false and true, false)
+#test(true and false, false)
+#test(true and true, true)
+
+// Or.
+#test(false or false, false)
+#test(false or true, true)
+#test(true or false, true)
+#test(true or true, true)
+
+// Short-circuiting.
+#test(false and dont-care, false)
+#test(true or dont-care, true)
+
diff --git a/test/typ/compiler/ops-08.typ b/test/typ/compiler/ops-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-08.typ
@@ -0,0 +1,27 @@
+// Test equality operators.
+
+// Most things compare by value.
+#test(1 == "hi", false)
+#test(1 == 1.0, true)
+#test(30% == 30% + 0cm, true)
+#test(1in == 0% + 72pt, true)
+#test(30% == 30% + 1cm, false)
+#test("ab" == "a" + "b", true)
+#test(() == (1,), false)
+#test((1, 2, 3) == (1, 2.0) + (3,), true)
+#test((:) == (a: 1), false)
+#test((a: 2 - 1.0, b: 2) == (b: 2, a: 1), true)
+#test("a" != "a", false)
+
+// Functions compare by identity.
+#test(test == test, true)
+#test((() => {}) == (() => {}), false)
+
+// Content compares field by field.
+#let t = [a]
+#test(t == t, true)
+#test([] == [], true)
+#test([a] == [a], true)
+#test(grid[a] == grid[a], true)
+#test(grid[a] == grid[b], false)
+
diff --git a/test/typ/compiler/ops-09.typ b/test/typ/compiler/ops-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-09.typ
@@ -0,0 +1,13 @@
+// Test comparison operators.
+
+#test(13 * 3 < 14 * 4, true)
+#test(5 < 10, true)
+#test(5 > 5, false)
+#test(5 <= 5, true)
+#test(5 <= 4, false)
+#test(45deg < 1rad, true)
+#test(10% < 20%, true)
+#test(50% < 40% + 0pt, false)
+#test(40% + 0pt < 50% + 0pt, true)
+#test(1em < 2em, true)
+
diff --git a/test/typ/compiler/ops-10.typ b/test/typ/compiler/ops-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-10.typ
@@ -0,0 +1,11 @@
+// Test assignment operators.
+
+#let x = 0
+#(x = 10)       #test(x, 10)
+#(x -= 5)       #test(x, 5)
+#(x += 1)       #test(x, 6)
+#(x *= x)       #test(x, 36)
+#(x /= 2.0)     #test(x, 18.0)
+#(x = "some")   #test(x, "some")
+#(x += "thing") #test(x, "something")
+
diff --git a/test/typ/compiler/ops-11.typ b/test/typ/compiler/ops-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-11.typ
@@ -0,0 +1,41 @@
+// Test destructuring assignments.
+
+#let a = none
+#let b = none
+#let c = none
+#((a,) = (1,))
+#test(a, 1)
+
+#((_, a, b, _) = (1, 2, 3, 4))
+#test(a, 2)
+#test(b, 3)
+
+#((a, b, ..c) = (1, 2, 3, 4, 5, 6))
+#test(a, 1)
+#test(b, 2)
+#test(c, (3, 4, 5, 6))
+
+#((a: a, b, x: c) = (a: 1, b: 2, x: 3))
+#test(a, 1)
+#test(b, 2)
+#test(c, 3)
+
+#let a = (1, 2)
+#((a: a.at(0), b) = (a: 3, b: 4))
+#test(a, (3, 2))
+#test(b, 4)
+
+#let a = (1, 2)
+#((a.at(0), b) = (3, 4))
+#test(a, (3, 2))
+#test(b, 4)
+
+#((a, ..b) = (1, 2, 3, 4))
+#test(a, 1)
+#test(b, (2, 3, 4))
+
+#let a = (1, 2)
+#((b, ..a.at(0)) = (1, 2, 3, 4))
+#test(a, ((2, 3, 4), 2))
+#test(b, 1)
+
diff --git a/test/typ/compiler/ops-12.typ b/test/typ/compiler/ops-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-12.typ
@@ -0,0 +1,3 @@
+// Error: 3-6 cannot mutate a constant: box
+#(box = 1)
+
diff --git a/test/typ/compiler/ops-13.typ b/test/typ/compiler/ops-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-13.typ
@@ -0,0 +1,14 @@
+// Test `in` operator.
+#test("hi" in "worship", true)
+#test("hi" in ("we", "hi", "bye"), true)
+#test("Hey" in "abHeyCd", true)
+#test("Hey" in "abheyCd", false)
+#test(5 in range(10), true)
+#test(12 in range(10), false)
+#test("" in (), false)
+#test("key" in (key: "value"), true)
+#test("value" in (key: "value"), false)
+#test("Hey" not in "abheyCd", true)
+#test("a" not
+/* fun comment? */ in "abc", false)
+
diff --git a/test/typ/compiler/ops-14.typ b/test/typ/compiler/ops-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-14.typ
@@ -0,0 +1,3 @@
+// Error: 10 expected keyword `in`
+#("a" not)
+
diff --git a/test/typ/compiler/ops-15.typ b/test/typ/compiler/ops-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-15.typ
@@ -0,0 +1,16 @@
+// Test `with` method.
+
+// Apply positional arguments.
+#let add(x, y) = x + y
+#test(add.with(2)(3), 5)
+#test(add.with(2).with(3)(), 5)
+#test((add.with(2))(4), 6)
+#test((add.with(2).with(3))(), 5)
+
+// Make sure that named arguments are overridable.
+#let inc(x, y: 1) = x + y
+#test(inc(1), 2)
+
+#let inc2 = inc.with(y: 2)
+#test(inc2(2), 4)
+#test(inc2(2, y: 4), 6)
diff --git a/test/typ/compiler/ops-assoc-00.typ b/test/typ/compiler/ops-assoc-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-assoc-00.typ
@@ -0,0 +1,5 @@
+// Math operators are left-associative.
+#test(10 / 2 / 2 == (10 / 2) / 2, true)
+#test(10 / 2 / 2 == 10 / (2 / 2), false)
+#test(1 / 2 * 3, 1.5)
+
diff --git a/test/typ/compiler/ops-assoc-01.typ b/test/typ/compiler/ops-assoc-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-assoc-01.typ
@@ -0,0 +1,8 @@
+// Assignment is right-associative.
+{
+  let x = 1
+  let y = 2
+  x = y = "ok"
+  test(x, none)
+  test(y, "ok")
+}
diff --git a/test/typ/compiler/ops-invalid-00.typ b/test/typ/compiler/ops-invalid-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-00.typ
@@ -0,0 +1,3 @@
+// Error: 4 expected expression
+#(-)
+
diff --git a/test/typ/compiler/ops-invalid-01.typ b/test/typ/compiler/ops-invalid-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-01.typ
@@ -0,0 +1,3 @@
+// Error: 10 expected expression
+#test({1+}, 1)
+
diff --git a/test/typ/compiler/ops-invalid-02.typ b/test/typ/compiler/ops-invalid-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-02.typ
@@ -0,0 +1,3 @@
+// Error: 10 expected expression
+#test({2*}, 2)
+
diff --git a/test/typ/compiler/ops-invalid-03.typ b/test/typ/compiler/ops-invalid-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-03.typ
@@ -0,0 +1,3 @@
+// Error: 3-13 cannot apply '+' to content
+#(+([] + []))
+
diff --git a/test/typ/compiler/ops-invalid-04.typ b/test/typ/compiler/ops-invalid-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-04.typ
@@ -0,0 +1,3 @@
+// Error: 3-6 cannot apply '-' to string
+#(-"")
+
diff --git a/test/typ/compiler/ops-invalid-05.typ b/test/typ/compiler/ops-invalid-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-05.typ
@@ -0,0 +1,3 @@
+// Error: 3-9 cannot apply 'not' to array
+#(not ())
+
diff --git a/test/typ/compiler/ops-invalid-06.typ b/test/typ/compiler/ops-invalid-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-06.typ
@@ -0,0 +1,3 @@
+// Error: 3-19 cannot apply '<=' to relative length and ratio
+#(30% + 1pt <= 40%)
+
diff --git a/test/typ/compiler/ops-invalid-07.typ b/test/typ/compiler/ops-invalid-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-07.typ
@@ -0,0 +1,3 @@
+// Error: 3-14 cannot apply '<=' to length and length
+#(1em <= 10pt)
+
diff --git a/test/typ/compiler/ops-invalid-08.typ b/test/typ/compiler/ops-invalid-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-08.typ
@@ -0,0 +1,3 @@
+// Error: 3-12 cannot divide by zero
+#(1.2 / 0.0)
+
diff --git a/test/typ/compiler/ops-invalid-09.typ b/test/typ/compiler/ops-invalid-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-09.typ
@@ -0,0 +1,3 @@
+// Error: 3-8 cannot divide by zero
+#(1 / 0)
+
diff --git a/test/typ/compiler/ops-invalid-10.typ b/test/typ/compiler/ops-invalid-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-10.typ
@@ -0,0 +1,3 @@
+// Error: 3-15 cannot divide by zero
+#(15deg / 0deg)
+
diff --git a/test/typ/compiler/ops-invalid-11.typ b/test/typ/compiler/ops-invalid-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-11.typ
@@ -0,0 +1,4 @@
+// Special messages for +, -, * and /.
+// Error: 3-10 cannot add integer and string
+#(1 + "2", 40% - 1)
+
diff --git a/test/typ/compiler/ops-invalid-12.typ b/test/typ/compiler/ops-invalid-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-12.typ
@@ -0,0 +1,3 @@
+// Error: 15-23 cannot add integer and string
+#{ let x = 1; x += "2" }
+
diff --git a/test/typ/compiler/ops-invalid-13.typ b/test/typ/compiler/ops-invalid-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-13.typ
@@ -0,0 +1,3 @@
+// Error: 4-13 cannot divide ratio by length
+#( 10% / 5pt )
+
diff --git a/test/typ/compiler/ops-invalid-14.typ b/test/typ/compiler/ops-invalid-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-14.typ
@@ -0,0 +1,3 @@
+// Error: 3-12 cannot divide these two lengths
+#(1em / 5pt)
+
diff --git a/test/typ/compiler/ops-invalid-15.typ b/test/typ/compiler/ops-invalid-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-15.typ
@@ -0,0 +1,3 @@
+// Error: 3-19 cannot divide relative length by ratio
+#((10% + 1pt) / 5%)
+
diff --git a/test/typ/compiler/ops-invalid-16.typ b/test/typ/compiler/ops-invalid-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-16.typ
@@ -0,0 +1,3 @@
+// Error: 3-28 cannot divide these two relative lengths
+#((10% + 1pt) / (20% + 1pt))
+
diff --git a/test/typ/compiler/ops-invalid-17.typ b/test/typ/compiler/ops-invalid-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-17.typ
@@ -0,0 +1,3 @@
+// Error: 13-20 cannot subtract integer from ratio
+#((1234567, 40% - 1))
+
diff --git a/test/typ/compiler/ops-invalid-18.typ b/test/typ/compiler/ops-invalid-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-18.typ
@@ -0,0 +1,3 @@
+// Error: 3-11 cannot multiply integer with boolean
+#(2 * true)
+
diff --git a/test/typ/compiler/ops-invalid-19.typ b/test/typ/compiler/ops-invalid-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-19.typ
@@ -0,0 +1,3 @@
+// Error: 3-11 cannot divide integer by length
+#(3 / 12pt)
+
diff --git a/test/typ/compiler/ops-invalid-20.typ b/test/typ/compiler/ops-invalid-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-20.typ
@@ -0,0 +1,3 @@
+// Error: 3-10 cannot repeat this string -1 times
+#(-1 * "")
+
diff --git a/test/typ/compiler/ops-invalid-21.typ b/test/typ/compiler/ops-invalid-21.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-21.typ
@@ -0,0 +1,9 @@
+#{
+  let x = 2
+  for _ in range(61) {
+    (x) *= 2
+  }
+  // Error: 3-17 cannot repeat this string 4611686018427387904 times
+  x * "abcdefgh"
+}
+
diff --git a/test/typ/compiler/ops-invalid-22.typ b/test/typ/compiler/ops-invalid-22.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-22.typ
@@ -0,0 +1,3 @@
+// Error: 4-5 unknown variable: x
+#((x) = "")
+
diff --git a/test/typ/compiler/ops-invalid-23.typ b/test/typ/compiler/ops-invalid-23.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-23.typ
@@ -0,0 +1,3 @@
+// Error: 4-5 unknown variable: x
+#((x,) = (1,))
+
diff --git a/test/typ/compiler/ops-invalid-24.typ b/test/typ/compiler/ops-invalid-24.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-24.typ
@@ -0,0 +1,3 @@
+// Error: 3-8 cannot mutate a temporary value
+#(1 + 2 += 3)
+
diff --git a/test/typ/compiler/ops-invalid-25.typ b/test/typ/compiler/ops-invalid-25.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-25.typ
@@ -0,0 +1,4 @@
+// Error: 2:3-2:8 cannot apply 'not' to string
+#let x = "Hey"
+#(not x = "a")
+
diff --git a/test/typ/compiler/ops-invalid-26.typ b/test/typ/compiler/ops-invalid-26.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-26.typ
@@ -0,0 +1,3 @@
+// Error: 7-8 unknown variable: x
+#(1 + x += 3)
+
diff --git a/test/typ/compiler/ops-invalid-27.typ b/test/typ/compiler/ops-invalid-27.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-27.typ
@@ -0,0 +1,3 @@
+// Error: 3-4 unknown variable: z
+#(z = 1)
+
diff --git a/test/typ/compiler/ops-invalid-28.typ b/test/typ/compiler/ops-invalid-28.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-28.typ
@@ -0,0 +1,3 @@
+// Error: 3-7 cannot mutate a constant: rect
+#(rect = "hi")
+
diff --git a/test/typ/compiler/ops-invalid-29.typ b/test/typ/compiler/ops-invalid-29.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-invalid-29.typ
@@ -0,0 +1,4 @@
+// Works if we define rect beforehand
+// (since then it doesn't resolve to the standard library version anymore).
+#let rect = ""
+#(rect = "hi")
diff --git a/test/typ/compiler/ops-prec-00.typ b/test/typ/compiler/ops-prec-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-prec-00.typ
@@ -0,0 +1,10 @@
+// Multiplication binds stronger than addition.
+#test(1+2*-3, -5)
+
+// Subtraction binds stronger than comparison.
+#test(3 == 5 - 2, true)
+
+// Boolean operations bind stronger than '=='.
+#test("a" == "a" and 2 < 3, true)
+#test(not "b" == "b", false)
+
diff --git a/test/typ/compiler/ops-prec-01.typ b/test/typ/compiler/ops-prec-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-prec-01.typ
@@ -0,0 +1,5 @@
+// Assignment binds stronger than boolean operations.
+// Error: 2:3-2:8 cannot mutate a temporary value
+#let x = false
+#(not x = "a")
+
diff --git a/test/typ/compiler/ops-prec-02.typ b/test/typ/compiler/ops-prec-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-prec-02.typ
@@ -0,0 +1,4 @@
+// Precedence doesn't matter for chained unary operators.
+// Error: 3-12 cannot apply '-' to boolean
+#(-not true)
+
diff --git a/test/typ/compiler/ops-prec-03.typ b/test/typ/compiler/ops-prec-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-prec-03.typ
@@ -0,0 +1,3 @@
+// Not in handles precedence.
+#test(-1 not in (1, 2, 3), true)
+
diff --git a/test/typ/compiler/ops-prec-04.typ b/test/typ/compiler/ops-prec-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/ops-prec-04.typ
@@ -0,0 +1,6 @@
+// Parentheses override precedence.
+#test((1), 1)
+#test((1+2)*-3, -9)
+
+// Error: 14 expected closing paren
+#test({(1 + 1}, 2)
diff --git a/test/typ/compiler/recursion-00.typ b/test/typ/compiler/recursion-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/recursion-00.typ
@@ -0,0 +1,11 @@
+// Test with named function.
+#let fib(n) = {
+  if n <= 2 {
+    1
+  } else {
+    fib(n - 1) + fib(n - 2)
+  }
+}
+
+#test(fib(10), 55)
+
diff --git a/test/typ/compiler/recursion-01.typ b/test/typ/compiler/recursion-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/recursion-01.typ
@@ -0,0 +1,5 @@
+// Test with unnamed function.
+// Error: 17-18 unknown variable: f
+#let f = (n) => f(n - 1)
+#f(10)
+
diff --git a/test/typ/compiler/recursion-02.typ b/test/typ/compiler/recursion-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/recursion-02.typ
@@ -0,0 +1,5 @@
+// Test capturing with named function.
+#let f = 10
+#let f() = f
+#test(type(f()), "function")
+
diff --git a/test/typ/compiler/recursion-03.typ b/test/typ/compiler/recursion-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/recursion-03.typ
@@ -0,0 +1,5 @@
+// Test capturing with unnamed function.
+#let f = 10
+#let f = () => f
+#test(type(f()), "integer")
+
diff --git a/test/typ/compiler/recursion-04.typ b/test/typ/compiler/recursion-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/recursion-04.typ
@@ -0,0 +1,4 @@
+// Error: 15-21 maximum function call depth exceeded
+#let rec(n) = rec(n) + 1
+#rec(1)
+
diff --git a/test/typ/compiler/recursion-05.typ b/test/typ/compiler/recursion-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/recursion-05.typ
@@ -0,0 +1,3 @@
+#let f(x) = "hello"
+#let f(x) = if x != none { f(none) } else { "world" }
+#test(f(1), "world")
diff --git a/test/typ/compiler/repr-00.typ b/test/typ/compiler/repr-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/repr-00.typ
@@ -0,0 +1,6 @@
+// Literal values.
+#auto \
+#none (empty) \
+#true \
+#false
+
diff --git a/test/typ/compiler/repr-01.typ b/test/typ/compiler/repr-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/repr-01.typ
@@ -0,0 +1,16 @@
+// Numerical values.
+#1 \
+#1.0e-4 \
+#3.15 \
+#1e-10 \
+#50.368% \
+#0.0000012345pt \
+#4.5cm \
+#12e1pt \
+#2.5rad \
+#45deg \
+#1.7em \
+#(1cm + 0em) \
+#(2em + 10pt) \
+#2.3fr
+
diff --git a/test/typ/compiler/repr-02.typ b/test/typ/compiler/repr-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/repr-02.typ
@@ -0,0 +1,18 @@
+// Colors and strokes.
+#set text(0.8em)
+#rgb("f7a205") \
+#(2pt + rgb("f7a205"))
+
+// Strings and escaping.
+#raw(repr("hi"), lang: "typc")
+#repr("a\n[]\"\u{1F680}string")
+
+// Content.
+#raw(lang: "typc", repr[*Hey*])
+
+// Functions are invisible.
+Nothing
+#let f(x) = x
+#f
+#rect
+#(() => none)
diff --git a/test/typ/compiler/return-00.typ b/test/typ/compiler/return-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/return-00.typ
@@ -0,0 +1,7 @@
+// Test return with value.
+#let f(x) = {
+  return x + 1
+}
+
+#test(f(1), 2)
+
diff --git a/test/typ/compiler/return-01.typ b/test/typ/compiler/return-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/return-01.typ
@@ -0,0 +1,19 @@
+// Test return with joining.
+
+#let f(x) = {
+  "a"
+  if x == 0 {
+    return "b"
+  } else if x == 1 {
+    "c"
+  } else {
+    "d"
+    return
+    "e"
+  }
+}
+
+#test(f(0), "b")
+#test(f(1), "ac")
+#test(f(2), "ad")
+
diff --git a/test/typ/compiler/return-02.typ b/test/typ/compiler/return-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/return-02.typ
@@ -0,0 +1,15 @@
+// Test return with joining and content.
+// Ref: true
+
+#let f(text, caption: none) = {
+  text
+  if caption == none [\.#return]
+  [, ]
+  emph(caption)
+  [\.]
+}
+
+#f(caption: [with caption])[My figure]
+
+#f[My other figure]
+
diff --git a/test/typ/compiler/return-03.typ b/test/typ/compiler/return-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/return-03.typ
@@ -0,0 +1,7 @@
+// Test return outside of function.
+
+#for x in range(5) {
+  // Error: 3-9 cannot return outside of function
+  return
+}
+
diff --git a/test/typ/compiler/return-04.typ b/test/typ/compiler/return-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/return-04.typ
@@ -0,0 +1,16 @@
+// Test that the expression is evaluated to the end.
+#let sum(..args) = {
+  let s = 0
+  for v in args.pos() {
+    s += v
+  }
+  s
+}
+
+#let f() = {
+  sum(..return, 1, 2, 3)
+  "nope"
+}
+
+#test(f(), 6)
+
diff --git a/test/typ/compiler/return-05.typ b/test/typ/compiler/return-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/return-05.typ
@@ -0,0 +1,9 @@
+// Test value return from content.
+#let x = 3
+#let f() = [
+  Hello 😀
+  #return "nope"
+  World
+]
+
+#test(f(), "nope")
diff --git a/test/typ/compiler/set-00.typ b/test/typ/compiler/set-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-00.typ
@@ -0,0 +1,4 @@
+// Test that text is affected by instantiation-site bold.
+#let x = [World]
+Hello *#x*
+
diff --git a/test/typ/compiler/set-01.typ b/test/typ/compiler/set-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-01.typ
@@ -0,0 +1,12 @@
+// Test that lists are affected by correct indents.
+#let fruit = [
+  - Apple
+  - Orange
+  #list(body-indent: 20pt)[Pear]
+]
+
+- Fruit
+#[#set list(indent: 10pt)
+ #fruit]
+- No more fruit
+
diff --git a/test/typ/compiler/set-02.typ b/test/typ/compiler/set-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-02.typ
@@ -0,0 +1,7 @@
+// Test that that block spacing and text style are respected from
+// the outside, but the more specific fill is respected.
+#set block(spacing: 4pt)
+#set text(style: "italic", fill: eastern)
+#let x = [And the red #parbreak() lay silent!]
+#text(fill: red, x)
+
diff --git a/test/typ/compiler/set-03.typ b/test/typ/compiler/set-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-03.typ
@@ -0,0 +1,9 @@
+// Test that scoping works as expected.
+#{
+  if true {
+    set text(blue)
+    [Blue ]
+  }
+  [Not blue]
+}
+
diff --git a/test/typ/compiler/set-04.typ b/test/typ/compiler/set-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-04.typ
@@ -0,0 +1,11 @@
+// Test relative path resolving in layout phase.
+#let choice = ("monkey.svg", "rhino.png", "tiger.jpg")
+#set enum(numbering: n => {
+  let path = "/" + choice.at(n - 1)
+  move(dy: -0.15em, image(path, width: 1em, height: 1em))
+})
+
++ Monkey
++ Rhino
++ Tiger
+
diff --git a/test/typ/compiler/set-05.typ b/test/typ/compiler/set-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-05.typ
@@ -0,0 +1,8 @@
+// Test conditional set.
+#show ref: it => {
+  set text(red) if it.target == <unknown>
+  "@" + str(it.target)
+}
+
+@hello from the @unknown
+
diff --git a/test/typ/compiler/set-06.typ b/test/typ/compiler/set-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-06.typ
@@ -0,0 +1,3 @@
+// Error: 19-24 expected boolean, found integer
+#set text(red) if 1 + 2
+
diff --git a/test/typ/compiler/set-07.typ b/test/typ/compiler/set-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/set-07.typ
@@ -0,0 +1,2 @@
+// Error: 12-26 set is only allowed directly in code and content blocks
+#{ let x = set text(blue) }
diff --git a/test/typ/compiler/shorthand-00.typ b/test/typ/compiler/shorthand-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/shorthand-00.typ
@@ -0,0 +1,2 @@
+The non-breaking~space does work.
+
diff --git a/test/typ/compiler/shorthand-01.typ b/test/typ/compiler/shorthand-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/shorthand-01.typ
@@ -0,0 +1,7 @@
+// Make sure non-breaking and normal space always
+// have the same width. Even if the font decided
+// differently.
+#set text(font: "New Computer Modern")
+a b \
+a~b
+
diff --git a/test/typ/compiler/shorthand-02.typ b/test/typ/compiler/shorthand-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/shorthand-02.typ
@@ -0,0 +1,3 @@
+- En dash: --
+- Em dash: ---
+
diff --git a/test/typ/compiler/shorthand-03.typ b/test/typ/compiler/shorthand-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/shorthand-03.typ
@@ -0,0 +1,2 @@
+#set text(font: "Roboto")
+A... vs #"A..."
diff --git a/test/typ/compiler/show-bare-00.typ b/test/typ/compiler/show-bare-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-bare-00.typ
@@ -0,0 +1,13 @@
+#set page(height: 130pt)
+#set text(0.7em)
+
+#align(center)[
+  #text(1.3em)[*Essay on typography*] \
+  T. Ypst
+]
+
+#show: columns.with(2)
+Great typography is at the essence of great storytelling. It is the medium that
+transports meaning from parchment to reader, the wave that sparks a flame
+in booklovers and the great fulfiller of human need.
+
diff --git a/test/typ/compiler/show-bare-01.typ b/test/typ/compiler/show-bare-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-bare-01.typ
@@ -0,0 +1,3 @@
+// Test bare show in content block.
+A #[_B #show: c => [*#c*]; C_] D
+
diff --git a/test/typ/compiler/show-bare-02.typ b/test/typ/compiler/show-bare-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-bare-02.typ
@@ -0,0 +1,5 @@
+// Test style precedence.
+#set text(fill: eastern, size: 1.5em)
+#show: text.with(fill: red)
+Forest
+
diff --git a/test/typ/compiler/show-bare-03.typ b/test/typ/compiler/show-bare-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-bare-03.typ
@@ -0,0 +1,3 @@
+#show: [Shown]
+Ignored
+
diff --git a/test/typ/compiler/show-bare-04.typ b/test/typ/compiler/show-bare-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-bare-04.typ
@@ -0,0 +1,3 @@
+// Error: 4-19 show is only allowed directly in code and content blocks
+#((show: body => 2) * body)
+
diff --git a/test/typ/compiler/show-bare-05.typ b/test/typ/compiler/show-bare-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-bare-05.typ
@@ -0,0 +1,3 @@
+// Error: 6 expected colon
+#show it => {}
+
diff --git a/test/typ/compiler/show-bare-06.typ b/test/typ/compiler/show-bare-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-bare-06.typ
@@ -0,0 +1,2 @@
+// Error: 6 expected colon
+#show it
diff --git a/test/typ/compiler/show-node-00.typ b/test/typ/compiler/show-node-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-00.typ
@@ -0,0 +1,9 @@
+// Override lists.
+#show list: it => "(" + it.children.map(v => v.body).join(", ") + ")"
+
+- A
+  - B
+  - C
+- D
+- E
+
diff --git a/test/typ/compiler/show-node-01.typ b/test/typ/compiler/show-node-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-01.typ
@@ -0,0 +1,5 @@
+// Test full reset.
+#show heading: [B]
+#show heading: set text(size: 10pt, weight: 400)
+A #[= Heading] C
+
diff --git a/test/typ/compiler/show-node-02.typ b/test/typ/compiler/show-node-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-02.typ
@@ -0,0 +1,7 @@
+// Test full removal.
+#show heading: none
+
+Where is
+= There are no headings around here!
+my heading?
+
diff --git a/test/typ/compiler/show-node-03.typ b/test/typ/compiler/show-node-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-03.typ
@@ -0,0 +1,21 @@
+// Test integrated example.
+#show heading: it => block({
+  set text(10pt)
+  box(move(dy: -1pt)[📖])
+  h(5pt)
+  if it.level == 1 {
+    underline(text(1.25em, blue, it.body))
+  } else {
+    text(red, it.body)
+  }
+})
+
+= Task 1
+Some text.
+
+== Subtask
+Some more text.
+
+= Task 2
+Another text.
+
diff --git a/test/typ/compiler/show-node-04.typ b/test/typ/compiler/show-node-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-04.typ
@@ -0,0 +1,9 @@
+// Test set and show in code blocks.
+#show heading: it => {
+  set text(red)
+  show "ding": [🛎]
+  it.body
+}
+
+= Heading
+
diff --git a/test/typ/compiler/show-node-05.typ b/test/typ/compiler/show-node-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-05.typ
@@ -0,0 +1,16 @@
+// Test that scoping works as expected.
+#{
+  let world = [ World ]
+  show "W": strong
+  world
+  {
+    set text(blue)
+    show: it => {
+      show "o": "Ø"
+      it
+    }
+    world
+  }
+  world
+}
+
diff --git a/test/typ/compiler/show-node-06.typ b/test/typ/compiler/show-node-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-06.typ
@@ -0,0 +1,3 @@
+#show heading: [1234]
+= Heading
+
diff --git a/test/typ/compiler/show-node-07.typ b/test/typ/compiler/show-node-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-07.typ
@@ -0,0 +1,4 @@
+// Error: 25-29 content does not contain field "page" and no default value was specified
+#show heading: it => it.page
+= Heading
+
diff --git a/test/typ/compiler/show-node-08.typ b/test/typ/compiler/show-node-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-08.typ
@@ -0,0 +1,3 @@
+#show text: none
+Hey
+
diff --git a/test/typ/compiler/show-node-09.typ b/test/typ/compiler/show-node-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-09.typ
@@ -0,0 +1,3 @@
+// Error: 7-12 only element functions can be used as selectors
+#show upper: it => {}
+
diff --git a/test/typ/compiler/show-node-10.typ b/test/typ/compiler/show-node-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-10.typ
@@ -0,0 +1,4 @@
+// Error: 16-20 expected content or function, found integer
+#show heading: 1234
+= Heading
+
diff --git a/test/typ/compiler/show-node-11.typ b/test/typ/compiler/show-node-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-11.typ
@@ -0,0 +1,3 @@
+// Error: 7-10 expected function, label, string, regular expression, symbol, or selector, found color
+#show red: []
+
diff --git a/test/typ/compiler/show-node-12.typ b/test/typ/compiler/show-node-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-node-12.typ
@@ -0,0 +1,2 @@
+// Error: 7-25 show is only allowed directly in code and content blocks
+#(1 + show heading: none)
diff --git a/test/typ/compiler/show-recursive-00.typ b/test/typ/compiler/show-recursive-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-recursive-00.typ
@@ -0,0 +1,4 @@
+// Test basic identity.
+#show heading: it => it
+= Heading
+
diff --git a/test/typ/compiler/show-recursive-01.typ b/test/typ/compiler/show-recursive-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-recursive-01.typ
@@ -0,0 +1,9 @@
+// Test more recipes down the chain.
+#show list: scale.with(origin: left, x: 80%)
+#show heading: []
+#show enum: []
+- Actual
+- Tight
+- List
+= Nope
+
diff --git a/test/typ/compiler/show-recursive-02.typ b/test/typ/compiler/show-recursive-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-recursive-02.typ
@@ -0,0 +1,22 @@
+// Test show rule in function.
+#let starwars(body) = {
+  show list: it => block({
+    stack(dir: ltr,
+      text(red, it),
+      1fr,
+      scale(x: -100%, text(blue, it)),
+    )
+  })
+  body
+}
+
+- Normal list
+
+#starwars[
+  - Star
+  - Wars
+  - List
+]
+
+- Normal list
+
diff --git a/test/typ/compiler/show-recursive-03.typ b/test/typ/compiler/show-recursive-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-recursive-03.typ
@@ -0,0 +1,10 @@
+// Test multi-recursion with nested lists.
+#set rect(inset: 3pt)
+#show list: rect.with(stroke: blue)
+#show list: rect.with(stroke: red)
+#show list: block
+
+- List
+  - Nested
+  - List
+- Recursive!
diff --git a/test/typ/compiler/show-selector-00.typ b/test/typ/compiler/show-selector-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-selector-00.typ
@@ -0,0 +1,29 @@
+// Inline code.
+#show raw.where(block: false): box.with(
+  radius: 2pt,
+  outset: (y: 2.5pt),
+  inset: (x: 3pt, y: 0pt),
+  fill: luma(230),
+)
+
+// Code blocks.
+#show raw.where(block: true): block.with(
+  outset: -3pt,
+  inset: 11pt,
+  fill: luma(230),
+  stroke: (left: 1.5pt + luma(180)),
+)
+
+#set page(margin: (top: 12pt))
+#set par(justify: true)
+
+This code tests `code`
+with selectors and justification.
+
+```rs
+code!("it");
+```
+
+You can use the ```rs *const T``` pointer or
+the ```rs &mut T``` reference.
+
diff --git a/test/typ/compiler/show-selector-01.typ b/test/typ/compiler/show-selector-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-selector-01.typ
@@ -0,0 +1,7 @@
+#show heading.where(level: 1): set text(red)
+#show heading.where(level: 2): set text(blue)
+#show heading: set text(green)
+= Red
+== Blue
+=== Green
+
diff --git a/test/typ/compiler/show-selector-02.typ b/test/typ/compiler/show-selector-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-selector-02.typ
@@ -0,0 +1,2 @@
+// Error: 7-35 this selector cannot be used with show
+#show selector(heading).or(strong): none
diff --git a/test/typ/compiler/show-text-00.typ b/test/typ/compiler/show-text-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-00.typ
@@ -0,0 +1,5 @@
+// Test classic example.
+#set text(font: "Roboto")
+#show "Der Spiegel": smallcaps
+Die Zeitung Der Spiegel existiert.
+
diff --git a/test/typ/compiler/show-text-01.typ b/test/typ/compiler/show-text-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-01.typ
@@ -0,0 +1,6 @@
+// Another classic example.
+#show "TeX": [T#h(-0.145em)#box(move(dy: 0.233em)[E])#h(-0.135em)X]
+#show regex("(Lua)?(La)?TeX"): name => box(text(font: "New Computer Modern")[#name])
+
+TeX, LaTeX, LuaTeX and LuaLaTeX!
+
diff --git a/test/typ/compiler/show-text-02.typ b/test/typ/compiler/show-text-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-02.typ
@@ -0,0 +1,5 @@
+// Test that replacements happen exactly once.
+#show "A": [BB]
+#show "B": [CC]
+AA (8)
+
diff --git a/test/typ/compiler/show-text-03.typ b/test/typ/compiler/show-text-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-03.typ
@@ -0,0 +1,5 @@
+// Test caseless match and word boundaries.
+#show regex("(?i)\bworld\b"): [🌍]
+
+Treeworld, the World of worlds, is a world.
+
diff --git a/test/typ/compiler/show-text-04.typ b/test/typ/compiler/show-text-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-04.typ
@@ -0,0 +1,5 @@
+// This is a fun one.
+#set par(justify: true)
+#show regex("\S"): letter => box(stroke: 1pt, inset: 2pt, upper(letter))
+#lorem(5)
+
diff --git a/test/typ/compiler/show-text-05.typ b/test/typ/compiler/show-text-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-05.typ
@@ -0,0 +1,4 @@
+// See also: https://github.com/mTvare6/hello-world.rs
+#show regex("(?i)rust"): it => [#it (🚀)]
+Rust is memory-safe and blazingly fast. Let's rewrite everything in rust.
+
diff --git a/test/typ/compiler/show-text-06.typ b/test/typ/compiler/show-text-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-06.typ
@@ -0,0 +1,4 @@
+// Test accessing the string itself.
+#show "hello": it => it.text.split("").map(upper).join("|")
+Oh, hello there!
+
diff --git a/test/typ/compiler/show-text-07.typ b/test/typ/compiler/show-text-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-07.typ
@@ -0,0 +1,9 @@
+// Replace worlds but only in lists.
+#show list: it => [
+  #show "World": [🌎]
+  #it
+]
+
+World
+- World
+
diff --git a/test/typ/compiler/show-text-08.typ b/test/typ/compiler/show-text-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/show-text-08.typ
@@ -0,0 +1,5 @@
+// Test absolute path in layout phase.
+
+#show "GRAPH": image("test/assets/files/graph.png")
+
+The GRAPH has nodes.
diff --git a/test/typ/compiler/spread-00.typ b/test/typ/compiler/spread-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-00.typ
@@ -0,0 +1,12 @@
+// Test standard argument overriding.
+#{
+  let f(style: "normal", weight: "regular") = {
+    "(style: " + style + ", weight: " + weight + ")"
+  }
+
+  let myf(..args) = f(weight: "bold", ..args)
+  test(myf(), "(style: normal, weight: bold)")
+  test(myf(weight: "black"), "(style: normal, weight: black)")
+  test(myf(style: "italic"), "(style: italic, weight: bold)")
+}
+
diff --git a/test/typ/compiler/spread-01.typ b/test/typ/compiler/spread-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-01.typ
@@ -0,0 +1,7 @@
+// Test multiple calls.
+#{
+  let f(b, c: "!") = b + c
+  let g(a, ..sink) = a + f(..sink)
+  test(g("a", "b", c: "c"), "abc")
+}
+
diff --git a/test/typ/compiler/spread-02.typ b/test/typ/compiler/spread-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-02.typ
@@ -0,0 +1,10 @@
+// Test doing things with arguments.
+#{
+  let save(..args) = {
+    test(type(args), "arguments")
+    test(repr(args), "(three: true, 1, 2)")
+  }
+
+  save(1, 2, three: true)
+}
+
diff --git a/test/typ/compiler/spread-03.typ b/test/typ/compiler/spread-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-03.typ
@@ -0,0 +1,14 @@
+// Test spreading array and dictionary.
+#{
+  let more = (3, -3, 6, 10)
+  test(calc.min(1, 2, ..more), -3)
+  test(calc.max(..more, 9), 10)
+  test(calc.max(..more, 11), 11)
+}
+
+#{
+  let more = (c: 3, d: 4)
+  let tostr(..args) = repr(args)
+  test(tostr(a: 1, ..more, b: 2), "(a: 1, c: 3, d: 4, b: 2)")
+}
+
diff --git a/test/typ/compiler/spread-04.typ b/test/typ/compiler/spread-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-04.typ
@@ -0,0 +1,6 @@
+// None is spreadable.
+#let f() = none
+#f(..none)
+#f(..if false {})
+#f(..for x in () [])
+
diff --git a/test/typ/compiler/spread-05.typ b/test/typ/compiler/spread-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-05.typ
@@ -0,0 +1,4 @@
+// unnamed spread
+#let f(.., a) = a
+#test(f(1, 2, 3), 3)
+
diff --git a/test/typ/compiler/spread-06.typ b/test/typ/compiler/spread-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-06.typ
@@ -0,0 +1,3 @@
+// Error: 13-19 cannot spread string
+#calc.min(.."nope")
+
diff --git a/test/typ/compiler/spread-07.typ b/test/typ/compiler/spread-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-07.typ
@@ -0,0 +1,3 @@
+// Error: 10-14 expected identifier, found boolean
+#let f(..true) = none
+
diff --git a/test/typ/compiler/spread-08.typ b/test/typ/compiler/spread-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-08.typ
@@ -0,0 +1,3 @@
+// Error: 13-16 only one argument sink is allowed
+#let f(..a, ..b) = none
+
diff --git a/test/typ/compiler/spread-09.typ b/test/typ/compiler/spread-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-09.typ
@@ -0,0 +1,16 @@
+// Test spreading into array and dictionary.
+#{
+  let l = (1, 2, 3)
+  let r = (5, 6, 7)
+  test((..l, 4, ..r), range(1, 8))
+  test((..none), ())
+}
+
+#{
+  let x = (a: 1)
+  let y = (b: 2)
+  let z = (a: 3)
+  test((:..x, ..y, ..z), (a: 3, b: 2))
+  test((..(a: 1), b: 2), (a: 1, b: 2))
+}
+
diff --git a/test/typ/compiler/spread-10.typ b/test/typ/compiler/spread-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-10.typ
@@ -0,0 +1,3 @@
+// Error: 11-17 cannot spread dictionary into array
+#(1, 2, ..(a: 1))
+
diff --git a/test/typ/compiler/spread-11.typ b/test/typ/compiler/spread-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-11.typ
@@ -0,0 +1,3 @@
+// Error: 5-11 cannot spread array into dictionary
+#(..(1, 2), a: 1)
+
diff --git a/test/typ/compiler/spread-12.typ b/test/typ/compiler/spread-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-12.typ
@@ -0,0 +1,8 @@
+// Spread at beginning.
+#{
+  let f(..a, b) = (a, b)
+  test(repr(f(1)), "((), 1)")
+  test(repr(f(1, 2, 3)), "((1, 2), 3)")
+  test(repr(f(1, 2, 3, 4, 5)), "((1, 2, 3, 4), 5)")
+}
+
diff --git a/test/typ/compiler/spread-13.typ b/test/typ/compiler/spread-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-13.typ
@@ -0,0 +1,7 @@
+// Spread in the middle.
+#{
+  let f(a, ..b, c) = (a, b, c)
+  test(repr(f(1, 2)), "(1, (), 2)")
+  test(repr(f(1, 2, 3, 4, 5)), "(1, (2, 3, 4), 5)")
+}
+
diff --git a/test/typ/compiler/spread-14.typ b/test/typ/compiler/spread-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/spread-14.typ
@@ -0,0 +1,6 @@
+#{
+  let f(..a, b, c, d) = none
+
+  // Error: 4-10 missing argument: d
+  f(1, 2)
+}
diff --git a/test/typ/compiler/string-00.typ b/test/typ/compiler/string-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-00.typ
@@ -0,0 +1,3 @@
+// Test the `len` method.
+#test("Hello World!".len(), 12)
+
diff --git a/test/typ/compiler/string-01.typ b/test/typ/compiler/string-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-01.typ
@@ -0,0 +1,6 @@
+// Test the `first` and `last` methods.
+#test("Hello".first(), "H")
+#test("Hello".last(), "o")
+#test("🏳️‍🌈A🏳️‍⚧️".first(), "🏳️‍🌈")
+#test("🏳️‍🌈A🏳️‍⚧️".last(), "🏳️‍⚧️")
+
diff --git a/test/typ/compiler/string-02.typ b/test/typ/compiler/string-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-02.typ
@@ -0,0 +1,3 @@
+// Error: 2-12 string is empty
+#"".first()
+
diff --git a/test/typ/compiler/string-03.typ b/test/typ/compiler/string-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-03.typ
@@ -0,0 +1,3 @@
+// Error: 2-11 string is empty
+#"".last()
+
diff --git a/test/typ/compiler/string-04.typ b/test/typ/compiler/string-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-04.typ
@@ -0,0 +1,7 @@
+// Test the `at` method.
+#test("Hello".at(1), "e")
+#test("Hello".at(4), "o")
+#test("Hello".at(-1), "o")
+#test("Hello".at(-2), "l")
+#test("Hey: 🏳️‍🌈 there!".at(5), "🏳️‍🌈")
+
diff --git a/test/typ/compiler/string-05.typ b/test/typ/compiler/string-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-05.typ
@@ -0,0 +1,3 @@
+// Error: 2-14 string index 2 is not a character boundary
+#"🏳️‍🌈".at(2)
+
diff --git a/test/typ/compiler/string-06.typ b/test/typ/compiler/string-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-06.typ
@@ -0,0 +1,3 @@
+// Error: 2-15 no default value was specified and string index out of bounds (index: 5, len: 5)
+#"Hello".at(5)
+
diff --git a/test/typ/compiler/string-07.typ b/test/typ/compiler/string-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-07.typ
@@ -0,0 +1,6 @@
+// Test the `slice` method.
+#test("abc".slice(1, 2), "b")
+#test("abc🏡def".slice(2, 7), "c🏡")
+#test("abc🏡def".slice(2, -2), "c🏡d")
+#test("abc🏡def".slice(-3, -1), "de")
+
diff --git a/test/typ/compiler/string-08.typ b/test/typ/compiler/string-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-08.typ
@@ -0,0 +1,3 @@
+// Error: 2-21 string index -1 is not a character boundary
+#"🏳️‍🌈".slice(0, -1)
+
diff --git a/test/typ/compiler/string-09.typ b/test/typ/compiler/string-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-09.typ
@@ -0,0 +1,6 @@
+// Test the `clusters` and `codepoints` methods.
+#test("abc".clusters(), ("a", "b", "c"))
+#test("abc".clusters(), ("a", "b", "c"))
+#test("🏳️‍🌈!".clusters(), ("🏳️‍🌈", "!"))
+#test("🏳️‍🌈!".codepoints(), ("🏳", "\u{fe0f}", "\u{200d}", "🌈", "!"))
+
diff --git a/test/typ/compiler/string-10.typ b/test/typ/compiler/string-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-10.typ
@@ -0,0 +1,10 @@
+// Test the `contains` method.
+#test("abc".contains("b"), true)
+#test("b" in "abc", true)
+#test("1234f".contains(regex("\d")), true)
+#test(regex("\d") in "1234f", true)
+#test("abc".contains("d"), false)
+#test("1234g" in "1234f", false)
+#test("abc".contains(regex("^[abc]$")), false)
+#test("abc".contains(regex("^[abc]+$")), true)
+
diff --git a/test/typ/compiler/string-11.typ b/test/typ/compiler/string-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-11.typ
@@ -0,0 +1,9 @@
+// Test the `starts-with` and `ends-with` methods.
+#test("Typst".starts-with("Ty"), true)
+#test("Typst".starts-with(regex("[Tt]ys")), false)
+#test("Typst".starts-with("st"), false)
+#test("Typst".ends-with("st"), true)
+#test("Typst".ends-with(regex("\d*")), true)
+#test("Typst".ends-with(regex("\d+")), false)
+#test("Typ12".ends-with(regex("\d+")), true)
+
diff --git a/test/typ/compiler/string-12.typ b/test/typ/compiler/string-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-12.typ
@@ -0,0 +1,7 @@
+// Test the `find` and `position` methods.
+#let date = regex("\d{2}:\d{2}")
+#test("Hello World".find("World"), "World")
+#test("Hello World".position("World"), 6)
+#test("It's 12:13 now".find(date), "12:13")
+#test("It's 12:13 now".position(date), 5)
+
diff --git a/test/typ/compiler/string-13.typ b/test/typ/compiler/string-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-13.typ
@@ -0,0 +1,28 @@
+// Test the `match` method.
+#test("Is there a".match("for this?"), none)
+#test(
+  "The time of my life.".match(regex("[mit]+e")),
+  (start: 4, end: 8, text: "time", captures: ()),
+)
+
+// Test the `matches` method.
+#test("Hello there".matches("\d"), ())
+#test("Day by Day.".matches("Day"), (
+  (start: 0, end: 3, text: "Day", captures: ()),
+  (start: 7, end: 10, text: "Day", captures: ()),
+))
+
+// Compute the sum of all timestamps in the text.
+#let timesum(text) = {
+  let time = 0
+  for match in text.matches(regex("(\d+):(\d+)")) {
+    let caps = match.captures
+    time += 60 * int(caps.at(0)) + int(caps.at(1))
+  }
+  str(int(time / 60)) + ":" + str(calc.rem(time, 60))
+}
+
+#test(timesum(""), "0:0")
+#test(timesum("2:70"), "3:10")
+#test(timesum("1:20, 2:10, 0:40"), "4:10")
+
diff --git a/test/typ/compiler/string-14.typ b/test/typ/compiler/string-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-14.typ
@@ -0,0 +1,15 @@
+// Test the `replace` method with `Str` replacements.
+#test("ABC".replace("", "-"), "-A-B-C-")
+#test("Ok".replace("Ok", "Nope", count: 0), "Ok")
+#test("to add?".replace("", "How ", count: 1), "How to add?")
+#test("AB C DEF GH J".replace(" ", ",", count: 2), "AB,C,DEF GH J")
+#test("Walcemo"
+  .replace("o", "k")
+  .replace("e", "o")
+  .replace("k", "e")
+  .replace("a", "e"),
+  "Welcome"
+)
+#test("123".replace(regex("\d$"), "_"), "12_")
+#test("123".replace(regex("\d{1,2}$"), "__"), "1__")
+
diff --git a/test/typ/compiler/string-15.typ b/test/typ/compiler/string-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-15.typ
@@ -0,0 +1,32 @@
+// Test the `replace` method with `Func` replacements.
+
+#test("abc".replace(regex("[a-z]"), m => {
+  str(m.start) + m.text + str(m.end)
+}), "0a11b22c3")
+#test("abcd, efgh".replace(regex("\w+"), m => {
+  upper(m.text)
+}), "ABCD, EFGH")
+#test("hello : world".replace(regex("^(.+)\s*(:)\s*(.+)$"), m => {
+  upper(m.captures.at(0)) + m.captures.at(1) + " " + upper(m.captures.at(2))
+}), "HELLO : WORLD")
+#test("hello world, lorem ipsum".replace(regex("(\w+) (\w+)"), m => {
+  m.captures.at(1) + " " + m.captures.at(0)
+}), "world hello, ipsum lorem")
+#test("hello world, lorem ipsum".replace(regex("(\w+) (\w+)"), count: 1, m => {
+  m.captures.at(1) + " " + m.captures.at(0)
+}), "world hello, lorem ipsum")
+#test("123 456".replace(regex("[a-z]+"), "a"), "123 456")
+
+#test("abc".replace("", m => "-"), "-a-b-c-")
+#test("abc".replace("", m => "-", count: 1), "-abc")
+#test("123".replace("abc", m => ""), "123")
+#test("123".replace("abc", m => "", count: 2), "123")
+#test("a123b123c".replace("123", m => {
+  str(m.start) + "-" + str(m.end)
+}), "a1-4b5-8c")
+#test("halla warld".replace("a", m => {
+  if m.start == 1 { "e" }
+  else if m.start == 4 or m.start == 7 { "o" }
+}), "hello world")
+#test("aaa".replace("a", m => str(m.captures.len())), "000")
+
diff --git a/test/typ/compiler/string-16.typ b/test/typ/compiler/string-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-16.typ
@@ -0,0 +1,3 @@
+// Error: 23-24 expected string, found integer
+#"123".replace("123", m => 1)
+
diff --git a/test/typ/compiler/string-17.typ b/test/typ/compiler/string-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-17.typ
@@ -0,0 +1,3 @@
+// Error: 23-32 expected string or function, found array
+#"123".replace("123", (1, 2, 3))
+
diff --git a/test/typ/compiler/string-18.typ b/test/typ/compiler/string-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-18.typ
@@ -0,0 +1,22 @@
+// Test the `trim` method.
+#let str = "Typst, LaTeX, Word, InDesign"
+#let array = ("Typst", "LaTeX", "Word", "InDesign")
+#test(str.split(",").map(s => s.trim()), array)
+#test("".trim(), "")
+#test(" abc ".trim(at: start), "abc ")
+#test(" abc ".trim(at: end, repeat: true), " abc")
+#test("  abc".trim(at: start, repeat: false), "abc")
+#test("aabcaa".trim("a", repeat: false), "abca")
+#test("aabca".trim("a", at: start), "bca")
+#test("aabcaa".trim("a", at: end, repeat: false), "aabca")
+#test("".trim(regex(".")), "")
+#test("123abc456".trim(regex("\d")), "abc")
+#test("123abc456".trim(regex("\d"), repeat: false), "23abc45")
+#test("123a4b5c678".trim(regex("\d"), repeat: true), "a4b5c")
+#test("123a4b5c678".trim(regex("\d"), repeat: false), "23a4b5c67")
+#test("123abc456".trim(regex("\d"), at: start), "abc456")
+#test("123abc456".trim(regex("\d"), at: end), "123abc")
+#test("123abc456".trim(regex("\d+"), at: end, repeat: false), "123abc")
+#test("123abc456".trim(regex("\d{1,2}$"), repeat: false), "123abc4")
+#test("hello world".trim(regex(".")), "")
+
diff --git a/test/typ/compiler/string-19.typ b/test/typ/compiler/string-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-19.typ
@@ -0,0 +1,3 @@
+// Error: 17-21 expected either `start` or `end`
+#"abc".trim(at: left)
+
diff --git a/test/typ/compiler/string-20.typ b/test/typ/compiler/string-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-20.typ
@@ -0,0 +1,6 @@
+// Test the `split` method.
+#test("abc".split(""), ("", "a", "b", "c", ""))
+#test("abc".split("b"), ("a", "c"))
+#test("a123c".split(regex("\d")), ("a", "", "", "c"))
+#test("a123c".split(regex("\d+")), ("a", "c"))
+
diff --git a/test/typ/compiler/string-21.typ b/test/typ/compiler/string-21.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/string-21.typ
@@ -0,0 +1,2 @@
+// Error: 2:1 expected quote
+#"hello\"
diff --git a/test/typ/compiler/while-00.typ b/test/typ/compiler/while-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/while-00.typ
@@ -0,0 +1,18 @@
+// Should output `2 4 6 8 10`.
+#let i = 0
+#while i < 10 [
+  #(i += 2)
+  #i
+]
+
+// Should output `Hi`.
+#let iter = true
+#while iter {
+  iter = false
+  "Hi."
+}
+
+#while false {
+  dont-care
+}
+
diff --git a/test/typ/compiler/while-01.typ b/test/typ/compiler/while-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/while-01.typ
@@ -0,0 +1,8 @@
+// Value of while loops.
+// Ref: false
+
+#test(while false {}, none)
+
+#let i = 0
+#test(type(while i < 1 [#(i += 1)]), "content")
+
diff --git a/test/typ/compiler/while-02.typ b/test/typ/compiler/while-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/while-02.typ
@@ -0,0 +1,4 @@
+// Condition must be boolean.
+// Error: 8-14 expected boolean, found content
+#while [nope] [nope]
+
diff --git a/test/typ/compiler/while-03.typ b/test/typ/compiler/while-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/while-03.typ
@@ -0,0 +1,3 @@
+// Error: 8-25 condition is always true
+#while 2 < "hello".len() {}
+
diff --git a/test/typ/compiler/while-04.typ b/test/typ/compiler/while-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/while-04.typ
@@ -0,0 +1,4 @@
+// Error: 2:2-2:24 loop seems to be infinite
+#let i = 1
+#while i > 0 { i += 1 }
+
diff --git a/test/typ/compiler/while-05.typ b/test/typ/compiler/while-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/while-05.typ
@@ -0,0 +1,15 @@
+// Error: 7 expected expression
+#while
+
+// Error: 8 expected expression
+#{while}
+
+// Error: 9 expected block
+#while x
+
+// Error: 7 expected expression
+#while
+x {}
+
+// Error: 9 expected block
+#while x something
diff --git a/test/typ/compute/calc-00.typ b/test/typ/compute/calc-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-00.typ
@@ -0,0 +1,11 @@
+// Test conversion to numbers.
+#test(int(false), 0)
+#test(int(true), 1)
+#test(int(10), 10)
+#test(int("150"), 150)
+#test(int(10 / 3), 3)
+#test(float(10), 10.0)
+#test(float(50% * 30%), 0.15)
+#test(float("31.4e-1"), 3.14)
+#test(type(float(10)), "float")
+
diff --git a/test/typ/compute/calc-01.typ b/test/typ/compute/calc-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-01.typ
@@ -0,0 +1,3 @@
+#test(calc.round(calc.e, digits: 2), 2.72)
+#test(calc.round(calc.pi, digits: 2), 3.14)
+
diff --git a/test/typ/compute/calc-02.typ b/test/typ/compute/calc-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-02.typ
@@ -0,0 +1,3 @@
+// Error: 6-10 expected boolean, integer, float, or string, found length
+#int(10pt)
+
diff --git a/test/typ/compute/calc-03.typ b/test/typ/compute/calc-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-03.typ
@@ -0,0 +1,3 @@
+// Error: 8-13 expected boolean, integer, float, ratio, or string, found function
+#float(float)
+
diff --git a/test/typ/compute/calc-04.typ b/test/typ/compute/calc-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-04.typ
@@ -0,0 +1,3 @@
+// Error: 6-12 invalid integer: nope
+#int("nope")
+
diff --git a/test/typ/compute/calc-05.typ b/test/typ/compute/calc-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-05.typ
@@ -0,0 +1,3 @@
+// Error: 8-15 invalid float: 1.2.3
+#float("1.2.3")
+
diff --git a/test/typ/compute/calc-06.typ b/test/typ/compute/calc-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-06.typ
@@ -0,0 +1,9 @@
+// Test the `abs` function.
+#test(calc.abs(-3), 3)
+#test(calc.abs(3), 3)
+#test(calc.abs(-0.0), 0.0)
+#test(calc.abs(0.0), -0.0)
+#test(calc.abs(-3.14), 3.14)
+#test(calc.abs(50%), 50%)
+#test(calc.abs(-25%), 25%)
+
diff --git a/test/typ/compute/calc-07.typ b/test/typ/compute/calc-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-07.typ
@@ -0,0 +1,3 @@
+// Error: 11-22 expected integer, float, length, angle, ratio, or fraction, found string
+#calc.abs("no number")
+
diff --git a/test/typ/compute/calc-08.typ b/test/typ/compute/calc-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-08.typ
@@ -0,0 +1,6 @@
+// Test the `even` and `odd` functions.
+#test(calc.even(2), true)
+#test(calc.odd(2), false)
+#test(calc.odd(-1), true)
+#test(calc.even(-11), false)
+
diff --git a/test/typ/compute/calc-09.typ b/test/typ/compute/calc-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-09.typ
@@ -0,0 +1,7 @@
+// Test the `rem` function.
+#test(calc.rem(1, 1), 0)
+#test(calc.rem(5, 3), 2)
+#test(calc.rem(5, -3), 2)
+#test(calc.rem(22.5, 10), 2.5)
+#test(calc.rem(9, 4.5), 0)
+
diff --git a/test/typ/compute/calc-10.typ b/test/typ/compute/calc-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-10.typ
@@ -0,0 +1,3 @@
+// Error: 14-15 divisor must not be zero
+#calc.rem(5, 0)
+
diff --git a/test/typ/compute/calc-11.typ b/test/typ/compute/calc-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-11.typ
@@ -0,0 +1,3 @@
+// Error: 16-19 divisor must not be zero
+#calc.rem(3.0, 0.0)
+
diff --git a/test/typ/compute/calc-12.typ b/test/typ/compute/calc-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-12.typ
@@ -0,0 +1,7 @@
+// Test the `quo` function.
+#test(calc.quo(1, 1), 1)
+#test(calc.quo(5, 3), 1)
+#test(calc.quo(5, -3), -1)
+#test(calc.quo(22.5, 10), 2)
+#test(calc.quo(9, 4.5), 2)
+
diff --git a/test/typ/compute/calc-13.typ b/test/typ/compute/calc-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-13.typ
@@ -0,0 +1,3 @@
+// Error: 14-15 divisor must not be zero
+#calc.quo(5, 0)
+
diff --git a/test/typ/compute/calc-14.typ b/test/typ/compute/calc-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-14.typ
@@ -0,0 +1,3 @@
+// Error: 16-19 divisor must not be zero
+#calc.quo(3.0, 0.0)
+
diff --git a/test/typ/compute/calc-15.typ b/test/typ/compute/calc-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-15.typ
@@ -0,0 +1,6 @@
+// Test the `min` and `max` functions.
+#test(calc.min(2, -4), -4)
+#test(calc.min(3.5, 1e2, -0.1, 3), -0.1)
+#test(calc.max(-3, 11), 11)
+#test(calc.min("hi"), "hi")
+
diff --git a/test/typ/compute/calc-16.typ b/test/typ/compute/calc-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-16.typ
@@ -0,0 +1,4 @@
+// Test the `calc` function.
+#test(calc.pow(10, 0), 1)
+#test(calc.pow(2, 4), 16)
+
diff --git a/test/typ/compute/calc-17.typ b/test/typ/compute/calc-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-17.typ
@@ -0,0 +1,3 @@
+// Error: 10-16 zero to the power of zero is undefined
+#calc.pow(0, 0)
+
diff --git a/test/typ/compute/calc-18.typ b/test/typ/compute/calc-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-18.typ
@@ -0,0 +1,3 @@
+// Error: 14-31 exponent is too large
+#calc.pow(2, 10000000000000000)
+
diff --git a/test/typ/compute/calc-19.typ b/test/typ/compute/calc-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-19.typ
@@ -0,0 +1,3 @@
+// Error: 10-25 the result is too large
+#calc.pow(2, 2147483647)
+
diff --git a/test/typ/compute/calc-20.typ b/test/typ/compute/calc-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-20.typ
@@ -0,0 +1,3 @@
+// Error: 14-36 exponent may not be infinite, subnormal, or NaN
+#calc.pow(2, calc.pow(2.0, 10000.0))
+
diff --git a/test/typ/compute/calc-21.typ b/test/typ/compute/calc-21.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-21.typ
@@ -0,0 +1,3 @@
+// Error: 10-19 the result is not a real number
+#calc.pow(-1, 0.5)
+
diff --git a/test/typ/compute/calc-22.typ b/test/typ/compute/calc-22.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-22.typ
@@ -0,0 +1,3 @@
+// Error: 12-14 cannot take square root of negative number
+#calc.sqrt(-1)
+
diff --git a/test/typ/compute/calc-23.typ b/test/typ/compute/calc-23.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-23.typ
@@ -0,0 +1,3 @@
+// Error: 11-13 value must be strictly positive
+#calc.log(-1)
+
diff --git a/test/typ/compute/calc-24.typ b/test/typ/compute/calc-24.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-24.typ
@@ -0,0 +1,3 @@
+// Error: 20-21 base may not be zero, NaN, infinite, or subnormal
+#calc.log(1, base: 0)
+
diff --git a/test/typ/compute/calc-25.typ b/test/typ/compute/calc-25.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-25.typ
@@ -0,0 +1,3 @@
+// Error: 10-24 the result is not a real number
+#calc.log(10, base: -1)
+
diff --git a/test/typ/compute/calc-26.typ b/test/typ/compute/calc-26.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-26.typ
@@ -0,0 +1,4 @@
+// Test the `fact` function.
+#test(calc.fact(0), 1)
+#test(calc.fact(5), 120)
+
diff --git a/test/typ/compute/calc-27.typ b/test/typ/compute/calc-27.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-27.typ
@@ -0,0 +1,3 @@
+// Error: 11-15 the result is too large
+#calc.fact(21)
+
diff --git a/test/typ/compute/calc-28.typ b/test/typ/compute/calc-28.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-28.typ
@@ -0,0 +1,6 @@
+// Test the `perm` function.
+#test(calc.perm(0, 0), 1)
+#test(calc.perm(5, 3), 60)
+#test(calc.perm(5, 5), 120)
+#test(calc.perm(5, 6), 0)
+
diff --git a/test/typ/compute/calc-29.typ b/test/typ/compute/calc-29.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-29.typ
@@ -0,0 +1,3 @@
+// Error: 11-19 the result is too large
+#calc.perm(21, 21)
+
diff --git a/test/typ/compute/calc-30.typ b/test/typ/compute/calc-30.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-30.typ
@@ -0,0 +1,7 @@
+// Test the `binom` function.
+#test(calc.binom(0, 0), 1)
+#test(calc.binom(5, 3), 10)
+#test(calc.binom(5, 5), 1)
+#test(calc.binom(5, 6), 0)
+#test(calc.binom(6, 2), 15)
+
diff --git a/test/typ/compute/calc-31.typ b/test/typ/compute/calc-31.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-31.typ
@@ -0,0 +1,9 @@
+// Test the `gcd` function.
+#test(calc.gcd(112, 77), 7)
+#test(calc.gcd(12, 96), 12)
+#test(calc.gcd(13, 9), 1)
+#test(calc.gcd(13, -9), 1)
+#test(calc.gcd(272557, 272557), 272557)
+#test(calc.gcd(0, 0), 0)
+#test(calc.gcd(7, 0), 7)
+
diff --git a/test/typ/compute/calc-32.typ b/test/typ/compute/calc-32.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-32.typ
@@ -0,0 +1,9 @@
+// Test the `lcm` function.
+#test(calc.lcm(112, 77), 1232)
+#test(calc.lcm(12, 96), 96)
+#test(calc.lcm(13, 9), 117)
+#test(calc.lcm(13, -9), 117)
+#test(calc.lcm(272557, 272557), 272557)
+#test(calc.lcm(0, 0), 0)
+#test(calc.lcm(8, 0), 0)
+
diff --git a/test/typ/compute/calc-33.typ b/test/typ/compute/calc-33.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-33.typ
@@ -0,0 +1,3 @@
+// Error: 10-41 the return value is too large
+#calc.lcm(15486487489457, 4874879896543)
+
diff --git a/test/typ/compute/calc-34.typ b/test/typ/compute/calc-34.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-34.typ
@@ -0,0 +1,3 @@
+// Error: 10-12 expected at least one value
+#calc.min()
+
diff --git a/test/typ/compute/calc-35.typ b/test/typ/compute/calc-35.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-35.typ
@@ -0,0 +1,3 @@
+// Error: 14-18 cannot compare integer and string
+#calc.min(1, "hi")
+
diff --git a/test/typ/compute/calc-36.typ b/test/typ/compute/calc-36.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-36.typ
@@ -0,0 +1,11 @@
+// Test the `range` function.
+#test(range(4), (0, 1, 2, 3))
+#test(range(1, 4), (1, 2, 3))
+#test(range(-4, 2), (-4, -3, -2, -1, 0, 1))
+#test(range(10, 5), ())
+#test(range(10, step: 3), (0, 3, 6, 9))
+#test(range(1, 4, step: 1), (1, 2, 3))
+#test(range(1, 8, step: 2), (1, 3, 5, 7))
+#test(range(5, 2, step: -1), (5, 4, 3))
+#test(range(10, 0, step: -3), (10, 7, 4, 1))
+
diff --git a/test/typ/compute/calc-37.typ b/test/typ/compute/calc-37.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-37.typ
@@ -0,0 +1,3 @@
+// Error: 7-9 missing argument: end
+#range()
+
diff --git a/test/typ/compute/calc-38.typ b/test/typ/compute/calc-38.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-38.typ
@@ -0,0 +1,3 @@
+// Error: 11-14 expected integer, found float
+#range(1, 2.0)
+
diff --git a/test/typ/compute/calc-39.typ b/test/typ/compute/calc-39.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-39.typ
@@ -0,0 +1,3 @@
+// Error: 17-22 expected integer, found string
+#range(4, step: "one")
+
diff --git a/test/typ/compute/calc-40.typ b/test/typ/compute/calc-40.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-40.typ
@@ -0,0 +1,2 @@
+// Error: 18-19 number must not be zero
+#range(10, step: 0)
diff --git a/test/typ/compute/construct-00.typ b/test/typ/compute/construct-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-00.typ
@@ -0,0 +1,12 @@
+// Compare both ways.
+#test(rgb(0%, 30%, 70%), rgb("004db3"))
+
+// Alpha channel.
+#test(rgb(255, 0, 0, 50%), rgb("ff000080"))
+
+// Test color modification methods.
+#test(rgb(25, 35, 45).lighten(10%), rgb(48, 57, 66))
+#test(rgb(40, 30, 20).darken(10%), rgb(36, 27, 18))
+#test(rgb("#133337").negate(), rgb(236, 204, 200))
+#test(white.lighten(100%), white)
+
diff --git a/test/typ/compute/construct-01.typ b/test/typ/compute/construct-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-01.typ
@@ -0,0 +1,4 @@
+// Test gray color conversion.
+// Ref: true
+#stack(dir: ltr, rect(fill: luma(0)), rect(fill: luma(80%)))
+
diff --git a/test/typ/compute/construct-02.typ b/test/typ/compute/construct-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-02.typ
@@ -0,0 +1,4 @@
+// Error for values that are out of range.
+// Error: 11-14 number must be between 0 and 255
+#test(rgb(-30, 15, 50))
+
diff --git a/test/typ/compute/construct-03.typ b/test/typ/compute/construct-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-03.typ
@@ -0,0 +1,3 @@
+// Error: 6-11 color string contains non-hexadecimal letters
+#rgb("lol")
+
diff --git a/test/typ/compute/construct-04.typ b/test/typ/compute/construct-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-04.typ
@@ -0,0 +1,3 @@
+// Error: 5-7 missing argument: red component
+#rgb()
+
diff --git a/test/typ/compute/construct-05.typ b/test/typ/compute/construct-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-05.typ
@@ -0,0 +1,3 @@
+// Error: 5-11 missing argument: blue component
+#rgb(0, 1)
+
diff --git a/test/typ/compute/construct-06.typ b/test/typ/compute/construct-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-06.typ
@@ -0,0 +1,3 @@
+// Error: 21-26 expected integer or ratio, found boolean
+#rgb(10%, 20%, 30%, false)
+
diff --git a/test/typ/compute/construct-07.typ b/test/typ/compute/construct-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-07.typ
@@ -0,0 +1,16 @@
+// Ref: true
+#let envelope = symbol(
+  "🖂",
+  ("stamped", "🖃"),
+  ("stamped.pen", "🖆"),
+  ("lightning", "🖄"),
+  ("fly", "🖅"),
+)
+
+#envelope
+#envelope.stamped
+#envelope.pen
+#envelope.stamped.pen
+#envelope.lightning
+#envelope.fly
+
diff --git a/test/typ/compute/construct-08.typ b/test/typ/compute/construct-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-08.typ
@@ -0,0 +1,3 @@
+// Error: 8-10 expected at least one variant
+#symbol()
+
diff --git a/test/typ/compute/construct-09.typ b/test/typ/compute/construct-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-09.typ
@@ -0,0 +1,5 @@
+// Test conversion to string.
+#test(str(123), "123")
+#test(str(50.14), "50.14")
+#test(str(10 / 3).len() > 10, true)
+
diff --git a/test/typ/compute/construct-10.typ b/test/typ/compute/construct-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-10.typ
@@ -0,0 +1,3 @@
+// Error: 6-8 expected integer, float, label, or string, found content
+#str([])
+
diff --git a/test/typ/compute/construct-11.typ b/test/typ/compute/construct-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-11.typ
@@ -0,0 +1,1 @@
+#assert(range(2, 5) == (2, 3, 4))
diff --git a/test/typ/compute/data-00.typ b/test/typ/compute/data-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-00.typ
@@ -0,0 +1,4 @@
+// Test reading plain text files
+#let data = read("test/assets/files/hello.txt")
+#test(data, "Hello, world!")
+
diff --git a/test/typ/compute/data-01.typ b/test/typ/compute/data-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-01.typ
@@ -0,0 +1,3 @@
+// Error: 18-32 file not found (searched at /missing.txt)
+#let data = read("test/assets/files/missing.txt")
+
diff --git a/test/typ/compute/data-02.typ b/test/typ/compute/data-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-02.typ
@@ -0,0 +1,3 @@
+// Error: 18-28 file is not valid utf-8
+#let data = read("test/assets/files/bad.txt")
+
diff --git a/test/typ/compute/data-03.typ b/test/typ/compute/data-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-03.typ
@@ -0,0 +1,7 @@
+// Test reading CSV data.
+// Ref: true
+#set page(width: auto)
+#let data = csv("test/assets/files/zoo.csv")
+#let cells = data.at(0).map(strong) + data.slice(1).flatten()
+#table(columns: data.at(0).len(), ..cells)
+
diff --git a/test/typ/compute/data-04.typ b/test/typ/compute/data-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-04.typ
@@ -0,0 +1,3 @@
+// Error: 6-16 file not found (searched at typ/compute/nope.csv)
+#csv("nope.csv")
+
diff --git a/test/typ/compute/data-05.typ b/test/typ/compute/data-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-05.typ
@@ -0,0 +1,3 @@
+// Error: 6-16 failed to parse csv file: found 3 instead of 2 fields in line 3
+#csv("test/assets/files/bad.csv")
+
diff --git a/test/typ/compute/data-06.typ b/test/typ/compute/data-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-06.typ
@@ -0,0 +1,6 @@
+// Test reading JSON data.
+#let data = json("test/assets/files/zoo.json")
+#test(data.len(), 3)
+#test(data.at(0).name, "Debby")
+#test(data.at(2).weight, 150)
+
diff --git a/test/typ/compute/data-07.typ b/test/typ/compute/data-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-07.typ
@@ -0,0 +1,3 @@
+// Error: 7-18 failed to parse json file: syntax error in line 3
+#json("test/assets/files/bad.json")
+
diff --git a/test/typ/compute/data-08.typ b/test/typ/compute/data-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-08.typ
@@ -0,0 +1,12 @@
+// Test reading TOML data.
+#let data = toml("test/assets/files/toml-types.toml")
+#test(data.string, "wonderful")
+#test(data.integer, 42)
+#test(data.float, 3.14)
+#test(data.boolean, true)
+#test(data.date_time, "2023-02-01T15:38:57Z")
+#test(data.array, (1, "string", 3.0, false))
+#test(data.inline_table, ("first": "amazing", "second": "greater") )
+#test(data.table.element, 5)
+#test(data.table.others, (false, "indeed", 7))
+
diff --git a/test/typ/compute/data-09.typ b/test/typ/compute/data-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-09.typ
@@ -0,0 +1,3 @@
+// Error: 7-18 failed to parse toml file: expected `.`, `=`, index 15-15
+#toml("test/assets/files/bad.toml")
+
diff --git a/test/typ/compute/data-10.typ b/test/typ/compute/data-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-10.typ
@@ -0,0 +1,11 @@
+// Test reading YAML data
+#let data = yaml("test/assets/files/yaml-types.yaml")
+#test(data.len(), 7)
+#test(data.null_key, (none, none))
+#test(data.string, "text")
+#test(data.integer, 5)
+#test(data.float, 1.12)
+#test(data.mapping, ("1": "one", "2": "two"))
+#test(data.seq, (1,2,3,4))
+#test(data.bool, false)
+#test(data.keys().contains("true"), false)
diff --git a/test/typ/compute/data-11.typ b/test/typ/compute/data-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-11.typ
@@ -0,0 +1,3 @@
+// Error: 7-18 failed to parse yaml file: while parsing a flow sequence, expected ',' or ']' at line 2 column 1
+#yaml("test/assets/files/bad.yaml")
+
diff --git a/test/typ/compute/data-12.typ b/test/typ/compute/data-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-12.typ
@@ -0,0 +1,24 @@
+// Test reading XML data.
+#let data = xml("test/assets/files/data.xml")
+#test(data, ((
+  tag: "data",
+  attrs: (:),
+  children: (
+    "\n  ",
+    (tag: "hello", attrs: (name: "hi"), children: ("1",)),
+    "\n  ",
+    (
+      tag: "data",
+      attrs: (:),
+      children: (
+        "\n    ",
+        (tag: "hello", attrs: (:), children: ("World",)),
+        "\n    ",
+        (tag: "hello", attrs: (:), children: ("World",)),
+        "\n  ",
+      ),
+    ),
+    "\n",
+  ),
+),))
+
diff --git a/test/typ/compute/data-13.typ b/test/typ/compute/data-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/data-13.typ
@@ -0,0 +1,2 @@
+// Error: 6-16 failed to parse xml file: found closing tag 'data' instead of 'hello' in line 3
+#xml("test/assets/files/bad.xml")
diff --git a/test/typ/compute/foundations-00.typ b/test/typ/compute/foundations-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-00.typ
@@ -0,0 +1,4 @@
+#test(type(1), "integer")
+#test(type(ltr), "direction")
+#test(type(10 / 3), "float")
+
diff --git a/test/typ/compute/foundations-01.typ b/test/typ/compute/foundations-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-01.typ
@@ -0,0 +1,3 @@
+#test(repr(ltr), "ltr")
+#test(repr((1, 2, false, )), "(1, 2, false)")
+
diff --git a/test/typ/compute/foundations-02.typ b/test/typ/compute/foundations-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-02.typ
@@ -0,0 +1,4 @@
+// Test panic.
+// Error: 7-9 panicked
+#panic()
+
diff --git a/test/typ/compute/foundations-03.typ b/test/typ/compute/foundations-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-03.typ
@@ -0,0 +1,4 @@
+// Test panic.
+// Error: 7-12 panicked with: 123
+#panic(123)
+
diff --git a/test/typ/compute/foundations-04.typ b/test/typ/compute/foundations-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-04.typ
@@ -0,0 +1,4 @@
+// Test panic.
+// Error: 7-24 panicked with: "this is wrong"
+#panic("this is wrong")
+
diff --git a/test/typ/compute/foundations-05.typ b/test/typ/compute/foundations-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-05.typ
@@ -0,0 +1,4 @@
+// Test failing assertions.
+// Error: 8-16 assertion failed
+#assert(1 == 2)
+
diff --git a/test/typ/compute/foundations-06.typ b/test/typ/compute/foundations-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-06.typ
@@ -0,0 +1,4 @@
+// Test failing assertions.
+// Error: 8-51 assertion failed: two is smaller than one
+#assert(2 < 1, message: "two is smaller than one")
+
diff --git a/test/typ/compute/foundations-07.typ b/test/typ/compute/foundations-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-07.typ
@@ -0,0 +1,4 @@
+// Test failing assertions.
+// Error: 9-15 expected boolean, found string
+#assert("true")
+
diff --git a/test/typ/compute/foundations-08.typ b/test/typ/compute/foundations-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-08.typ
@@ -0,0 +1,4 @@
+// Test failing assertions.
+// Error: 11-19 equality assertion failed: value 10 was not equal to 11
+#assert.eq(10, 11)
+
diff --git a/test/typ/compute/foundations-09.typ b/test/typ/compute/foundations-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-09.typ
@@ -0,0 +1,4 @@
+// Test failing assertions.
+// Error: 11-55 equality assertion failed: 10 and 12 are not equal
+#assert.eq(10, 12, message: "10 and 12 are not equal")
+
diff --git a/test/typ/compute/foundations-10.typ b/test/typ/compute/foundations-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-10.typ
@@ -0,0 +1,4 @@
+// Test failing assertions.
+// Error: 11-19 inequality assertion failed: value 11 was equal to 11
+#assert.ne(11, 11)
+
diff --git a/test/typ/compute/foundations-11.typ b/test/typ/compute/foundations-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-11.typ
@@ -0,0 +1,4 @@
+// Test failing assertions.
+// Error: 11-57 inequality assertion failed: must be different from 11
+#assert.ne(11, 11, message: "must be different from 11")
+
diff --git a/test/typ/compute/foundations-12.typ b/test/typ/compute/foundations-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-12.typ
@@ -0,0 +1,5 @@
+// Test successful assertions.
+#assert(5 > 3)
+#assert.eq(15, 15)
+#assert.ne(10, 12)
+
diff --git a/test/typ/compute/foundations-13.typ b/test/typ/compute/foundations-13.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-13.typ
@@ -0,0 +1,5 @@
+// Test the `type` function.
+#test(type(1), "integer")
+#test(type(ltr), "direction")
+#test(type(10 / 3), "float")
+
diff --git a/test/typ/compute/foundations-14.typ b/test/typ/compute/foundations-14.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-14.typ
@@ -0,0 +1,2 @@
+#eval("[_Hello" + " World!_]")
+
diff --git a/test/typ/compute/foundations-15.typ b/test/typ/compute/foundations-15.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-15.typ
@@ -0,0 +1,3 @@
+// Error: 7-12 expected identifier
+#eval("let")
+
diff --git a/test/typ/compute/foundations-16.typ b/test/typ/compute/foundations-16.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-16.typ
@@ -0,0 +1,8 @@
+#show raw: it => text(font: "PT Sans", eval("[" + it.text + "]"))
+
+Interacting
+```
+#set text(blue)
+Blue #move(dy: -0.15em)[🌊]
+```
+
diff --git a/test/typ/compute/foundations-17.typ b/test/typ/compute/foundations-17.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-17.typ
@@ -0,0 +1,3 @@
+// Error: 7-17 cannot continue outside of loop
+#eval("continue")
+
diff --git a/test/typ/compute/foundations-18.typ b/test/typ/compute/foundations-18.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-18.typ
@@ -0,0 +1,3 @@
+// Error: 7-32 cannot access file system from here
+#eval("include \"../coma.typ\"")
+
diff --git a/test/typ/compute/foundations-19.typ b/test/typ/compute/foundations-19.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-19.typ
@@ -0,0 +1,3 @@
+// Error: 7-30 cannot access file system from here
+#eval("image(\"/tiger.jpg\")")
+
diff --git a/test/typ/compute/foundations-20.typ b/test/typ/compute/foundations-20.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-20.typ
@@ -0,0 +1,7 @@
+// Error: 23-30 cannot access file system from here
+#show raw: it => eval(it.text)
+
+```
+image("test/assets/files/tiger.jpg")
+```
+
diff --git a/test/typ/compute/foundations-21.typ b/test/typ/compute/foundations-21.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-21.typ
@@ -0,0 +1,8 @@
+// Error: 23-42 cannot access file system from here
+#show raw: it => eval("[" + it.text + "]")
+
+```
+#show emph: _ => image("test/assets/files/giraffe.jpg")
+_No relative giraffe!_
+```
+
diff --git a/test/typ/compute/foundations-22.typ b/test/typ/compute/foundations-22.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/foundations-22.typ
@@ -0,0 +1,2 @@
+// Error: 7-12 expected semicolon or line break
+#eval("1 2")
diff --git a/test/typ/layout/align-00.typ b/test/typ/layout/align-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/align-00.typ
@@ -0,0 +1,12 @@
+#set page(height: 100pt)
+#stack(dir: ltr,
+  align(left, square(size: 15pt, fill: eastern)),
+  align(center, square(size: 20pt, fill: eastern)),
+  align(right, square(size: 15pt, fill: eastern)),
+)
+#align(center + horizon, rect(fill: eastern, height: 10pt))
+#align(bottom, stack(
+  align(center, rect(fill: green, height: 10pt)),
+  rect(fill: red, height: 10pt, width: 100%),
+))
+
diff --git a/test/typ/layout/align-01.typ b/test/typ/layout/align-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/align-01.typ
@@ -0,0 +1,7 @@
+// Test that multiple paragraphs in subflow also respect alignment.
+#align(center)[
+  Lorem Ipsum
+
+  Dolor
+]
+
diff --git a/test/typ/layout/align-02.typ b/test/typ/layout/align-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/align-02.typ
@@ -0,0 +1,11 @@
+// Test start and end alignment.
+#rotate(-30deg, origin: end + horizon)[Hello]
+
+#set text(lang: "de")
+#align(start)[Start]
+#align(end)[Ende]
+
+#set text(lang: "ar")
+#align(start)[يبدأ]
+#align(end)[نهاية]
+
diff --git a/test/typ/layout/align-03.typ b/test/typ/layout/align-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/align-03.typ
@@ -0,0 +1,5 @@
+// Ref: false
+#test(type(center), "alignment")
+#test(type(horizon), "alignment")
+#test(type(center + horizon), "2d alignment")
+
diff --git a/test/typ/layout/align-04.typ b/test/typ/layout/align-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/align-04.typ
@@ -0,0 +1,3 @@
+// Error: 8-22 cannot add two horizontal alignments
+#align(center + right, [A])
+
diff --git a/test/typ/layout/align-05.typ b/test/typ/layout/align-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/align-05.typ
@@ -0,0 +1,2 @@
+// Error: 8-20 cannot add two vertical alignments
+#align(top + bottom, [A])
diff --git a/test/typ/layout/block-sizing-00.typ b/test/typ/layout/block-sizing-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/block-sizing-00.typ
@@ -0,0 +1,14 @@
+#set page(height: 100pt)
+#set align(center)
+
+#lorem(10)
+#block(width: 80%, height: 60pt, fill: aqua)
+#lorem(6)
+#block(
+  breakable: false,
+  width: 100%,
+  inset: 4pt,
+  fill: aqua,
+  lorem(8) + colbreak(),
+)
+
diff --git a/test/typ/layout/block-sizing-01.typ b/test/typ/layout/block-sizing-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/block-sizing-01.typ
@@ -0,0 +1,6 @@
+// Layout inside a block with certain dimensions should provide those dimensions.
+
+#set page(height: 120pt)
+#block(width: 60pt, height: 80pt, layout(size => [
+  This block has a width of #size.width and height of #size.height
+]))
diff --git a/test/typ/layout/block-spacing-00.typ b/test/typ/layout/block-spacing-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/block-spacing-00.typ
@@ -0,0 +1,6 @@
+#set block(spacing: 10pt)
+Hello
+
+There
+
+#block(spacing: 20pt)[Further down]
diff --git a/test/typ/layout/clip-00.typ b/test/typ/layout/clip-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/clip-00.typ
@@ -0,0 +1,9 @@
+// Test box clipping with a rectangle
+Hello #box(width: 1em, height: 1em, clip: false)[#rect(width: 3em, height: 3em, fill: red)]
+world 1
+
+Space
+
+Hello #box(width: 1em, height: 1em, clip: true)[#rect(width: 3em, height: 3em, fill: red)] 
+world 2
+
diff --git a/test/typ/layout/clip-01.typ b/test/typ/layout/clip-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/clip-01.typ
@@ -0,0 +1,12 @@
+// Test cliping text
+#block(width: 5em, height: 2em, clip: false, stroke: 1pt + black)[
+  But, soft! what light through 
+]
+
+#v(2em)
+
+#block(width: 5em, height: 2em, clip: true, stroke: 1pt + black)[
+  But, soft! what light through yonder window breaks? It is the east, and Juliet
+  is the sun.
+]
+
diff --git a/test/typ/layout/clip-02.typ b/test/typ/layout/clip-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/clip-02.typ
@@ -0,0 +1,5 @@
+// Test cliping svg glyphs
+Emoji: #box(height: 0.5em, stroke: 1pt + black)[🐪, 🌋, 🏞]
+
+Emoji: #box(height: 0.5em, clip: true, stroke: 1pt + black)[🐪, 🌋, 🏞]
+
diff --git a/test/typ/layout/clip-03.typ b/test/typ/layout/clip-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/clip-03.typ
@@ -0,0 +1,10 @@
+// Test block clipping over multiple pages.
+
+#set page(height: 60pt)
+
+First!
+
+#block(height: 4em, clip: true, stroke: 1pt + black)[
+  But, soft! what light through yonder window breaks? It is the east, and Juliet
+  is the sun.
+]
diff --git a/test/typ/layout/columns-00.typ b/test/typ/layout/columns-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-00.typ
@@ -0,0 +1,11 @@
+// Test normal operation and RTL directions.
+#set page(height: 3.25cm, width: 7.05cm, columns: 2)
+#set text(lang: "ar", font: ("Noto Sans Arabic", "Linux Libertine"))
+#set columns(gutter: 30pt)
+
+#box(fill: green, height: 8pt, width: 6pt) وتحفيز
+العديد من التفاعلات الكيميائية. (DNA) من أهم الأحماض النووية التي تُشكِّل
+إلى جانب كل من البروتينات والليبيدات والسكريات المتعددة
+#box(fill: eastern, height: 8pt, width: 6pt)
+الجزيئات الضخمة الأربعة الضرورية للحياة.
+
diff --git a/test/typ/layout/columns-01.typ b/test/typ/layout/columns-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-01.typ
@@ -0,0 +1,10 @@
+// Test the `columns` function.
+#set page(width: auto)
+
+#rect(width: 180pt, height: 100pt, inset: 8pt, columns(2, [
+    A special plight has befallen our document.
+    Columns in text boxes reigned down unto the soil
+    to waste a year's crop of rich layouts.
+    The columns at least were graciously balanced.
+]))
+
diff --git a/test/typ/layout/columns-02.typ b/test/typ/layout/columns-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-02.typ
@@ -0,0 +1,12 @@
+// Test columns for a sized page.
+#set page(height: 5cm, width: 7.05cm, columns: 2)
+
+Lorem ipsum dolor sit amet is a common blind text
+and I again am in need of filling up this page
+#align(bottom, rect(fill: eastern, width: 100%, height: 12pt))
+#colbreak()
+
+so I'm returning to this trusty tool of tangible terror.
+Sure, it is not the most creative way of filling up
+a page for a test but it does get the job done.
+
diff --git a/test/typ/layout/columns-03.typ b/test/typ/layout/columns-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-03.typ
@@ -0,0 +1,10 @@
+// Test the expansion behavior.
+#set page(height: 2.5cm, width: 7.05cm)
+
+#rect(inset: 6pt, columns(2, [
+    ABC \
+    BCD
+    #colbreak()
+    DEF
+]))
+
diff --git a/test/typ/layout/columns-04.typ b/test/typ/layout/columns-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-04.typ
@@ -0,0 +1,8 @@
+// Test setting a column gutter and more than two columns.
+#set page(height: 3.25cm, width: 7.05cm, columns: 3)
+#set columns(gutter: 30pt)
+
+#rect(width: 100%, height: 2.5cm, fill: green) #parbreak()
+#rect(width: 100%, height: 2cm, fill: eastern) #parbreak()
+#circle(fill: eastern)
+
diff --git a/test/typ/layout/columns-05.typ b/test/typ/layout/columns-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-05.typ
@@ -0,0 +1,12 @@
+// Test the `colbreak` and `pagebreak` functions.
+#set page(height: 1cm, width: 7.05cm, columns: 2)
+
+A
+#colbreak()
+#colbreak()
+B
+#pagebreak()
+C
+#colbreak()
+D
+
diff --git a/test/typ/layout/columns-06.typ b/test/typ/layout/columns-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-06.typ
@@ -0,0 +1,5 @@
+// Test an empty second column.
+#set page(width: 7.05cm, columns: 2)
+
+#rect(width: 100%, inset: 3pt)[So there isn't anything in the second column?]
+
diff --git a/test/typ/layout/columns-07.typ b/test/typ/layout/columns-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-07.typ
@@ -0,0 +1,5 @@
+// Test columns when one of them is empty.
+#set page(width: auto, columns: 3)
+
+Arbitrary horizontal growth.
+
diff --git a/test/typ/layout/columns-08.typ b/test/typ/layout/columns-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-08.typ
@@ -0,0 +1,11 @@
+// Test columns in an infinitely high frame.
+#set page(width: 7.05cm, columns: 2)
+
+There can be as much content as you want in the left column
+and the document will grow with it.
+
+#rect(fill: green, width: 100%, height: 30pt)
+
+Only an explicit #colbreak() `#colbreak()` can put content in the
+second column.
+
diff --git a/test/typ/layout/columns-09.typ b/test/typ/layout/columns-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-09.typ
@@ -0,0 +1,5 @@
+// Test a page with a single column.
+#set page(height: auto, width: 7.05cm, columns: 1)
+
+This is a normal page. Very normal.
+
diff --git a/test/typ/layout/columns-10.typ b/test/typ/layout/columns-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/columns-10.typ
@@ -0,0 +1,3 @@
+// Test a page with zero columns.
+// Error: 49-50 number must be positive
+#set page(height: auto, width: 7.05cm, columns: 0)
diff --git a/test/typ/layout/container-00.typ b/test/typ/layout/container-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/container-00.typ
@@ -0,0 +1,8 @@
+// Test box in paragraph.
+A #box[B \ C] D.
+
+// Test box with height.
+Spaced \
+#box(height: 0.5cm) \
+Apart
+
diff --git a/test/typ/layout/container-01.typ b/test/typ/layout/container-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/container-01.typ
@@ -0,0 +1,8 @@
+// Test block sizing.
+#set page(height: 120pt)
+#set block(spacing: 0pt)
+#block(width: 90pt, height: 80pt, fill: red)[
+  #block(width: 60%, height: 60%, fill: green)
+  #block(width: 50%, height: 60%, fill: blue)
+]
+
diff --git a/test/typ/layout/container-02.typ b/test/typ/layout/container-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/container-02.typ
@@ -0,0 +1,14 @@
+// Test box sizing with layoutable child.
+#box(
+  width: 50pt,
+  height: 50pt,
+  fill: yellow,
+  path(
+    fill: purple,
+    (0pt, 0pt),
+    (30pt, 30pt),
+    (0pt, 30pt),
+    (30pt, 0pt),
+  ),
+)
+
diff --git a/test/typ/layout/container-03.typ b/test/typ/layout/container-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/container-03.typ
@@ -0,0 +1,3 @@
+// Test fr box.
+Hello #box(width: 1fr, rect(height: 0.7em, width: 100%)) World
+
diff --git a/test/typ/layout/container-04.typ b/test/typ/layout/container-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/container-04.typ
@@ -0,0 +1,10 @@
+// Test block over multiple pages.
+
+#set page(height: 60pt)
+
+First!
+
+#block[
+  But, soft! what light through yonder window breaks? It is the east, and Juliet
+  is the sun.
+]
diff --git a/test/typ/layout/container-fill-00.typ b/test/typ/layout/container-fill-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/container-fill-00.typ
@@ -0,0 +1,7 @@
+#set page(height: 100pt)
+#let words = lorem(18).split()
+#block(inset: 8pt, width: 100%, fill: aqua, stroke: aqua.darken(30%))[
+  #words.slice(0, 13).join(" ")
+  #box(fill: teal, outset: 2pt)[tempor]
+  #words.slice(13).join(" ")
+]
diff --git a/test/typ/layout/enum-00.typ b/test/typ/layout/enum-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-00.typ
@@ -0,0 +1,2 @@
+#enum[Embrace][Extend][Extinguish]
+
diff --git a/test/typ/layout/enum-01.typ b/test/typ/layout/enum-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-01.typ
@@ -0,0 +1,6 @@
+0. Before first!
+1. First.
+   2. Indented
+
++ Second
+
diff --git a/test/typ/layout/enum-02.typ b/test/typ/layout/enum-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-02.typ
@@ -0,0 +1,5 @@
+// Test automatic numbering in summed content.
+#for i in range(5) {
+   [+ #numbering("I", 1 + i)]
+}
+
diff --git a/test/typ/layout/enum-03.typ b/test/typ/layout/enum-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-03.typ
@@ -0,0 +1,5 @@
+// Mix of different lists
+- Bullet List
++ Numbered List
+/ Term: List
+
diff --git a/test/typ/layout/enum-04.typ b/test/typ/layout/enum-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-04.typ
@@ -0,0 +1,5 @@
+// In the line.
+1.2 \
+This is 0. \
+See 0.3. \
+
diff --git a/test/typ/layout/enum-05.typ b/test/typ/layout/enum-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-05.typ
@@ -0,0 +1,6 @@
+// Edge cases.
++
+Empty \
++Nope \
+a + 0.
+
diff --git a/test/typ/layout/enum-06.typ b/test/typ/layout/enum-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-06.typ
@@ -0,0 +1,10 @@
+// Test item number overriding.
+1. first
++ second
+5. fifth
+
+#enum(
+   enum.item(1)[First],
+   [Second],
+   enum.item(5)[Fifth]
+)
diff --git a/test/typ/layout/enum-align-00.typ b/test/typ/layout/enum-align-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-align-00.typ
@@ -0,0 +1,7 @@
+// Alignment shouldn't affect number
+#set align(horizon)
+
++ ABCDEF\ GHIJKL\ MNOPQR
+   + INNER\ INNER\ INNER
++ BACK\ HERE
+
diff --git a/test/typ/layout/enum-align-01.typ b/test/typ/layout/enum-align-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-align-01.typ
@@ -0,0 +1,10 @@
+// Enum number alignment should be 'end' by default
+1. a
+10. b
+100. c
+
+#set enum(number-align: start)
+1.  a
+8.  b
+16. c
+
diff --git a/test/typ/layout/enum-align-02.typ b/test/typ/layout/enum-align-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-align-02.typ
@@ -0,0 +1,11 @@
+// Number align option should not be affected by the context
+#set align(center)
+#set enum(number-align: start)
+
+4.  c
+8.  d
+16. e\ f
+   2.  f\ g
+   32. g
+   64. h
+
diff --git a/test/typ/layout/enum-align-03.typ b/test/typ/layout/enum-align-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-align-03.typ
@@ -0,0 +1,7 @@
+// Test valid number align values (horizontal)
+#set enum(number-align: start)
+#set enum(number-align: end)
+#set enum(number-align: left)
+#set enum(number-align: right)
+// Error: 25-28 alignment must be horizontal
+#set enum(number-align: top)
diff --git a/test/typ/layout/enum-numbering-00.typ b/test/typ/layout/enum-numbering-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-numbering-00.typ
@@ -0,0 +1,8 @@
+// Test numbering pattern.
+#set enum(numbering: "(1.a.*)")
++ First
++ Second
+  2. Nested
+     + Deep
++ Normal
+
diff --git a/test/typ/layout/enum-numbering-01.typ b/test/typ/layout/enum-numbering-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-numbering-01.typ
@@ -0,0 +1,5 @@
+// Test full numbering.
+#set enum(numbering: "1.a.", full: true)
++ First
+  + Nested
+
diff --git a/test/typ/layout/enum-numbering-02.typ b/test/typ/layout/enum-numbering-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-numbering-02.typ
@@ -0,0 +1,12 @@
+// Test numbering with closure.
+#enum(
+  start: 3,
+  spacing: 0.65em - 3pt,
+  tight: false,
+  numbering: n => text(
+    fill: (red, green, blue).at(calc.rem(n, 3)),
+    numbering("A", n),
+  ),
+  [Red], [Green], [Blue], [Red],
+)
+
diff --git a/test/typ/layout/enum-numbering-03.typ b/test/typ/layout/enum-numbering-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-numbering-03.typ
@@ -0,0 +1,6 @@
+// Test numbering with closure and nested lists.
+#set enum(numbering: n => super[#n])
++ A
+  + B
++ C
+
diff --git a/test/typ/layout/enum-numbering-04.typ b/test/typ/layout/enum-numbering-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-numbering-04.typ
@@ -0,0 +1,10 @@
+// Test numbering with closure and nested lists.
+#set text(font: "New Computer Modern")
+#set enum(numbering: (..args) => math.mat(args.pos()), full: true)
++ A
+  + B
+  + C
+    + D
++ E
++ F
+
diff --git a/test/typ/layout/enum-numbering-05.typ b/test/typ/layout/enum-numbering-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-numbering-05.typ
@@ -0,0 +1,3 @@
+// Error: 22-24 invalid numbering pattern
+#set enum(numbering: "")
+
diff --git a/test/typ/layout/enum-numbering-06.typ b/test/typ/layout/enum-numbering-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/enum-numbering-06.typ
@@ -0,0 +1,2 @@
+// Error: 22-28 invalid numbering pattern
+#set enum(numbering: "(())")
diff --git a/test/typ/layout/flow-orphan-00.typ b/test/typ/layout/flow-orphan-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/flow-orphan-00.typ
@@ -0,0 +1,6 @@
+#set page(height: 100pt)
+#lorem(12)
+
+= Introduction
+This is the start and it goes on.
+
diff --git a/test/typ/layout/flow-orphan-01.typ b/test/typ/layout/flow-orphan-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/flow-orphan-01.typ
@@ -0,0 +1,20 @@
+#set page("a8", height: 140pt)
+#set text(weight: 700)
+
+// Fits fully onto the first page.
+#set text(blue)
+#lorem(27)
+
+// The first line would fit, but is moved to the second page.
+#lorem(20)
+
+// The second-to-last line is moved to the third page so that the last is isn't
+// as lonely.
+#set text(maroon)
+#lorem(11)
+
+#lorem(13)
+
+// All three lines go to the next page.
+#set text(olive)
+#lorem(10)
diff --git a/test/typ/layout/grid-1-00.typ b/test/typ/layout/grid-1-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-1-00.typ
@@ -0,0 +1,18 @@
+#let cell(width, color) = rect(width: width, height: 2cm, fill: color)
+#set page(width: 100pt, height: 140pt)
+#grid(
+  columns: (auto, 1fr, 3fr, 0.25cm, 3%, 2mm + 10%),
+  cell(0.5cm, rgb("2a631a")),
+  cell(100%,  red),
+  cell(100%,  green),
+  cell(100%,  rgb("ff0000")),
+  cell(100%,  rgb("00ff00")),
+  cell(80%,   rgb("00faf0")),
+  cell(1cm,   rgb("00ff00")),
+  cell(0.5cm, rgb("2a631a")),
+  cell(100%,  red),
+  cell(100%,  green),
+  cell(100%,  rgb("ff0000")),
+  cell(100%,  rgb("00ff00")),
+)
+
diff --git a/test/typ/layout/grid-1-01.typ b/test/typ/layout/grid-1-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-1-01.typ
@@ -0,0 +1,10 @@
+#set rect(inset: 0pt)
+#grid(
+  columns: (auto, auto, 40%),
+  column-gutter: 1fr,
+  row-gutter: 1fr,
+  rect(fill: eastern)[dddaa aaa aaa],
+  rect(fill: green)[ccc],
+  rect(fill: rgb("dddddd"))[aaa],
+)
+
diff --git a/test/typ/layout/grid-1-02.typ b/test/typ/layout/grid-1-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-1-02.typ
@@ -0,0 +1,8 @@
+#set page(height: 3cm, margin: 0pt)
+#grid(
+  columns: (1fr,),
+  rows: (1fr, auto, 2fr),
+  [],
+  align(center)[A bit more to the top],
+  [],
+)
diff --git a/test/typ/layout/grid-2-00.typ b/test/typ/layout/grid-2-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-2-00.typ
@@ -0,0 +1,26 @@
+#set page(width: 11cm, height: 2.5cm)
+#grid(
+  columns: 5,
+  column-gutter: (2fr, 1fr, 1fr),
+  row-gutter: 6pt,
+  [*Quarter*],
+  [Expenditure],
+  [External Revenue],
+  [Financial ROI],
+  [_total_],
+  [*Q1*],
+  [173,472.57 \$],
+  [472,860.91 \$],
+  [51,286.84 \$],
+  [_350,675.18 \$_],
+  [*Q2*],
+  [93,382.12 \$],
+  [439,382.85 \$],
+  [-1,134.30 \$],
+  [_344,866.43 \$_],
+  [*Q3*],
+  [96,421.49 \$],
+  [238,583.54 \$],
+  [3,497.12 \$],
+  [_145,659.17 \$_],
+)
diff --git a/test/typ/layout/grid-3-00.typ b/test/typ/layout/grid-3-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-3-00.typ
@@ -0,0 +1,14 @@
+#set page(width: 5cm, height: 3cm)
+#grid(
+  columns: 2,
+  row-gutter: 8pt,
+  [Lorem ipsum dolor sit amet.
+
+  Aenean commodo ligula eget dolor. Aenean massa. Penatibus et magnis.],
+  [Text that is rather short],
+  [Fireflies],
+  [Critical],
+  [Decorum],
+  [Rampage],
+)
+
diff --git a/test/typ/layout/grid-3-01.typ b/test/typ/layout/grid-3-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-3-01.typ
@@ -0,0 +1,14 @@
+// Test a column that starts overflowing right after another row/column did
+// that.
+#set page(width: 5cm, height: 2cm)
+#grid(
+  columns: 4 * (1fr,),
+  row-gutter: 10pt,
+  column-gutter: (0pt, 10%),
+  align(top, image("test/assets/files/rhino.png")),
+  align(top, rect(inset: 0pt, fill: eastern, align(right)[LoL])),
+  [rofl],
+  [\ A] * 3,
+  [Ha!\ ] * 3,
+)
+
diff --git a/test/typ/layout/grid-3-02.typ b/test/typ/layout/grid-3-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-3-02.typ
@@ -0,0 +1,15 @@
+// Test two columns in the same row overflowing by a different amount.
+#set page(width: 5cm, height: 2cm)
+#grid(
+  columns: 3 * (1fr,),
+  row-gutter: 8pt,
+  column-gutter: (0pt, 10%),
+  [A], [B], [C],
+  [Ha!\ ] * 6,
+  [rofl],
+  [\ A] * 3,
+  [hello],
+  [darkness],
+  [my old]
+)
+
diff --git a/test/typ/layout/grid-3-03.typ b/test/typ/layout/grid-3-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-3-03.typ
@@ -0,0 +1,12 @@
+// Test grid within a grid, overflowing.
+#set page(width: 5cm, height: 2.25cm)
+#grid(
+  columns: 4 * (1fr,),
+  row-gutter: 10pt,
+  column-gutter: (0pt, 10%),
+  [A], [B], [C], [D],
+  grid(columns: 2, [A], [B], [C\ ]*3, [D]),
+  align(top, rect(inset: 0pt, fill: eastern, align(right)[LoL])),
+  [rofl],
+  [E\ ]*4,
+)
diff --git a/test/typ/layout/grid-4-00.typ b/test/typ/layout/grid-4-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-4-00.typ
@@ -0,0 +1,9 @@
+// Test that auto and relative columns use the correct base.
+#grid(
+  columns: (auto, 60%),
+  rows: (auto, auto),
+  rect(width: 50%, height: 0.5cm, fill: green),
+  rect(width: 100%, height: 0.5cm, fill: eastern),
+  rect(width: 50%, height: 0.5cm, fill: red),
+)
+
diff --git a/test/typ/layout/grid-4-01.typ b/test/typ/layout/grid-4-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-4-01.typ
@@ -0,0 +1,10 @@
+// Test that fr columns use the correct base.
+#grid(
+  columns: (1fr,) * 4,
+  rows: (1cm,),
+  rect(width: 50%, fill: green),
+  rect(width: 50%, fill: red),
+  rect(width: 50%, fill: green),
+  rect(width: 50%, fill: red),
+)
+
diff --git a/test/typ/layout/grid-4-02.typ b/test/typ/layout/grid-4-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-4-02.typ
@@ -0,0 +1,9 @@
+// Test that all three kinds of rows use the correct bases.
+#set page(height: 4cm, margin: 0cm)
+#grid(
+  rows: (1cm, 1fr, 1fr, auto),
+  rect(height: 50%, width: 100%, fill: green),
+  rect(height: 50%, width: 100%, fill: red),
+  rect(height: 50%, width: 100%, fill: green),
+  rect(height: 25%, width: 100%, fill: red),
+)
diff --git a/test/typ/layout/grid-5-00.typ b/test/typ/layout/grid-5-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-5-00.typ
@@ -0,0 +1,10 @@
+// Test that trailing linebreak doesn't overflow the region.
+#set page(height: 2cm)
+#grid[
+  Hello \
+  Hello \
+  Hello \
+
+  World
+]
+
diff --git a/test/typ/layout/grid-5-01.typ b/test/typ/layout/grid-5-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-5-01.typ
@@ -0,0 +1,17 @@
+// Test that broken cell expands vertically.
+#set page(height: 2.25cm)
+#grid(
+  columns: 2,
+  gutter: 10pt,
+  align(bottom)[A],
+  [
+    Top
+    #align(bottom)[
+      Bottom \
+      Bottom \
+      #v(0pt)
+      Top
+    ]
+  ],
+  align(top)[B],
+)
diff --git a/test/typ/layout/grid-auto-shrink-00.typ b/test/typ/layout/grid-auto-shrink-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-auto-shrink-00.typ
@@ -0,0 +1,9 @@
+#set page(width: 210mm - 2 * 2.5cm + 2 * 10pt)
+#set text(11pt)
+#table(
+  columns: 4,
+  [Hello!],
+  [Hello there, my friend!],
+  [Hello there, my friends! Hi!],
+  [Hello there, my friends! Hi! What is going on right now?],
+)
diff --git a/test/typ/layout/grid-rtl-00.typ b/test/typ/layout/grid-rtl-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-rtl-00.typ
@@ -0,0 +1,3 @@
+#set text(dir: rtl)
+- מימין לשמאל
+
diff --git a/test/typ/layout/grid-rtl-01.typ b/test/typ/layout/grid-rtl-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/grid-rtl-01.typ
@@ -0,0 +1,2 @@
+#set text(dir: rtl)
+#table(columns: 2)[A][B][C][D]
diff --git a/test/typ/layout/hide-00.typ b/test/typ/layout/hide-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/hide-00.typ
@@ -0,0 +1,2 @@
+AB #h(1fr) CD \
+#hide[A]B #h(1fr) C#hide[D]
diff --git a/test/typ/layout/list-00.typ b/test/typ/layout/list-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-00.typ
@@ -0,0 +1,3 @@
+_Shopping list_
+#list[Apples][Potatoes][Juice]
+
diff --git a/test/typ/layout/list-01.typ b/test/typ/layout/list-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-01.typ
@@ -0,0 +1,13 @@
+- First level.
+
+  - Second level.
+    There are multiple paragraphs.
+
+    - Third level.
+
+    Still the same bullet point.
+
+  - Still level 2.
+
+- At the top.
+
diff --git a/test/typ/layout/list-02.typ b/test/typ/layout/list-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-02.typ
@@ -0,0 +1,5 @@
+- Level 1
+  - Level #[
+2 through content block
+]
+
diff --git a/test/typ/layout/list-03.typ b/test/typ/layout/list-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-03.typ
@@ -0,0 +1,3 @@
+  - Top-level indent
+- is fine.
+
diff --git a/test/typ/layout/list-04.typ b/test/typ/layout/list-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-04.typ
@@ -0,0 +1,5 @@
+ - A
+     - B
+   - C
+- D
+
diff --git a/test/typ/layout/list-05.typ b/test/typ/layout/list-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-05.typ
@@ -0,0 +1,4 @@
+// This works because tabs are used consistently.
+	- A with 1 tab
+		- B with 2 tabs
+
diff --git a/test/typ/layout/list-06.typ b/test/typ/layout/list-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-06.typ
@@ -0,0 +1,4 @@
+// This doesn't work because of mixed tabs and spaces.
+  - A with 2 spaces
+		- B with 2 tabs
+
diff --git a/test/typ/layout/list-07.typ b/test/typ/layout/list-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-07.typ
@@ -0,0 +1,5 @@
+// Edge cases.
+-
+Not in list
+-Nope
+
diff --git a/test/typ/layout/list-08.typ b/test/typ/layout/list-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-08.typ
@@ -0,0 +1,4 @@
+// Alignment shouldn't affect marker
+#set align(horizon)
+
+- ABCDEF\ GHIJKL\ MNOPQR
diff --git a/test/typ/layout/list-attach-00.typ b/test/typ/layout/list-attach-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-attach-00.typ
@@ -0,0 +1,7 @@
+// Test basic attached list.
+Attached to:
+- the bottom
+- of the paragraph
+
+Next paragraph.
+
diff --git a/test/typ/layout/list-attach-01.typ b/test/typ/layout/list-attach-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-attach-01.typ
@@ -0,0 +1,7 @@
+// Test that attached list isn't affected by block spacing.
+#show list: set block(above: 100pt)
+Hello
+- A
+World
+- B
+
diff --git a/test/typ/layout/list-attach-02.typ b/test/typ/layout/list-attach-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-attach-02.typ
@@ -0,0 +1,9 @@
+// Test non-attached list followed by attached list,
+// separated by only word.
+Hello
+
+- A
+
+World
+- B
+
diff --git a/test/typ/layout/list-attach-03.typ b/test/typ/layout/list-attach-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-attach-03.typ
@@ -0,0 +1,11 @@
+// Test non-attached tight list.
+#set block(spacing: 15pt)
+Hello
+- A
+World
+
+- B
+- C
+
+More.
+
diff --git a/test/typ/layout/list-attach-04.typ b/test/typ/layout/list-attach-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-attach-04.typ
@@ -0,0 +1,8 @@
+// Test that wide lists cannot be ...
+#set block(spacing: 15pt)
+Hello
+- A
+
+- B
+World
+
diff --git a/test/typ/layout/list-attach-05.typ b/test/typ/layout/list-attach-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-attach-05.typ
@@ -0,0 +1,4 @@
+// ... even if forced to.
+Hello
+#list(tight: false)[A][B]
+World
diff --git a/test/typ/layout/list-marker-00.typ b/test/typ/layout/list-marker-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-marker-00.typ
@@ -0,0 +1,5 @@
+// Test en-dash.
+#set list(marker: [--])
+- A
+- B
+
diff --git a/test/typ/layout/list-marker-01.typ b/test/typ/layout/list-marker-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-marker-01.typ
@@ -0,0 +1,6 @@
+// Test that last item is repeated.
+#set list(marker: ([--], [•]))
+- A
+  - B
+    - C
+
diff --git a/test/typ/layout/list-marker-02.typ b/test/typ/layout/list-marker-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-marker-02.typ
@@ -0,0 +1,9 @@
+// Test function.
+#set list(marker: n => if n == 1 [--] else [•])
+- A
+- B
+  - C
+  - D
+    - E
+- F
+
diff --git a/test/typ/layout/list-marker-03.typ b/test/typ/layout/list-marker-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-marker-03.typ
@@ -0,0 +1,5 @@
+// Test that bare hyphen doesn't lead to cycles and crashes.
+#set list(marker: [-])
+- Bare hyphen is
+- a bad marker
+
diff --git a/test/typ/layout/list-marker-04.typ b/test/typ/layout/list-marker-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/list-marker-04.typ
@@ -0,0 +1,2 @@
+// Error: 19-21 array must contain at least one marker
+#set list(marker: ())
diff --git a/test/typ/layout/pad-00.typ b/test/typ/layout/pad-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pad-00.typ
@@ -0,0 +1,13 @@
+// Use for indentation.
+#pad(left: 10pt, [Indented!])
+
+// All sides together.
+#set rect(inset: 0pt)
+#rect(fill: green,
+  pad(10pt, right: 20pt,
+    rect(width: 20pt, height: 20pt, fill: rgb("eb5278"))
+  )
+)
+
+Hi #box(pad(left: 10pt)[A]) there
+
diff --git a/test/typ/layout/pad-01.typ b/test/typ/layout/pad-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pad-01.typ
@@ -0,0 +1,3 @@
+// Pad can grow.
+#pad(left: 10pt, right: 10pt)[PL #h(1fr) PR]
+
diff --git a/test/typ/layout/pad-02.typ b/test/typ/layout/pad-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pad-02.typ
@@ -0,0 +1,6 @@
+// Test that the pad element doesn't consume the whole region.
+#set page(height: 6cm)
+#align(left)[Before]
+#pad(10pt, image("test/assets/files/tiger.jpg"))
+#align(right)[After]
+
diff --git a/test/typ/layout/pad-03.typ b/test/typ/layout/pad-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pad-03.typ
@@ -0,0 +1,2 @@
+// Test that padding adding up to 100% does not panic.
+#pad(50%)[]
diff --git a/test/typ/layout/page-00.typ b/test/typ/layout/page-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-00.typ
@@ -0,0 +1,4 @@
+// Just empty page.
+// Should result in auto-sized page, just like nothing.
+#page[]
+
diff --git a/test/typ/layout/page-01.typ b/test/typ/layout/page-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-01.typ
@@ -0,0 +1,4 @@
+// Just empty page with styles.
+// Should result in one green-colored A11 page.
+#page("a11", flipped: true, fill: green)[]
+
diff --git a/test/typ/layout/page-02.typ b/test/typ/layout/page-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-02.typ
@@ -0,0 +1,9 @@
+// Set width and height.
+// Should result in one high and one wide page.
+#set page(width: 80pt, height: 80pt)
+#[#set page(width: 40pt);High]
+#[#set page(height: 40pt);Wide]
+
+// Flipped predefined paper.
+#[#set page(paper: "a11", flipped: true);Flipped A11]
+
diff --git a/test/typ/layout/page-03.typ b/test/typ/layout/page-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-03.typ
@@ -0,0 +1,5 @@
+// Test page fill.
+#set page(width: 80pt, height: 40pt, fill: eastern)
+#text(15pt, font: "Roboto", fill: white, smallcaps[Typst])
+#page(width: 40pt, fill: none, margin: (top: 10pt, rest: auto))[Hi]
+
diff --git a/test/typ/layout/page-04.typ b/test/typ/layout/page-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-04.typ
@@ -0,0 +1,5 @@
+// Just page followed by pagebreak.
+// Should result in one red-colored A11 page and one auto-sized page.
+#page("a11", flipped: true, fill: red)[]
+#pagebreak()
+
diff --git a/test/typ/layout/page-05.typ b/test/typ/layout/page-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-05.typ
@@ -0,0 +1,7 @@
+// Layout without any container should provide the page's dimensions, minus its margins.
+
+#page(width: 100pt, height: 100pt, {
+  layout(size => [This page has a width of #size.width and height of #size.height ])
+  h(1em)
+  place(left, rect(width: 80pt, stroke: blue))
+})
diff --git a/test/typ/layout/page-margin-00.typ b/test/typ/layout/page-margin-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-margin-00.typ
@@ -0,0 +1,7 @@
+// Set all margins at once.
+#[
+  #set page(height: 20pt, margin: 5pt)
+  #place(top + left)[TL]
+  #place(bottom + right)[BR]
+]
+
diff --git a/test/typ/layout/page-margin-01.typ b/test/typ/layout/page-margin-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-margin-01.typ
@@ -0,0 +1,9 @@
+// Set individual margins.
+#set page(height: 40pt)
+#[#set page(margin: (left: 0pt)); #align(left)[Left]]
+#[#set page(margin: (right: 0pt)); #align(right)[Right]]
+#[#set page(margin: (top: 0pt)); #align(top)[Top]]
+#[#set page(margin: (bottom: 0pt)); #align(bottom)[Bottom]]
+
+// Ensure that specific margins override general margins.
+#[#set page(margin: (rest: 0pt, left: 20pt)); Overridden]
diff --git a/test/typ/layout/page-marginals-00.typ b/test/typ/layout/page-marginals-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-marginals-00.typ
@@ -0,0 +1,24 @@
+#set page(
+  paper: "a8",
+  margin: (x: 15pt, y: 30pt),
+  header: {
+    text(eastern)[*Typst*]
+    h(1fr)
+    text(0.8em)[_Chapter 1_]
+  },
+  footer: align(center)[\~ #counter(page).display() \~],
+  background: counter(page).display(n => if n <= 2 {
+    place(center + horizon, circle(radius: 1cm, fill: luma(90%)))
+  })
+)
+
+But, soft! what light through yonder window breaks? It is the east, and Juliet
+is the sun. Arise, fair sun, and kill the envious moon, Who is already sick and
+pale with grief, That thou her maid art far more fair than she: Be not her maid,
+since she is envious; Her vestal livery is but sick and green And none but fools
+do wear it; cast it off. It is my lady, O, it is my love! O, that she knew she
+were! She speaks yet she says nothing: what of that? Her eye discourses; I will
+answer it.
+
+#set page(header: none, height: auto, margin: (top: 15pt, bottom: 25pt))
+The END.
diff --git a/test/typ/layout/page-style-00.typ b/test/typ/layout/page-style-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-style-00.typ
@@ -0,0 +1,4 @@
+// Empty with styles
+// Should result in one green-colored A11 page.
+#set page("a11", flipped: true, fill: green)
+
diff --git a/test/typ/layout/page-style-01.typ b/test/typ/layout/page-style-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-style-01.typ
@@ -0,0 +1,5 @@
+// Empty with styles and then pagebreak
+// Should result in two red-colored pages.
+#set page(fill: red)
+#pagebreak()
+
diff --git a/test/typ/layout/page-style-02.typ b/test/typ/layout/page-style-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-style-02.typ
@@ -0,0 +1,6 @@
+// Empty with multiple page styles.
+// Should result in a small white page.
+#set page("a4")
+#set page("a5")
+#set page(width: 1cm, height: 1cm)
+
diff --git a/test/typ/layout/page-style-03.typ b/test/typ/layout/page-style-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/page-style-03.typ
@@ -0,0 +1,7 @@
+// Empty with multiple page styles.
+// Should result in one eastern-colored A11 page.
+#set page("a4")
+#set page("a5")
+#set page("a11", flipped: true, fill: eastern)
+#set text(font: "Roboto", white)
+#smallcaps[Typst]
diff --git a/test/typ/layout/pagebreak-00.typ b/test/typ/layout/pagebreak-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pagebreak-00.typ
@@ -0,0 +1,4 @@
+// Just a pagebreak.
+// Should result in two pages.
+#pagebreak()
+
diff --git a/test/typ/layout/pagebreak-01.typ b/test/typ/layout/pagebreak-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pagebreak-01.typ
@@ -0,0 +1,6 @@
+// Pagebreak, empty with styles and then pagebreak
+// Should result in one auto-sized page and two green-colored 2cm wide pages.
+#pagebreak()
+#set page(width: 2cm, fill: green)
+#pagebreak()
+
diff --git a/test/typ/layout/pagebreak-02.typ b/test/typ/layout/pagebreak-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pagebreak-02.typ
@@ -0,0 +1,9 @@
+// Two text bodies separated with and surrounded by weak pagebreaks.
+// Should result in two aqua-colored pages.
+#set page(fill: aqua)
+#pagebreak(weak: true)
+First
+#pagebreak(weak: true)
+Second
+#pagebreak(weak: true)
+
diff --git a/test/typ/layout/pagebreak-03.typ b/test/typ/layout/pagebreak-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pagebreak-03.typ
@@ -0,0 +1,10 @@
+// Test a combination of pagebreaks, styled pages and pages with bodies.
+// Should result in three five pages, with the fourth one being red-colored.
+#set page(width: 80pt, height: 30pt)
+#[#set page(width: 60pt); First]
+#pagebreak()
+#pagebreak()
+Third
+#page(height: 20pt, fill: red)[]
+Fif#[#set page();th]
+
diff --git a/test/typ/layout/pagebreak-04.typ b/test/typ/layout/pagebreak-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/pagebreak-04.typ
@@ -0,0 +1,9 @@
+// Test hard and weak pagebreak followed by page with body.
+// Should result in three navy-colored pages.
+#set page(fill: navy)
+#set text(fill: white)
+First
+#pagebreak()
+#page[Second]
+#pagebreak(weak: true)
+#page[Third]
diff --git a/test/typ/layout/par-00.typ b/test/typ/layout/par-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-00.typ
@@ -0,0 +1,4 @@
+// Test ragged-left.
+#set align(right)
+To the right! Where the sunlight peeks behind the mountain.
+
diff --git a/test/typ/layout/par-01.typ b/test/typ/layout/par-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-01.typ
@@ -0,0 +1,7 @@
+// Test changing leading and spacing.
+#set block(spacing: 1em)
+#set par(leading: 2pt)
+But, soft! what light through yonder window breaks?
+
+It is the east, and Juliet is the sun.
+
diff --git a/test/typ/layout/par-02.typ b/test/typ/layout/par-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-02.typ
@@ -0,0 +1,7 @@
+// Test that paragraph spacing loses against block spacing.
+// TODO
+#set block(spacing: 100pt)
+#show table: set block(above: 5pt, below: 5pt)
+Hello
+#table(columns: 4, fill: (x, y) => if calc.odd(x + y) { silver })[A][B][C][D]
+
diff --git a/test/typ/layout/par-03.typ b/test/typ/layout/par-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-03.typ
@@ -0,0 +1,12 @@
+// While we're at it, test the larger block spacing wins.
+#set block(spacing: 0pt)
+#show raw: set block(spacing: 15pt)
+#show list: set block(spacing: 2.5pt)
+
+```rust
+fn main() {}
+```
+
+- List
+
+Paragraph
diff --git a/test/typ/layout/par-bidi-00.typ b/test/typ/layout/par-bidi-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-00.typ
@@ -0,0 +1,5 @@
+// Test reordering with different top-level paragraph directions.
+#let content = par[Text טֶקסט]
+#text(lang: "he", content)
+#text(lang: "de", content)
+
diff --git a/test/typ/layout/par-bidi-01.typ b/test/typ/layout/par-bidi-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-01.typ
@@ -0,0 +1,7 @@
+// Test that consecutive, embedded  LTR runs stay LTR.
+// Here, we have two runs: "A" and italic "B".
+#let content = par[أنت A#emph[B]مطرC]
+#set text(font: ("PT Sans", "Noto Sans Arabic"))
+#text(lang: "ar", content)
+#text(lang: "de", content)
+
diff --git a/test/typ/layout/par-bidi-02.typ b/test/typ/layout/par-bidi-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-02.typ
@@ -0,0 +1,7 @@
+// Test that consecutive, embedded RTL runs stay RTL.
+// Here, we have three runs: "גֶ", bold "שֶׁ", and "ם".
+#let content = par[Aגֶ#strong[שֶׁ]םB]
+#set text(font: ("Linux Libertine", "Noto Serif Hebrew"))
+#text(lang: "he", content)
+#text(lang: "de", content)
+
diff --git a/test/typ/layout/par-bidi-03.typ b/test/typ/layout/par-bidi-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-03.typ
@@ -0,0 +1,4 @@
+// Test embedding up to level 4 with isolates.
+#set text(dir: rtl)
+א\u{2066}A\u{2067}Bב\u{2069}?
+
diff --git a/test/typ/layout/par-bidi-04.typ b/test/typ/layout/par-bidi-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-04.typ
@@ -0,0 +1,5 @@
+// Test hard line break (leads to two paragraphs in unicode-bidi).
+#set text(lang: "ar", font: ("Noto Sans Arabic", "PT Sans"))
+Life المطر هو الحياة \
+الحياة تمطر is rain.
+
diff --git a/test/typ/layout/par-bidi-05.typ b/test/typ/layout/par-bidi-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-05.typ
@@ -0,0 +1,4 @@
+// Test spacing.
+L #h(1cm) ריווחR \
+Lריווח #h(1cm) R
+
diff --git a/test/typ/layout/par-bidi-06.typ b/test/typ/layout/par-bidi-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-06.typ
@@ -0,0 +1,4 @@
+// Test inline object.
+#set text(lang: "he")
+קרנפיםRh#box(image("test/assets/files/rhino.png", height: 11pt))inoחיים
+
diff --git a/test/typ/layout/par-bidi-07.typ b/test/typ/layout/par-bidi-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-07.typ
@@ -0,0 +1,3 @@
+// Test whether L1 whitespace resetting destroys stuff.
+الغالب #h(70pt) ن#" "ة
+
diff --git a/test/typ/layout/par-bidi-08.typ b/test/typ/layout/par-bidi-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-bidi-08.typ
@@ -0,0 +1,5 @@
+// Test setting a vertical direction.
+// Ref: false
+
+// Error: 16-19 text direction must be horizontal
+#set text(dir: ttb)
diff --git a/test/typ/layout/par-indent-00.typ b/test/typ/layout/par-indent-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-indent-00.typ
@@ -0,0 +1,27 @@
+#set par(first-line-indent: 12pt, leading: 5pt)
+#set block(spacing: 5pt)
+#show heading: set text(size: 10pt)
+
+The first paragraph has no indent.
+
+But the second one does.
+
+#box(image("test/assets/files/tiger.jpg", height: 6pt))
+starts a paragraph, also with indent.
+
+#align(center, image("test/assets/files/rhino.png", width: 1cm))
+
+= Headings
+- And lists.
+- Have no indent.
+
+  Except if you have another paragraph in them.
+
+#set text(8pt, lang: "ar", font: ("Noto Sans Arabic", "Linux Libertine"))
+#set par(leading: 8pt)
+
+= Arabic
+دع النص يمطر عليك
+
+ثم يصبح النص رطبًا وقابل للطرق ويبدو المستند رائعًا.
+
diff --git a/test/typ/layout/par-indent-01.typ b/test/typ/layout/par-indent-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-indent-01.typ
@@ -0,0 +1,6 @@
+// This is madness.
+#set par(first-line-indent: 12pt)
+Why would anybody ever ...
+
+... want spacing and indent?
+
diff --git a/test/typ/layout/par-indent-02.typ b/test/typ/layout/par-indent-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-indent-02.typ
@@ -0,0 +1,4 @@
+// Test hanging indent.
+#set par(hanging-indent: 15pt, justify: true)
+#lorem(10)
+
diff --git a/test/typ/layout/par-indent-03.typ b/test/typ/layout/par-indent-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-indent-03.typ
@@ -0,0 +1,3 @@
+#set par(hanging-indent: 1em)
+Welcome \ here. Does this work well?
+
diff --git a/test/typ/layout/par-indent-04.typ b/test/typ/layout/par-indent-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-indent-04.typ
@@ -0,0 +1,4 @@
+#set par(hanging-indent: 2em)
+#set text(dir: rtl)
+لآن وقد أظلم الليل وبدأت النجوم
+تنضخ وجه الطبيعة التي أعْيَتْ من طول ما انبعثت في النهار
diff --git a/test/typ/layout/par-justify-00.typ b/test/typ/layout/par-justify-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-00.typ
@@ -0,0 +1,9 @@
+#set page(width: 180pt)
+#set block(spacing: 5pt)
+#set par(justify: true, first-line-indent: 14pt, leading: 5pt)
+
+This text is justified, meaning that spaces are stretched so that the text
+forms a "block" with flush edges at both sides.
+
+First line indents and hyphenation play nicely with justified text.
+
diff --git a/test/typ/layout/par-justify-01.typ b/test/typ/layout/par-justify-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-01.typ
@@ -0,0 +1,5 @@
+// Test that lines with hard breaks aren't justified.
+#set par(justify: true)
+A B C \
+D
+
diff --git a/test/typ/layout/par-justify-02.typ b/test/typ/layout/par-justify-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-02.typ
@@ -0,0 +1,4 @@
+// Test forced justification with justified break.
+A B C #linebreak(justify: true)
+D E F #linebreak(justify: true)
+
diff --git a/test/typ/layout/par-justify-03.typ b/test/typ/layout/par-justify-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-03.typ
@@ -0,0 +1,5 @@
+// Test that there are no hick-ups with justification enabled and
+// basically empty paragraph.
+#set par(justify: true)
+#""
+
diff --git a/test/typ/layout/par-justify-04.typ b/test/typ/layout/par-justify-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-04.typ
@@ -0,0 +1,4 @@
+// Test that the last line can be shrunk
+#set page(width: 155pt)
+#set par(justify: true)
+This text can be fitted in one line.
diff --git a/test/typ/layout/par-justify-cjk-00.typ b/test/typ/layout/par-justify-cjk-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-cjk-00.typ
@@ -0,0 +1,13 @@
+// Test Chinese text in narrow lines.
+
+// In Chinese typography, line length should be multiples of the character size
+// and the line ends should be aligned with each other.
+// Most Chinese publications do not use hanging punctuation at line end.
+#set page(width: auto)
+#set par(justify: true)
+#set text(font: "Noto Serif CJK SC", lang: "zh")
+
+#rect(inset: 0pt, width: 80pt, fill: rgb("eee"))[
+  中文维基百科使用汉字书写，汉字是汉族或华人的共同文字，是中国大陆、新加坡、马来西亚、台湾、香港、澳门的唯一官方文字或官方文字之一。25.9%，而美国和荷兰则分別占13.7%及8.2%。近年來，中国大陆地区的维基百科编辑者正在迅速增加；
+]
+
diff --git a/test/typ/layout/par-justify-cjk-01.typ b/test/typ/layout/par-justify-cjk-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-cjk-01.typ
@@ -0,0 +1,10 @@
+// Japanese typography is more complex, make sure it is at least a bit sensible.
+#set page(width: auto)
+#set par(justify: true)
+#set text(lang: "jp")
+#rect(inset: 0pt, width: 80pt, fill: rgb("eee"))[
+  ウィキペディア（英: Wikipedia）は、世界中のボランティアの共同作業によって執筆及び作成されるフリーの多言語インターネット百科事典である。主に寄付に依って活動している非営利団体「ウィキメディア財団」が所有・運営している。
+
+  専門家によるオンライン百科事典プロジェクトNupedia（ヌーペディア）を前身として、2001年1月、ラリー・サンガーとジミー・ウェールズ（英: Jimmy Donal "Jimbo" Wales）により英語でプロジェクトが開始された。
+]
+
diff --git a/test/typ/layout/par-justify-cjk-02.typ b/test/typ/layout/par-justify-cjk-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-cjk-02.typ
@@ -0,0 +1,12 @@
+// Test punctuation whitespace adjustment
+#set page(width: auto)
+#set text(lang: "zh", font: "Noto Serif CJK SC")
+#set par(justify: true)
+#rect(inset: 0pt, width: 80pt, fill: rgb("eee"))[
+  “引号测试”，还，
+
+  《书名》《测试》下一行
+
+  《书名》《测试》。
+]
+
diff --git a/test/typ/layout/par-justify-cjk-03.typ b/test/typ/layout/par-justify-cjk-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-justify-cjk-03.typ
@@ -0,0 +1,11 @@
+// Test Variants of Mainland China, Hong Kong, and Japan.
+
+// 17 characters a line.
+#set page(width: 170pt + 10pt, margin: (x: 5pt))
+#set text(font: "Noto Serif CJK SC", lang: "zh")
+#set par(justify: true)
+
+孔雀最早见于《山海经》中的《海内经》：\u{200b}“有孔雀。”东汉杨孚著《异物志》记载，岭南：“孔雀，其大如大雁而足高，毛皆有斑纹彩，捕而蓄之，拍手即舞。”
+
+#set text(font: "Noto Serif CJK TC", lang: "zh", region: "hk")
+孔雀最早见于《山海经》中的《海内经》：「有孔雀。」东汉杨孚著《异物志》记载，岭南：「孔雀，其大如大雁而足高，毛皆有斑纹彩，捕而蓄之，拍手即舞。」
diff --git a/test/typ/layout/par-knuth-00.typ b/test/typ/layout/par-knuth-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-knuth-00.typ
@@ -0,0 +1,30 @@
+#set page(width: auto, height: auto)
+#set par(leading: 4pt, justify: true)
+#set text(font: "New Computer Modern")
+
+#let story = [
+  In olden times when wishing still helped one, there lived a king whose
+  daughters were all beautiful; and the youngest was so beautiful that the sun
+  itself, which has seen so much, was astonished whenever it shone in her face.
+  Close by the king’s castle lay a great dark red, and under an old lime-tree
+  in the red was a well, and when the day was very warm, the king’s child
+  went out into the red and sat down by the side of the cool fountain; and
+  when she was bored she took a golden ball, and threw it up on high and caught
+  it; and this ball was her favorite plaything.
+]
+
+#let column(title, linebreaks, hyphenate) = {
+  rect(inset: 0pt, width: 132pt, fill: rgb("eee"))[
+    #set par(linebreaks: linebreaks)
+    #set text(hyphenate: hyphenate)
+    #strong(title) \ #story
+  ]
+}
+
+#grid(
+  columns: 3,
+  gutter: 10pt,
+  column([Simple without hyphens], "simple", false),
+  column([Simple with hyphens], "simple", true),
+  column([Optimized with hyphens], "optimized", true),
+)
diff --git a/test/typ/layout/par-simple-00.typ b/test/typ/layout/par-simple-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/par-simple-00.typ
@@ -0,0 +1,17 @@
+#set page(width: 250pt, height: 120pt)
+
+But, soft! what light through yonder window breaks? It is the east, and Juliet
+is the sun. Arise, fair sun, and kill the envious moon, Who is already sick and
+pale with grief, That thou her maid art far more fair than she: Be not her maid,
+since she is envious; Her vestal livery is but sick and green And none but fools
+do wear it; cast it off. It is my lady, O, it is my love! O, that she knew she
+were! She speaks yet she says nothing: what of that? Her eye discourses; I will
+answer it.
+
+I am too bold, 'tis not to me she speaks: Two of the fairest stars in all the
+heaven, Having some business, do entreat her eyes To twinkle in their spheres
+till they return. What if her eyes were there, they in her head? The brightness
+of her cheek would shame those stars, As daylight doth a lamp; her eyes in
+heaven Would through the airy region stream so bright That birds would sing and
+think it were not night. See, how she leans her cheek upon her hand! O, that I
+were a glove upon that hand, That I might touch that cheek!
diff --git a/test/typ/layout/place-00.typ b/test/typ/layout/place-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/place-00.typ
@@ -0,0 +1,23 @@
+#set page("a8")
+#place(bottom + center)[© Typst]
+
+= Placement
+#place(right, image("test/assets/files/tiger.jpg", width: 1.8cm))
+Hi there. This is \
+a placed element. \
+Unfortunately, \
+the line breaks still had to be inserted manually.
+
+#stack(
+  rect(fill: eastern, height: 10pt, width: 100%),
+  place(right, dy: 1.5pt)[ABC],
+  rect(fill: green, height: 10pt, width: 80%),
+  rect(fill: red, height: 10pt, width: 100%),
+  10pt,
+  block[
+    #place(center, dx: -7pt, dy: -5pt)[Hello]
+    #place(center, dx: 7pt, dy: 5pt)[Hello]
+    Hello #h(1fr) Hello
+  ]
+)
+
diff --git a/test/typ/layout/place-01.typ b/test/typ/layout/place-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/place-01.typ
@@ -0,0 +1,8 @@
+// Test how the placed element interacts with paragraph spacing around it.
+#set page("a8", height: 60pt)
+
+First
+
+#place(bottom + right)[Placed]
+
+Second
diff --git a/test/typ/layout/place-background-00.typ b/test/typ/layout/place-background-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/place-background-00.typ
@@ -0,0 +1,15 @@
+#set page(paper: "a10", flipped: true)
+#set text(fill: white)
+#place(
+  dx: -10pt,
+  dy: -10pt,
+  image(
+    "/tiger.jpg",
+    fit: "cover",
+    width: 100% + 20pt,
+    height: 100% + 20pt,
+  )
+)
+#align(bottom + right)[
+  _Welcome to_ #underline[*Tigerland*]
+]
diff --git a/test/typ/layout/repeat-00.typ b/test/typ/layout/repeat-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/repeat-00.typ
@@ -0,0 +1,14 @@
+// Test multiple repeats.
+#let sections = (
+  ("Introduction", 1),
+  ("Approach", 1),
+  ("Evaluation", 3),
+  ("Discussion", 15),
+  ("Related Work", 16),
+  ("Conclusion", 253),
+)
+
+#for section in sections [
+  #section.at(0) #box(width: 1fr, repeat[.]) #section.at(1) \
+]
+
diff --git a/test/typ/layout/repeat-01.typ b/test/typ/layout/repeat-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/repeat-01.typ
@@ -0,0 +1,4 @@
+// Test dots with RTL.
+#set text(lang: "ar")
+مقدمة #box(width: 1fr, repeat[.]) 15
+
diff --git a/test/typ/layout/repeat-02.typ b/test/typ/layout/repeat-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/repeat-02.typ
@@ -0,0 +1,3 @@
+// Test empty repeat.
+A #box(width: 1fr, repeat[]) B
+
diff --git a/test/typ/layout/repeat-03.typ b/test/typ/layout/repeat-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/repeat-03.typ
@@ -0,0 +1,3 @@
+// Test unboxed repeat.
+#repeat(rect(width: 2em, height: 1em))
+
diff --git a/test/typ/layout/repeat-04.typ b/test/typ/layout/repeat-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/repeat-04.typ
@@ -0,0 +1,9 @@
+// Test single repeat in both directions.
+A#box(width: 1fr, repeat(rect(width: 6em, height: 0.7em)))B
+
+#set align(center)
+A#box(width: 1fr, repeat(rect(width: 6em, height: 0.7em)))B
+
+#set text(dir: rtl)
+ريجين#box(width: 1fr, repeat(rect(width: 4em, height: 0.7em)))سون
+
diff --git a/test/typ/layout/repeat-05.typ b/test/typ/layout/repeat-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/repeat-05.typ
@@ -0,0 +1,3 @@
+// Error: 2:2-2:13 repeat with no size restrictions
+#set page(width: auto)
+#repeat(".")
diff --git a/test/typ/layout/spacing-00.typ b/test/typ/layout/spacing-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/spacing-00.typ
@@ -0,0 +1,16 @@
+// Linebreak and leading-sized weak spacing are equivalent.
+#box[A \ B] #box[A #v(0.65em, weak: true) B]
+
+// Eating up soft spacing.
+Inv#h(0pt)isible
+
+// Multiple spacings in a row.
+Add #h(10pt) #h(10pt) up
+
+// Relative to area.
+#let x = 25% - 4pt
+|#h(x)|#h(x)|#h(x)|#h(x)|
+
+// Fractional.
+| #h(1fr) | #h(2fr) | #h(1fr) |
+
diff --git a/test/typ/layout/spacing-01.typ b/test/typ/layout/spacing-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/spacing-01.typ
@@ -0,0 +1,6 @@
+// Test spacing collapsing before spacing.
+#set align(right)
+A #h(0pt) B #h(0pt) \
+A B \
+A #h(-1fr) B
+
diff --git a/test/typ/layout/spacing-02.typ b/test/typ/layout/spacing-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/spacing-02.typ
@@ -0,0 +1,5 @@
+// Test RTL spacing.
+#set text(dir: rtl)
+A #h(10pt) B \
+A #h(1fr) B
+
diff --git a/test/typ/layout/spacing-03.typ b/test/typ/layout/spacing-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/spacing-03.typ
@@ -0,0 +1,3 @@
+// Missing spacing.
+// Error: 11-13 missing argument: amount
+Totally #h() ignored
diff --git a/test/typ/layout/stack-1-00.typ b/test/typ/layout/stack-1-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/stack-1-00.typ
@@ -0,0 +1,18 @@
+// Test stacks with different directions.
+#let widths = (
+  30pt, 20pt, 40pt, 15pt,
+  30pt, 50%, 20pt, 100%,
+)
+
+#let shaded(i, w) = {
+  let v = (i + 1) * 10%
+  rect(width: w, height: 10pt, fill: rgb(v, v, v))
+}
+
+#let items = for (i, w) in widths.enumerate() {
+  (align(right, shaded(i, w)),)
+}
+
+#set page(width: 50pt, margin: 0pt)
+#stack(dir: btt, ..items)
+
diff --git a/test/typ/layout/stack-1-01.typ b/test/typ/layout/stack-1-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/stack-1-01.typ
@@ -0,0 +1,11 @@
+// Test spacing.
+#set page(width: 50pt, margin: 0pt)
+
+#let x = square(size: 10pt, fill: eastern)
+#stack(
+  spacing: 5pt,
+  stack(dir: rtl, spacing: 5pt, x, x, x),
+  stack(dir: ltr, x, 20%, x, 20%, x),
+  stack(dir: ltr, spacing: 5pt, x, x, 7pt, 3pt, x),
+)
+
diff --git a/test/typ/layout/stack-1-02.typ b/test/typ/layout/stack-1-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/stack-1-02.typ
@@ -0,0 +1,7 @@
+// Test overflow.
+#set page(width: 50pt, height: 30pt, margin: 0pt)
+#box(stack(
+  rect(width: 40pt, height: 20pt, fill: green),
+  rect(width: 30pt, height: 13pt, fill: red),
+))
+
diff --git a/test/typ/layout/stack-1-03.typ b/test/typ/layout/stack-1-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/stack-1-03.typ
@@ -0,0 +1,10 @@
+// Test aligning things in RTL stack with align function & fr units.
+#set page(width: 50pt, margin: 5pt)
+#set block(spacing: 5pt)
+#set text(8pt)
+#stack(dir: rtl, 1fr, [A], 1fr, [B], [C])
+#stack(dir: rtl,
+  align(center, [A]),
+  align(left, [B]),
+  [C],
+)
diff --git a/test/typ/layout/stack-2-00.typ b/test/typ/layout/stack-2-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/stack-2-00.typ
@@ -0,0 +1,13 @@
+#set page(height: 3.5cm)
+#stack(
+  dir: ltr,
+  spacing: 1fr,
+  ..for c in "ABCDEFGHI" {([#c],)}
+)
+
+Hello
+#v(2fr)
+from #h(1fr) the #h(1fr) wonderful
+#v(1fr)
+World! 🌍
+
diff --git a/test/typ/layout/stack-2-01.typ b/test/typ/layout/stack-2-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/stack-2-01.typ
@@ -0,0 +1,6 @@
+#set page(height: 2cm)
+#set text(white)
+#rect(fill: red)[
+          #v(1fr)
+  #h(1fr) Hi you!
+]
diff --git a/test/typ/layout/table-00.typ b/test/typ/layout/table-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/table-00.typ
@@ -0,0 +1,9 @@
+#set page(height: 70pt)
+#set table(fill: (x, y) => if calc.even(x + y) { rgb("aaa") })
+
+#table(
+  columns: (1fr,) * 3,
+  stroke: 2pt + rgb("333"),
+  [A], [B], [C], [], [], [D \ E \ F \ \ \ G], [H],
+)
+
diff --git a/test/typ/layout/table-01.typ b/test/typ/layout/table-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/table-01.typ
@@ -0,0 +1,2 @@
+#table(columns: 3, stroke: none, fill: green, [A], [B], [C])
+
diff --git a/test/typ/layout/table-02.typ b/test/typ/layout/table-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/table-02.typ
@@ -0,0 +1,15 @@
+// Test alignment with array.
+#table(
+  columns: (1fr, 1fr, 1fr),
+  align: (left, center, right),
+  [A], [B], [C]
+)
+
+// Test empty array.
+#set align(center)
+#table(
+  columns: (1fr, 1fr, 1fr),
+  align: (),
+  [A], [B], [C]
+)
+
diff --git a/test/typ/layout/table-03.typ b/test/typ/layout/table-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/table-03.typ
@@ -0,0 +1,3 @@
+// Ref: false
+#table()
+
diff --git a/test/typ/layout/table-04.typ b/test/typ/layout/table-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/table-04.typ
@@ -0,0 +1,2 @@
+// Error: 14-19 expected color, none, array, or function, found string
+#table(fill: "hey")
diff --git a/test/typ/layout/terms-00.typ b/test/typ/layout/terms-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/terms-00.typ
@@ -0,0 +1,6 @@
+// Test with constructor.
+#terms(
+  ([One], [First]),
+  ([Two], [Second]),
+)
+
diff --git a/test/typ/layout/terms-01.typ b/test/typ/layout/terms-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/terms-01.typ
@@ -0,0 +1,5 @@
+// Test joining.
+#for word in lorem(4).split().map(s => s.trim(".")) [
+  / #word: Latin stuff.
+]
+
diff --git a/test/typ/layout/terms-02.typ b/test/typ/layout/terms-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/terms-02.typ
@@ -0,0 +1,8 @@
+// Test multiline.
+#set text(8pt)
+
+/ Fruit: A tasty, edible thing.
+/ Veggie:
+  An important energy source
+  for vegetarians.
+
diff --git a/test/typ/layout/terms-03.typ b/test/typ/layout/terms-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/terms-03.typ
@@ -0,0 +1,7 @@
+// Test style change.
+#set text(8pt)
+/ First list: #lorem(6)
+
+#set terms(hanging-indent: 30pt)
+/ Second list: #lorem(5)
+
diff --git a/test/typ/layout/terms-04.typ b/test/typ/layout/terms-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/terms-04.typ
@@ -0,0 +1,11 @@
+// Test grid like show rule.
+#show terms: it => table(
+  columns: 2,
+  inset: 3pt,
+  ..it.children.map(v => (emph(v.term), v.description)).flatten(),
+)
+
+/ A: One letter
+/ BB: Two letters
+/ CCC: Three letters
+
diff --git a/test/typ/layout/terms-05.typ b/test/typ/layout/terms-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/terms-05.typ
@@ -0,0 +1,4 @@
+/ Term:
+Not in list
+/Nope
+
diff --git a/test/typ/layout/terms-06.typ b/test/typ/layout/terms-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/terms-06.typ
@@ -0,0 +1,2 @@
+// Error: 8 expected colon
+/ Hello
diff --git a/test/typ/layout/transform-00.typ b/test/typ/layout/transform-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/transform-00.typ
@@ -0,0 +1,26 @@
+// Test creating the TeX and XeTeX logos.
+#let size = 11pt
+#let tex = {
+  [T]
+  h(-0.14 * size)
+  box(move(dy: 0.22 * size)[E])
+  h(-0.12 * size)
+  [X]
+}
+
+#let xetex = {
+  [X]
+  h(-0.14 * size)
+  box(scale(x: -100%, move(dy: 0.26 * size)[E]))
+  h(-0.14 * size)
+  [T]
+  h(-0.14 * size)
+  box(move(dy: 0.26 * size)[E])
+  h(-0.12 * size)
+  [X]
+}
+
+#set text(font: "New Computer Modern", size)
+Neither #tex, \
+nor #xetex!
+
diff --git a/test/typ/layout/transform-01.typ b/test/typ/layout/transform-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/transform-01.typ
@@ -0,0 +1,6 @@
+// Test combination of scaling and rotation.
+#set page(height: 80pt)
+#align(center + horizon,
+  rotate(20deg, scale(70%, image("test/assets/files/tiger.jpg")))
+)
+
diff --git a/test/typ/layout/transform-02.typ b/test/typ/layout/transform-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/transform-02.typ
@@ -0,0 +1,5 @@
+// Test setting rotation origin.
+#rotate(10deg, origin: top + left,
+  image("test/assets/files/tiger.jpg", width: 50%)
+)
+
diff --git a/test/typ/layout/transform-03.typ b/test/typ/layout/transform-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/layout/transform-03.typ
@@ -0,0 +1,6 @@
+// Test setting scaling origin.
+#let r = rect(width: 100pt, height: 10pt, fill: red)
+#set page(height: 65pt)
+#box(scale(r, x: 50%, y: 200%, origin: left + top))
+#box(scale(r, x: 50%, origin: center))
+#box(scale(r, x: 50%, y: 200%, origin: right + bottom))
diff --git a/test/typ/math/accent-00.typ b/test/typ/math/accent-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/accent-00.typ
@@ -0,0 +1,4 @@
+// Test function call.
+$grave(a), acute(b), hat(f), tilde(§), macron(ä), diaer(a), ä \
+ breve(\&), dot(!), circle(a), caron(@), arrow(Z), arrow.l(Z)$
+
diff --git a/test/typ/math/accent-01.typ b/test/typ/math/accent-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/accent-01.typ
@@ -0,0 +1,2 @@
+$ x &= p \ dot(x) &= v \ dot.double(x) &= a \ dot.triple(x) &= j \ dot.quad(x) &= s $
+
diff --git a/test/typ/math/accent-02.typ b/test/typ/math/accent-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/accent-02.typ
@@ -0,0 +1,3 @@
+// Test `accent` function.
+$accent(ö, .), accent(v, <-), accent(ZZ, \u{0303})$
+
diff --git a/test/typ/math/accent-03.typ b/test/typ/math/accent-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/accent-03.typ
@@ -0,0 +1,3 @@
+// Test accent bounds.
+$sqrt(tilde(T)) + hat(f)/hat(g)$
+
diff --git a/test/typ/math/accent-04.typ b/test/typ/math/accent-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/accent-04.typ
@@ -0,0 +1,3 @@
+// Test wide base.
+$arrow("ABC" + d), tilde(sum)$
+
diff --git a/test/typ/math/accent-05.typ b/test/typ/math/accent-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/accent-05.typ
@@ -0,0 +1,3 @@
+// Test effect of accent on superscript.
+$A^x != hat(A)^x != hat(hat(A))^x$
+
diff --git a/test/typ/math/accent-06.typ b/test/typ/math/accent-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/accent-06.typ
@@ -0,0 +1,2 @@
+// Test high base.
+$ tilde(integral), tilde(integral)_a^b, tilde(integral_a^b) $
diff --git a/test/typ/math/alignment-00.typ b/test/typ/math/alignment-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/alignment-00.typ
@@ -0,0 +1,9 @@
+// Test alignment step functions.
+#set page(width: 225pt)
+$
+"a" &= c \
+&= c + 1 & "By definition" \
+&= d + 100 + 1000 \
+&= x && "Even longer" \
+$
+
diff --git a/test/typ/math/alignment-01.typ b/test/typ/math/alignment-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/alignment-01.typ
@@ -0,0 +1,7 @@
+// Test post-fix alignment.
+$
+& "right" \
+"a very long line" \
+"left" \
+$
+
diff --git a/test/typ/math/alignment-02.typ b/test/typ/math/alignment-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/alignment-02.typ
@@ -0,0 +1,7 @@
+// Test no alignment.
+$
+"right" \
+"a very long line" \
+"left" \
+$
+
diff --git a/test/typ/math/alignment-03.typ b/test/typ/math/alignment-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/alignment-03.typ
@@ -0,0 +1,5 @@
+// Test #460 equations.
+$
+a &=b & quad c&=d \
+e &=f & g&=h
+$
diff --git a/test/typ/math/attach-00.typ b/test/typ/math/attach-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-00.typ
@@ -0,0 +1,3 @@
+// Test basics, postscripts.
+$f_x + t^b + V_1^2 + attach(A, t: alpha, b: beta)$
+
diff --git a/test/typ/math/attach-01.typ b/test/typ/math/attach-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-01.typ
@@ -0,0 +1,7 @@
+// Test basics, prescripts. Notably, the upper and lower prescripts' content need to be
+// aligned on the right edge of their bounding boxes, not on the left as in postscripts.
+$
+attach(upright(O), bl: 8, tl: 16, br: 2, tr: 2-),
+attach("Pb", bl: 82, tl: 207) + attach(upright(e), bl: -1, tl: 0) + macron(v)_e \
+$
+
diff --git a/test/typ/math/attach-02.typ b/test/typ/math/attach-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-02.typ
@@ -0,0 +1,28 @@
+// A mixture of attachment positioning schemes.
+$
+attach(a, tl: u),   attach(a, tr: v),   attach(a, bl: x),
+attach(a, br: y),   limits(a)^t,        limits(a)_b \
+
+attach(a, tr: v, t: t),
+attach(a, tr: v, br: y),
+attach(a, br: y, b: b),
+attach(limits(a), b: b, bl: x),
+attach(a, tl: u, bl: x),
+attach(limits(a), t: t, tl: u) \
+
+attach(a, tl: u, tr: v),
+attach(limits(a), t: t, br: y),
+attach(limits(a), b: b, tr: v),
+attach(a, bl: x, br: y),
+attach(limits(a), b: b, tl: u),
+attach(limits(a), t: t, bl: u),
+limits(a)^t_b \
+
+attach(a, tl: u, tr: v, bl: x, br: y),
+attach(limits(a), t: t, bl: x, br: y, b: b),
+attach(limits(a), t: t, tl: u, tr: v, b: b),
+attach(limits(a), tl: u, bl: x, t: t, b: b),
+attach(limits(a), t: t, b: b, tr: v, br: y),
+attach(a, tl: u, t: t, tr: v, bl: x, b: b, br: y)
+$
+
diff --git a/test/typ/math/attach-03.typ b/test/typ/math/attach-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-03.typ
@@ -0,0 +1,4 @@
+// Test function call after subscript.
+$pi_1(Y), a_f(x), a^zeta(x) \
+ a^subset.eq(x), a_(zeta(x)), pi_(1(Y))$
+
diff --git a/test/typ/math/attach-04.typ b/test/typ/math/attach-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-04.typ
@@ -0,0 +1,11 @@
+// Test associativity and scaling.
+$ 1/(V^2^3^4^5),
+  1/attach(V, tl: attach(2, tl: attach(3, tl: attach(4, tl: 5)))),
+  attach(Omega,
+    tl: attach(2, tl: attach(3, tl: attach(4, tl: 5))),
+    tr: attach(2, tr: attach(3, tr: attach(4, tr: 5))),
+    bl: attach(2, bl: attach(3, bl: attach(4, bl: 5))),
+    br: attach(2, br: attach(3, br: attach(4, br: 5))),
+  )
+$
+
diff --git a/test/typ/math/attach-05.typ b/test/typ/math/attach-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-05.typ
@@ -0,0 +1,5 @@
+// Test high subscript and superscript.
+$ sqrt(a_(1/2)^zeta), sqrt(a_alpha^(1/2)), sqrt(a_(1/2)^(3/4)) \
+  sqrt(attach(a, tl: 1/2, bl: 3/4)),
+  sqrt(attach(a, tl: 1/2, bl: 3/4, tr: 1/2, br: 3/4)) $
+
diff --git a/test/typ/math/attach-06.typ b/test/typ/math/attach-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-06.typ
@@ -0,0 +1,3 @@
+// Test frame base.
+$ (-1)^n + (1/2 + 3)^(-1/2) $
+
diff --git a/test/typ/math/attach-07.typ b/test/typ/math/attach-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-07.typ
@@ -0,0 +1,9 @@
+#set text(size: 8pt)
+
+// Test that the attachments are aligned horizontally.
+$ x_1 p_1 frak(p)_1 2_1 dot_1 lg_1 !_1 \\_1 ]_1 "ip"_1 op("iq")_1 \
+  x^1 b^1 frak(b)^1 2^1 dot^1 lg^1 !^1 \\^1 ]^1 "ib"^1 op("id")^1 \
+  x_1 y_1 "_"_1 x^1 l^1 "`"^1 attach(I,tl:1,bl:1,tr:1,br:1)
+  scripts(sum)_1^1 integral_1^1 |1/2|_1^1 \
+  x^1_1, "("b y")"^1_1 != (b y)^1_1, "[∫]"_1 [integral]_1 $
+
diff --git a/test/typ/math/attach-08.typ b/test/typ/math/attach-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-08.typ
@@ -0,0 +1,3 @@
+// Test limit.
+$ lim_(n->oo \ n "grows") sum_(k=0 \ k in NN)^n k $
+
diff --git a/test/typ/math/attach-09.typ b/test/typ/math/attach-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/attach-09.typ
@@ -0,0 +1,4 @@
+// Test forcing scripts and limits.
+$ limits(A)_1^2 != A_1^2 $
+$ scripts(sum)_1^2 != sum_1^2 $
+$ limits(integral)_a^b != integral_a^b $
diff --git a/test/typ/math/cancel-00.typ b/test/typ/math/cancel-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/cancel-00.typ
@@ -0,0 +1,5 @@
+// Inline
+$a + 5 + cancel(x) + b - cancel(x)$
+
+$c + (a dot.c cancel(b dot.c c))/(cancel(b dot.c c))$
+
diff --git a/test/typ/math/cancel-01.typ b/test/typ/math/cancel-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/cancel-01.typ
@@ -0,0 +1,5 @@
+// Display
+#set page(width: auto)
+$ a + b + cancel(b + c) - cancel(b) - cancel(c) - 5 + cancel(6) - cancel(6) $
+$ e + (a dot.c cancel((b + c + d)))/(cancel(b + c + d)) $
+
diff --git a/test/typ/math/cancel-02.typ b/test/typ/math/cancel-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/cancel-02.typ
@@ -0,0 +1,4 @@
+// Inverted
+$a + cancel(x, inverted: #true) - cancel(x, inverted: #true) + 10 + cancel(y) - cancel(y)$
+$ x + cancel("abcdefg", inverted: #true) $
+
diff --git a/test/typ/math/cancel-03.typ b/test/typ/math/cancel-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/cancel-03.typ
@@ -0,0 +1,4 @@
+// Cross
+$a + cancel(b + c + d, cross: #true, stroke: #red) + e$
+$ a + cancel(b + c + d, cross: #true) + e $
+
diff --git a/test/typ/math/cancel-04.typ b/test/typ/math/cancel-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/cancel-04.typ
@@ -0,0 +1,5 @@
+// Resized and styled
+#set page(width: 200pt, height: auto)
+$a + cancel(x, length: #200%) - cancel(x, length: #50%, stroke: #{red + 1.1pt})$
+$ b + cancel(x, length: #150%) - cancel(a + b + c, length: #50%, stroke: #{blue + 1.2pt}) $
+
diff --git a/test/typ/math/cancel-05.typ b/test/typ/math/cancel-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/cancel-05.typ
@@ -0,0 +1,3 @@
+// Rotated
+$x + cancel(y, rotation: #90deg) - cancel(z, rotation: #135deg)$
+$ e + cancel((j + e)/(f + e)) - cancel((j + e)/(f + e), rotation: #30deg) $
diff --git a/test/typ/math/cases-00.typ b/test/typ/math/cases-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/cases-00.typ
@@ -0,0 +1,6 @@
+$ f(x, y) := cases(
+  1 quad &"if" (x dot y)/2 <= 0,
+  2 &"if" x divides 2,
+  3 &"if" x in NN,
+  4 &"else",
+) $
diff --git a/test/typ/math/content-00.typ b/test/typ/math/content-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/content-00.typ
@@ -0,0 +1,4 @@
+// Test images and font fallback.
+#let monkey = move(dy: 0.2em, image("test/assets/files/monkey.svg", height: 1em))
+$ sum_(i=#emoji.apple)^#emoji.apple.red i + monkey/2 $
+
diff --git a/test/typ/math/content-01.typ b/test/typ/math/content-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/content-01.typ
@@ -0,0 +1,3 @@
+// Test tables.
+$ x := #table(columns: 2)[x][y]/mat(1, 2, 3)
+     = #table[A][B][C] $
diff --git a/test/typ/math/content-02.typ b/test/typ/math/content-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/content-02.typ
@@ -0,0 +1,3 @@
+// Test non-equation math directly in content.
+#math.attach($a$, t: [b])
+
diff --git a/test/typ/math/content-03.typ b/test/typ/math/content-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/content-03.typ
@@ -0,0 +1,3 @@
+// Test font switch.
+#let here = text.with(font: "Noto Sans")
+$#here[f] := #here[Hi there]$.
diff --git a/test/typ/math/delimited-00.typ b/test/typ/math/delimited-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-00.typ
@@ -0,0 +1,4 @@
+// Test automatic matching.
+$ (a) + {b/2} + |a|/2 + (b) $
+$f(x/2) < zeta(c^2 + |a + b/2|)$
+
diff --git a/test/typ/math/delimited-01.typ b/test/typ/math/delimited-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-01.typ
@@ -0,0 +1,3 @@
+// Test unmatched.
+$[1,2[ = [1,2) != zeta\(x/2\) $
+
diff --git a/test/typ/math/delimited-02.typ b/test/typ/math/delimited-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-02.typ
@@ -0,0 +1,4 @@
+// Test manual matching.
+$ [|a/b|] != lr(|]a/b|]) != [a/b) $
+$ lr(| ]1,2\[ + 1/2|) $
+
diff --git a/test/typ/math/delimited-03.typ b/test/typ/math/delimited-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-03.typ
@@ -0,0 +1,4 @@
+// Test fence confusion.
+$ |x + |y| + z/a| \
+  |x + lr(|y|) + z/a| $
+
diff --git a/test/typ/math/delimited-04.typ b/test/typ/math/delimited-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-04.typ
@@ -0,0 +1,4 @@
+// Test that symbols aren't matched automatically.
+$ bracket.l a/b bracket.r
+  = lr(bracket.l a/b bracket.r) $
+
diff --git a/test/typ/math/delimited-05.typ b/test/typ/math/delimited-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-05.typ
@@ -0,0 +1,3 @@
+// Test half LRs.
+$ lr(a/b\]) = a = lr(\{a/b) $
+
diff --git a/test/typ/math/delimited-06.typ b/test/typ/math/delimited-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-06.typ
@@ -0,0 +1,4 @@
+// Test manual scaling.
+$ lr(]sum_(x=1)^n x], size: #70%)
+  < lr((1, 2), size: #200%) $
+
diff --git a/test/typ/math/delimited-07.typ b/test/typ/math/delimited-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-07.typ
@@ -0,0 +1,3 @@
+// Test predefined delimiter pairings.
+$floor(x/2), ceil(x/2), abs(x), norm(x)$
+
diff --git a/test/typ/math/delimited-08.typ b/test/typ/math/delimited-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-08.typ
@@ -0,0 +1,5 @@
+// Test colored delimiters
+$ lr(
+    text("(", fill: #green) a/b
+    text(")", fill: #blue)
+  ) $
diff --git a/test/typ/math/frac-00.typ b/test/typ/math/frac-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/frac-00.typ
@@ -0,0 +1,3 @@
+// Test that denominator baseline matches in the common case.
+$ x = 1/2 = a/(a h) = a/a = a/(1/2) $
+
diff --git a/test/typ/math/frac-01.typ b/test/typ/math/frac-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/frac-01.typ
@@ -0,0 +1,3 @@
+// Test parenthesis removal.
+$ (|x| + |y|)/2 < [1+2]/3 $
+
diff --git a/test/typ/math/frac-02.typ b/test/typ/math/frac-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/frac-02.typ
@@ -0,0 +1,3 @@
+// Test large fraction.
+$ x = (-b plus.minus sqrt(b^2 - 4a c))/(2a) $
+
diff --git a/test/typ/math/frac-03.typ b/test/typ/math/frac-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/frac-03.typ
@@ -0,0 +1,3 @@
+// Test binomial.
+$ binom(circle, square) $
+
diff --git a/test/typ/math/frac-04.typ b/test/typ/math/frac-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/frac-04.typ
@@ -0,0 +1,3 @@
+// Error: 8-13 missing argument: lower
+$ binom(x^2) $
+
diff --git a/test/typ/math/frac-05.typ b/test/typ/math/frac-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/frac-05.typ
@@ -0,0 +1,3 @@
+// Test associativity.
+$ 1/2/3 = (1/2)/3 = 1/(2/3) $
+
diff --git a/test/typ/math/frac-06.typ b/test/typ/math/frac-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/frac-06.typ
@@ -0,0 +1,6 @@
+// Test precedence.
+$ a_1/b_2, 1/f(x), zeta(x)/2, "foo"[|x|]/2 \
+  1.2/3.7, 2.3^3.4 \
+  🏳️‍🌈[x]/2, f [x]/2, phi [x]/2, 🏳️‍🌈 [x]/2 \
+  +[x]/2, 1(x)/2, 2[x]/2 \
+  (a)b/2, b(a)[b]/2 $
diff --git a/test/typ/math/matrix-00.typ b/test/typ/math/matrix-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-00.typ
@@ -0,0 +1,10 @@
+// Test semicolon syntax.
+#set align(center)
+$mat() dot
+ mat(;) dot
+ mat(1, 2) dot
+ mat(1, 2;) \
+ mat(1; 2) dot
+ mat(1, 2; 3, 4) dot
+ mat(1 + &2, 1/2; &3, 4)$
+
diff --git a/test/typ/math/matrix-01.typ b/test/typ/math/matrix-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-01.typ
@@ -0,0 +1,8 @@
+// Test sparse matrix.
+$ mat(
+  1, 2, ..., 10;
+  2, 2, ..., 10;
+  dots.v, dots.v, dots.down, dots.v;
+  10, 10, ..., 10;
+) $
+
diff --git a/test/typ/math/matrix-02.typ b/test/typ/math/matrix-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-02.typ
@@ -0,0 +1,7 @@
+// Test baseline alignment.
+$ mat(
+  a, b^2;
+  sum_(x \ y) x, a^(1/2);
+  zeta, alpha;
+) $
+
diff --git a/test/typ/math/matrix-03.typ b/test/typ/math/matrix-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-03.typ
@@ -0,0 +1,5 @@
+// Test alternative delimiter with set rule.
+#set math.mat(delim: "[")
+$ mat(1, 2; 3, 4) $
+$ a + mat(delim: #none, 1, 2; 3, 4) + b $
+
diff --git a/test/typ/math/matrix-04.typ b/test/typ/math/matrix-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-04.typ
@@ -0,0 +1,19 @@
+// Test alternative math delimiter directly in call.
+#set align(center)
+#grid(
+  columns: 3,
+  gutter: 10pt,
+
+  $ mat(1, 2, delim: "[") $,
+  $ mat(1, 2; delim: "[") $,
+  $ mat(delim: "[", 1, 2) $,
+
+  $ mat(1; 2; delim: "[") $,
+  $ mat(1; delim: "[", 2) $,
+  $ mat(delim: "[", 1; 2) $,
+
+  $ mat(1, 2; delim: "[", 3, 4) $,
+  $ mat(delim: "[", 1, 2; 3, 4) $,
+  $ mat(1, 2; 3, 4; delim: "[") $,
+)
+
diff --git a/test/typ/math/matrix-05.typ b/test/typ/math/matrix-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-05.typ
@@ -0,0 +1,2 @@
+// Error: 13-14 expected array, found content
+$ mat(1, 2; 3, 4, delim: "[") $,
diff --git a/test/typ/math/matrix-alignment-00.typ b/test/typ/math/matrix-alignment-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-alignment-00.typ
@@ -0,0 +1,7 @@
+// Test alternating alignment in a vector.
+$ vec(
+  "a" & "a a a" & "a a",
+  "a a" & "a a" & "a",
+  "a a a" & "a" & "a a a",
+) $
+
diff --git a/test/typ/math/matrix-alignment-01.typ b/test/typ/math/matrix-alignment-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-alignment-01.typ
@@ -0,0 +1,7 @@
+// Test alternating explicit alignment in a matrix.
+$ mat(
+  "a" & "a a a" & "a a";
+  "a a" & "a a" & "a";
+  "a a a" & "a" & "a a a";
+) $
+
diff --git a/test/typ/math/matrix-alignment-02.typ b/test/typ/math/matrix-alignment-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-alignment-02.typ
@@ -0,0 +1,7 @@
+// Test alignment in a matrix.
+$ mat(
+  "a", "a a a", "a a";
+  "a a", "a a", "a";
+  "a a a", "a", "a a a";
+) $
+
diff --git a/test/typ/math/matrix-alignment-03.typ b/test/typ/math/matrix-alignment-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-alignment-03.typ
@@ -0,0 +1,7 @@
+// Test explicit left alignment in a matrix.
+$ mat(
+  &"a", &"a a a", &"a a";
+  &"a a", &"a a", &"a";
+  &"a a a", &"a", &"a a a";
+) $
+
diff --git a/test/typ/math/matrix-alignment-04.typ b/test/typ/math/matrix-alignment-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-alignment-04.typ
@@ -0,0 +1,7 @@
+// Test explicit right alignment in a matrix.
+$ mat(
+  "a"&, "a a a"&, "a a"&;
+  "a a"&, "a a"&, "a"&;
+  "a a a"&, "a"&, "a a a"&;
+) $
+
diff --git a/test/typ/math/matrix-alignment-05.typ b/test/typ/math/matrix-alignment-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-alignment-05.typ
@@ -0,0 +1,6 @@
+// Test #460 equations.
+$ mat(&a+b,c;&d, e) $
+$ mat(&a+b&,c;&d&, e) $
+$ mat(&&&a+b,c;&&&d, e) $
+$ mat(.&a+b&.,c;.....&d&....., e) $
+
diff --git a/test/typ/math/matrix-alignment-06.typ b/test/typ/math/matrix-alignment-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/matrix-alignment-06.typ
@@ -0,0 +1,5 @@
+// Test #454 equations.
+$ mat(-1, 1, 1; 1, -1, 1; 1, 1, -1) $
+$ mat(-1&, 1&, 1&; 1&, -1&, 1&; 1&, 1&, -1&) $
+$ mat(-1&, 1&, 1&; 1, -1, 1; 1, 1, -1) $
+$ mat(&-1, &1, &1; 1, -1, 1; 1, 1, -1) $
diff --git a/test/typ/math/multiline-00.typ b/test/typ/math/multiline-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-00.typ
@@ -0,0 +1,5 @@
+// Test basic alignment.
+$ x &= x + y \
+    &= x + 2z \
+    &= sum x dot 2z $
+
diff --git a/test/typ/math/multiline-01.typ b/test/typ/math/multiline-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-01.typ
@@ -0,0 +1,5 @@
+// Test text before first alignment point.
+$ x + 1 &= a^2 + b^2 \
+      y &= a + b^2 \
+      z &= alpha dot beta $
+
diff --git a/test/typ/math/multiline-02.typ b/test/typ/math/multiline-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-02.typ
@@ -0,0 +1,4 @@
+// Test space between inner alignment points.
+$ a + b &= 2 + 3 &= 5 \
+      b &= c     &= 3 $
+
diff --git a/test/typ/math/multiline-03.typ b/test/typ/math/multiline-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-03.typ
@@ -0,0 +1,6 @@
+// Test in case distinction.
+$ f := cases(
+  1 + 2 &"iff" &x,
+  3     &"if"  &y,
+) $
+
diff --git a/test/typ/math/multiline-04.typ b/test/typ/math/multiline-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-04.typ
@@ -0,0 +1,5 @@
+// Test mixing lines with and some without alignment points.
+$ "abc" &= c \
+   &= d + 1 \
+   = x $
+
diff --git a/test/typ/math/multiline-05.typ b/test/typ/math/multiline-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-05.typ
@@ -0,0 +1,3 @@
+// Test multiline subscript.
+$ sum_(n in NN \ n <= 5) n = (5(5+1))/2 = 15 $
+
diff --git a/test/typ/math/multiline-06.typ b/test/typ/math/multiline-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-06.typ
@@ -0,0 +1,6 @@
+// Test no trailing line break.
+$
+"abc" &= c
+$
+No trailing line break.
+
diff --git a/test/typ/math/multiline-07.typ b/test/typ/math/multiline-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-07.typ
@@ -0,0 +1,6 @@
+// Test single trailing line break.
+$
+"abc" &= c \
+$
+One trailing line break.
+
diff --git a/test/typ/math/multiline-08.typ b/test/typ/math/multiline-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/multiline-08.typ
@@ -0,0 +1,5 @@
+// Test multiple trailing line breaks.
+$
+"abc" &= c \ \ \
+$
+Multiple trailing line breaks.
diff --git a/test/typ/math/numbering-00.typ b/test/typ/math/numbering-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/numbering-00.typ
@@ -0,0 +1,8 @@
+#set page(width: 150pt)
+#set math.equation(numbering: "(I)")
+
+We define $x$ in preparation of @fib:
+$ phi.alt := (1 + sqrt(5)) / 2 $ <ratio>
+
+With @ratio, we get
+$ F_n = round(1 / sqrt(5) phi.alt^n) $ <fib>
diff --git a/test/typ/math/op-00.typ b/test/typ/math/op-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/op-00.typ
@@ -0,0 +1,3 @@
+// Test predefined.
+$ max_(1<=n<=m) n $
+
diff --git a/test/typ/math/op-01.typ b/test/typ/math/op-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/op-01.typ
@@ -0,0 +1,4 @@
+// With or without parens.
+$  &sin x + log_2 x \
+ = &sin(x) + log_2(x) $
+
diff --git a/test/typ/math/op-02.typ b/test/typ/math/op-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/op-02.typ
@@ -0,0 +1,5 @@
+// Test scripts vs limits.
+#set text(font: "New Computer Modern")
+Discuss $lim_(n->oo) 1/n$ now.
+$ lim_(n->infinity) 1/n = 0 $
+
diff --git a/test/typ/math/op-03.typ b/test/typ/math/op-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/op-03.typ
@@ -0,0 +1,4 @@
+// Test custom operator.
+$ op("myop", limits: #false)_(x:=1) x \
+  op("myop", limits: #true)_(x:=1) x $
+
diff --git a/test/typ/math/op-04.typ b/test/typ/math/op-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/op-04.typ
@@ -0,0 +1,2 @@
+// Test styled operator.
+$ bold(op("bold", limits: #true))_x y $
diff --git a/test/typ/math/root-00.typ b/test/typ/math/root-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/root-00.typ
@@ -0,0 +1,3 @@
+// Test root with more than one character.
+$A = sqrt(x + y) = c$
+
diff --git a/test/typ/math/root-01.typ b/test/typ/math/root-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/root-01.typ
@@ -0,0 +1,10 @@
+// Test root size with radicals containing attachments.
+$ sqrt(a) quad
+  sqrt(f) quad
+  sqrt(q) quad
+  sqrt(a^2) \
+  sqrt(n_0) quad
+  sqrt(b^()) quad
+  sqrt(b^2) quad
+  sqrt(q_1^2) $
+
diff --git a/test/typ/math/root-02.typ b/test/typ/math/root-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/root-02.typ
@@ -0,0 +1,8 @@
+// Test precomposed vs constructed roots.
+// 3 and 4 are precomposed.
+$sqrt(x)$
+$root(2, x)$
+$root(3, x)$
+$root(4, x)$
+$root(5, x)$
+
diff --git a/test/typ/math/root-03.typ b/test/typ/math/root-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/root-03.typ
@@ -0,0 +1,6 @@
+// Test large bodies
+$ sqrt([|x|]^2 + [|y|]^2) < [|z|] $
+$ v = sqrt((1/2) / (4/5))
+   = root(3, (1/2/3) / (4/5/6))
+   = root(4, ((1/2) / (3/4)) / ((1/2) / (3/4))) $
+
diff --git a/test/typ/math/root-04.typ b/test/typ/math/root-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/root-04.typ
@@ -0,0 +1,6 @@
+// Test large index.
+$ root(2, x) quad
+  root(3/(2/1), x) quad
+  root(1/11, x) quad
+  root(1/2/3, 1) $
+
diff --git a/test/typ/math/root-05.typ b/test/typ/math/root-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/root-05.typ
@@ -0,0 +1,4 @@
+// Test shorthand.
+$ √2^3 = sqrt(2^3) $
+$ √(x+y) quad ∛x quad ∜x $
+$ (√2+3) = (sqrt(2)+3) $
diff --git a/test/typ/math/spacing-00.typ b/test/typ/math/spacing-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/spacing-00.typ
@@ -0,0 +1,12 @@
+// Test spacing cases.
+$ä, +, c, (, )$ \
+$=), (+), {times}$
+$⟧<⟦, |-|, [=$ \
+$a=b, a==b$ \
+$-a, +a$ \
+$a not b$ \
+$a+b, a*b$ \
+$sum x, sum(x)$ \
+$sum product x$ \
+$f(x), zeta(x), "frac"(x)$
+
diff --git a/test/typ/math/spacing-01.typ b/test/typ/math/spacing-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/spacing-01.typ
@@ -0,0 +1,5 @@
+// Test ignored vs non-ignored spaces.
+$f (x), f(x)$ \
+$[a|b], [a | b]$ \
+$a"is"b, a "is" b$
+
diff --git a/test/typ/math/spacing-02.typ b/test/typ/math/spacing-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/spacing-02.typ
@@ -0,0 +1,5 @@
+// Test predefined spacings.
+$a thin b, a med b, a thick b, a quad b$ \
+$a = thin b$ \
+$a - b ident c quad (mod 2)$
+
diff --git a/test/typ/math/spacing-03.typ b/test/typ/math/spacing-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/spacing-03.typ
@@ -0,0 +1,4 @@
+// Test spacing for set comprehension.
+#set page(width: auto)
+$ { x in RR | x "is natural" and x < 10 } $
+
diff --git a/test/typ/math/spacing-04.typ b/test/typ/math/spacing-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/spacing-04.typ
@@ -0,0 +1,7 @@
+// Test spacing for operators with decorations and modifiers on them
+#set page(width: auto)
+$a ident b + c - d => e log 5 op("ln") 6$ \
+$a cancel(ident) b overline(+) c arrow(-) d hat(=>) e cancel(log) 5 dot(op("ln")) 6$ \
+$a overbrace(ident) b underline(+) c grave(-) d underbracket(=>) e circle(log) 5 caron(op("ln")) 6$ \
+\
+$a attach(ident, tl: a, tr: b) b attach(limits(+), t: a, b: b) c tilde(-) d breve(=>) e attach(limits(log), t: a, b: b) 5 attach(op("ln"), tr: a, bl: b) 6$
diff --git a/test/typ/math/style-00.typ b/test/typ/math/style-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/style-00.typ
@@ -0,0 +1,3 @@
+// Test italic defaults.
+$a, A, delta, ϵ, diff, Delta, ϴ$
+
diff --git a/test/typ/math/style-01.typ b/test/typ/math/style-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/style-01.typ
@@ -0,0 +1,7 @@
+// Test forcing a specific style.
+$A, italic(A), upright(A), bold(A), bold(upright(A)), \
+ serif(A), sans(A), cal(A), frak(A), mono(A), bb(A), \
+ italic(diff), upright(diff), \
+ bb("hello") + bold(cal("world")), \
+ mono("SQRT")(x) wreath mono(123 + 456)$
+
diff --git a/test/typ/math/style-02.typ b/test/typ/math/style-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/style-02.typ
@@ -0,0 +1,3 @@
+// Test a few style exceptions.
+$h, bb(N), cal(R), Theta, italic(Theta), sans(Theta), sans(italic(Theta))$
+
diff --git a/test/typ/math/style-03.typ b/test/typ/math/style-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/style-03.typ
@@ -0,0 +1,3 @@
+// Test font fallback.
+$ よ and 🏳️‍🌈 $
+
diff --git a/test/typ/math/style-04.typ b/test/typ/math/style-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/style-04.typ
@@ -0,0 +1,3 @@
+// Test text properties.
+$text(#red, "time"^2) + sqrt("place")$
+
diff --git a/test/typ/math/style-05.typ b/test/typ/math/style-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/style-05.typ
@@ -0,0 +1,4 @@
+// Test different font.
+#show math.equation: set text(font: "Fira Math")
+$ v := vec(1 + 2, 2 - 4, sqrt(3), arrow(x)) + 1 $
+
diff --git a/test/typ/math/style-06.typ b/test/typ/math/style-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/style-06.typ
@@ -0,0 +1,3 @@
+// Test using rules for symbols
+#show sym.tack: it => $#h(1em) it #h(1em)$
+$ a tack b $
diff --git a/test/typ/math/syntax-00.typ b/test/typ/math/syntax-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/syntax-00.typ
@@ -0,0 +1,3 @@
+// Test Unicode math.
+$ ∑_(i=0)^ℕ a ∘ b = \u{2211}_(i=0)^NN a compose b $
+
diff --git a/test/typ/math/syntax-01.typ b/test/typ/math/syntax-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/syntax-01.typ
@@ -0,0 +1,8 @@
+// Test a few shorthands.
+$ underline(f' : NN -> RR) \
+  n |-> cases(
+    [|1|] &"if" n >>> 10,
+    2 * 3 &"if" n != 5,
+    1 - 0 thick &...,
+  ) $
+
diff --git a/test/typ/math/syntax-02.typ b/test/typ/math/syntax-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/syntax-02.typ
@@ -0,0 +1,3 @@
+// Test common symbols.
+$ dot \ dots \ ast \ tilde \ star $
+
diff --git a/test/typ/math/syntax-03.typ b/test/typ/math/syntax-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/syntax-03.typ
@@ -0,0 +1,2 @@
+// Error: 1:3 expected dollar sign
+$a
diff --git a/test/typ/math/unbalanced-00.typ b/test/typ/math/unbalanced-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/unbalanced-00.typ
@@ -0,0 +1,3 @@
+$ 1/(2 (x) $
+$ 1_(2 y (x) () $
+$ 1/(2 y (x) (2(3)) $
diff --git a/test/typ/math/underover-00.typ b/test/typ/math/underover-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/underover-00.typ
@@ -0,0 +1,6 @@
+// Test braces.
+$ x = underbrace(
+  1 + 2 + ... + 5,
+  underbrace("numbers", x + y)
+) $
+
diff --git a/test/typ/math/underover-01.typ b/test/typ/math/underover-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/underover-01.typ
@@ -0,0 +1,6 @@
+// Test lines and brackets.
+$ x = overbracket(
+  overline(underline(x + y)),
+  1 + 2 + ... + 5,
+) $
+
diff --git a/test/typ/math/underover-02.typ b/test/typ/math/underover-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/underover-02.typ
@@ -0,0 +1,4 @@
+// Test brackets.
+$ underbracket([1, 2/3], "relevant stuff")
+          arrow.l.r.double.long
+  overbracket([4/5,6], "irrelevant stuff") $
diff --git a/test/typ/math/vec-00.typ b/test/typ/math/vec-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/vec-00.typ
@@ -0,0 +1,3 @@
+// Test wide cell.
+$ v = vec(1, 2+3, 4) $
+
diff --git a/test/typ/math/vec-01.typ b/test/typ/math/vec-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/vec-01.typ
@@ -0,0 +1,4 @@
+// Test alternative delimiter.
+#set math.vec(delim: "[")
+$ vec(1, 2) $
+
diff --git a/test/typ/math/vec-02.typ b/test/typ/math/vec-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/vec-02.typ
@@ -0,0 +1,2 @@
+// Error: 22-25 expected "(", "[", "{", "|", "||", or none
+#set math.vec(delim: "%")
diff --git a/test/typ/meta/bibliography-00.typ b/test/typ/meta/bibliography-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/bibliography-00.typ
@@ -0,0 +1,6 @@
+// Test ambiguous reference.
+= Introduction <arrgh>
+// Error: 1-7 label occurs in the document and its bibliography
+@arrgh
+#bibliography("/works.bib")
+
diff --git a/test/typ/meta/bibliography-01.typ b/test/typ/meta/bibliography-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/bibliography-01.typ
@@ -0,0 +1,5 @@
+#set page(width: 200pt)
+= Details
+See also #cite("arrgh", "distress", [p. 22]), @arrgh[p. 4], and @distress[p. 5].
+#bibliography("/works.bib")
+
diff --git a/test/typ/meta/bibliography-02.typ b/test/typ/meta/bibliography-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/bibliography-02.typ
@@ -0,0 +1,10 @@
+// Test unconventional order.
+#set page(width: 200pt)
+#bibliography("/works.bib", title: [Works to be cited], style: "chicago-author-date")
+#line(length: 100%)
+#[#set cite(brackets: false)
+As described by @netwok],
+the net-work is a creature of its own.
+This is close to piratery! @arrgh
+And quark! @quark
+
diff --git a/test/typ/meta/bibliography-03.typ b/test/typ/meta/bibliography-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/bibliography-03.typ
@@ -0,0 +1,3 @@
+// Error: 15-43 duplicate bibliography keys: arrgh, distress, glacier-melt, issue201, mcintosh_anxiety, netwok, psychology25, quark, restful, sharing, tolkien54
+#bibliography(("/works.bib", "/works.bib"))
+
diff --git a/test/typ/meta/bibliography-04.typ b/test/typ/meta/bibliography-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/bibliography-04.typ
@@ -0,0 +1,7 @@
+#set page(width: 200pt)
+#set heading(numbering: "1.")
+#show bibliography: set heading(numbering: "1.")
+
+= Multiple Bibs
+Now we have multiple bibliographies containing #cite("glacier-melt", "keshav2007read")
+#bibliography(("/works.bib", "/works_too.bib"))
diff --git a/test/typ/meta/bibliography-ordering-00.typ b/test/typ/meta/bibliography-ordering-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/bibliography-ordering-00.typ
@@ -0,0 +1,7 @@
+#set page(width: 300pt)
+
+@mcintosh_anxiety, @psychology25
+@netwok, @issue201, @arrgh, @quark, @distress,
+@glacier-melt, @issue201, @tolkien54, @sharing, @restful
+
+#bibliography("/works.bib")
diff --git a/test/typ/meta/cite-footnote-00.typ b/test/typ/meta/cite-footnote-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/cite-footnote-00.typ
@@ -0,0 +1,5 @@
+Hello @netwok
+And again: @netwok
+
+#pagebreak()
+#bibliography("/works.bib", style: "chicago-notes")
diff --git a/test/typ/meta/counter-00.typ b/test/typ/meta/counter-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/counter-00.typ
@@ -0,0 +1,14 @@
+// Count with string key.
+#let mine = counter("mine!")
+
+Final: #locate(loc => mine.final(loc).at(0)) \
+#mine.step()
+First: #mine.display() \
+#mine.update(7)
+#mine.display("1 of 1", both: true) \
+#mine.step()
+#mine.step()
+Second: #mine.display("I")
+#mine.update(n => n * 2)
+#mine.step()
+
diff --git a/test/typ/meta/counter-01.typ b/test/typ/meta/counter-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/counter-01.typ
@@ -0,0 +1,8 @@
+// Count labels.
+#let label = <heya>
+#let count = counter(label).display()
+#let elem(it) = [#box(it) #label]
+
+#elem[hey, there!] #count \
+#elem[more here!] #count
+
diff --git a/test/typ/meta/counter-02.typ b/test/typ/meta/counter-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/counter-02.typ
@@ -0,0 +1,18 @@
+// Count headings.
+#set heading(numbering: "1.a.")
+#show heading: set text(10pt)
+#counter(heading).step()
+
+= Alpha
+In #counter(heading).display()
+== Beta
+
+#set heading(numbering: none)
+= Gamma
+#heading(numbering: "I.")[Delta]
+
+At Beta, it was #locate(loc => {
+  let it = query(heading, loc).find(it => it.body == [Beta])
+  numbering(it.numbering, ..counter(heading).at(it.location()))
+})
+
diff --git a/test/typ/meta/counter-03.typ b/test/typ/meta/counter-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/counter-03.typ
@@ -0,0 +1,6 @@
+// Count figures.
+#figure(numbering: "A", caption: [Four 'A's], kind: image, supplement: "Figure")[_AAAA!_]
+#figure(numbering: none, caption: [Four 'B's], kind: image, supplement: "Figure")[_BBBB!_]
+#figure(caption: [Four 'C's], kind: image, supplement: "Figure")[_CCCC!_]
+#counter(figure.where(kind: image)).update(n => n + 3)
+#figure(caption: [Four 'D's], kind: image, supplement: "Figure")[_DDDD!_]
diff --git a/test/typ/meta/counter-page-00.typ b/test/typ/meta/counter-page-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/counter-page-00.typ
@@ -0,0 +1,10 @@
+// Test the page counter.
+
+#set page(height: 50pt, margin: (bottom: 20pt, rest: 10pt))
+#lorem(12)
+#set page(numbering: "(i)")
+#lorem(6)
+#pagebreak()
+#set page(numbering: "1 / 1")
+#counter(page).update(1)
+#lorem(20)
diff --git a/test/typ/meta/document-00.typ b/test/typ/meta/document-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-00.typ
@@ -0,0 +1,4 @@
+// This is okay.
+#set document(title: "Hello")
+What's up?
+
diff --git a/test/typ/meta/document-01.typ b/test/typ/meta/document-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-01.typ
@@ -0,0 +1,4 @@
+// This, too.
+// Ref: false
+#set document(author: ("A", "B"))
+
diff --git a/test/typ/meta/document-02.typ b/test/typ/meta/document-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-02.typ
@@ -0,0 +1,5 @@
+// This, too.
+// Error: 23-29 expected string, found integer
+#set document(author: (123,))
+What's up?
+
diff --git a/test/typ/meta/document-03.typ b/test/typ/meta/document-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-03.typ
@@ -0,0 +1,5 @@
+Hello
+
+// Error: 2-30 document set rules must appear before any content
+#set document(title: "Hello")
+
diff --git a/test/typ/meta/document-04.typ b/test/typ/meta/document-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-04.typ
@@ -0,0 +1,3 @@
+// Error: 10-12 can only be used in set rules
+#document()
+
diff --git a/test/typ/meta/document-05.typ b/test/typ/meta/document-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-05.typ
@@ -0,0 +1,5 @@
+#box[
+  // Error: 4-32 document set rules are not allowed inside of containers
+  #set document(title: "Hello")
+]
+
diff --git a/test/typ/meta/document-06.typ b/test/typ/meta/document-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-06.typ
@@ -0,0 +1,5 @@
+#box[
+  // Error: 4-18 page configuration is not allowed inside of containers
+  #set page("a4")
+]
+
diff --git a/test/typ/meta/document-07.typ b/test/typ/meta/document-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/document-07.typ
@@ -0,0 +1,4 @@
+#box[
+  // Error: 4-15 pagebreaks are not allowed inside of containers
+  #pagebreak()
+]
diff --git a/test/typ/meta/figure-00.typ b/test/typ/meta/figure-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/figure-00.typ
@@ -0,0 +1,22 @@
+#set page(width: 150pt)
+#set figure(numbering: "I")
+
+We can clearly see that @fig-cylinder and
+@tab-complex are relevant in this context.
+
+#figure(
+  table(columns: 2)[a][b],
+  caption: [The basic table.],
+) <tab-basic>
+
+#figure(
+  pad(y: -6pt, image("test/assets/files/cylinder.svg", height: 2cm)),
+  caption: [The basic shapes.],
+  numbering: "I",
+) <fig-cylinder>
+
+#figure(
+  table(columns: 3)[a][b][c][d][e][f],
+  caption: [The complex table.],
+) <tab-complex>
+
diff --git a/test/typ/meta/figure-01.typ b/test/typ/meta/figure-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/figure-01.typ
@@ -0,0 +1,11 @@
+
+// Testing figures with tables.
+#figure(
+  table(
+    columns: 2,
+    [Second cylinder],
+    image("test/assets/files/cylinder.svg"),
+  ),
+  caption: "A table containing images."
+) <fig-image-in-table>
+
diff --git a/test/typ/meta/figure-02.typ b/test/typ/meta/figure-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/figure-02.typ
@@ -0,0 +1,58 @@
+
+// Testing show rules with figures with a simple theorem display
+#show figure.where(kind: "theorem"): it => {
+  let name = none
+  if not it.caption == none {
+    name = [ #emph(it.caption)]
+  } else {
+    name = []
+  }
+
+  let title = none
+  if not it.numbering == none {
+    title = it.supplement
+    if not it.numbering == none {
+      title += " " +  it.counter.display(it.numbering)
+    }
+  }
+  title = strong(title)
+  pad(
+    top: 0em, bottom: 0em,
+    block(
+      fill: green.lighten(90%),
+      stroke: 1pt + green,
+      inset: 10pt,
+      width: 100%,
+      radius: 5pt,
+      breakable: false,
+      [#title#name#h(0.1em):#h(0.2em)#it.body#v(0.5em)]
+    )
+  )
+}
+
+#set page(width: 150pt)
+#figure(
+  $a^2 + b^2 = c^2$,
+  supplement: "Theorem",
+  kind: "theorem",
+  caption: "Pythagoras' theorem.",
+  numbering: "1",
+) <fig-formula>
+
+#figure(
+  $a^2 + b^2 = c^2$,
+  supplement: "Theorem",
+  kind: "theorem",
+  caption: "Another Pythagoras' theorem.",
+  numbering: none,
+) <fig-formula>
+
+#figure(
+  ```rust
+  fn main() {
+    println!("Hello!");
+  }
+  ```,
+  caption: [Hello world in _rust_],
+)
+
diff --git a/test/typ/meta/figure-03.typ b/test/typ/meta/figure-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/figure-03.typ
@@ -0,0 +1,5 @@
+// Test breakable figures
+#set page(height: 6em)
+#show figure: set block(breakable: true)
+
+#figure(table[a][b][c][d][e], caption: [A table])
diff --git a/test/typ/meta/footnote-00.typ b/test/typ/meta/footnote-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-00.typ
@@ -0,0 +1,2 @@
+#footnote[Hi]
+
diff --git a/test/typ/meta/footnote-01.typ b/test/typ/meta/footnote-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-01.typ
@@ -0,0 +1,4 @@
+// Test space collapsing before footnote.
+A#footnote[A] \
+A #footnote[A]
+
diff --git a/test/typ/meta/footnote-02.typ b/test/typ/meta/footnote-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-02.typ
@@ -0,0 +1,6 @@
+// Test nested footnotes.
+First \
+Second #footnote[A, #footnote[B, #footnote[C]]] \
+Third #footnote[D, #footnote[E]] \
+Fourth
+
diff --git a/test/typ/meta/footnote-03.typ b/test/typ/meta/footnote-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-03.typ
@@ -0,0 +1,4 @@
+// Currently, numbers a bit out of order if a nested footnote ends up in the
+// same frame as another one. :(
+#footnote[A, #footnote[B]], #footnote[C]
+
diff --git a/test/typ/meta/footnote-04.typ b/test/typ/meta/footnote-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-04.typ
@@ -0,0 +1,11 @@
+// Test customization.
+#show footnote: set text(red)
+#show footnote.entry: set text(8pt, style: "italic")
+#set footnote.entry(
+  indent: 0pt,
+  gap: 0.6em,
+  clearance: 0.3em,
+  separator: repeat[.],
+)
+
+Beautiful footnotes. #footnote[Wonderful, aren't they?]
diff --git a/test/typ/meta/footnote-break-00.typ b/test/typ/meta/footnote-break-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-break-00.typ
@@ -0,0 +1,13 @@
+#set page(height: 200pt)
+
+#lorem(5)
+#footnote[ // 1
+  A simple footnote.
+  #footnote[Well, not that simple ...] // 2
+]
+#lorem(15)
+#footnote[Another footnote: #lorem(30)] // 3
+#lorem(15)
+#footnote[My fourth footnote: #lorem(50)] // 4
+#lorem(15)
+#footnote[And a final footnote.] // 5
diff --git a/test/typ/meta/footnote-container-00.typ b/test/typ/meta/footnote-container-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-container-00.typ
@@ -0,0 +1,10 @@
+// Test footnote in caption.
+Read the docs #footnote[https://typst.app/docs]!
+#figure(
+  image("test/assets/files/graph.png", width: 70%),
+  caption: [
+    A graph #footnote[A _graph_ is a structure with nodes and edges.]
+  ]
+)
+More #footnote[just for ...] footnotes #footnote[... testing. :)]
+
diff --git a/test/typ/meta/footnote-container-01.typ b/test/typ/meta/footnote-container-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-container-01.typ
@@ -0,0 +1,18 @@
+// Test duplicate footnotes.
+#let lang = footnote[Languages.]
+#let nums = footnote[Numbers.]
+
+/ "Hello": A word #lang
+/ "123": A number #nums
+
+- "Hello" #lang
+- "123" #nums
+
++ "Hello" #lang
++ "123" #nums
+
+#table(
+  columns: 2,
+  [Hello], [A word #lang],
+  [123], [A number #nums],
+)
diff --git a/test/typ/meta/footnote-invariant-00.typ b/test/typ/meta/footnote-invariant-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/footnote-invariant-00.typ
@@ -0,0 +1,5 @@
+#set page(height: 120pt)
+
+#lorem(13)
+
+There #footnote(lorem(20))
diff --git a/test/typ/meta/heading-00.typ b/test/typ/meta/heading-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/heading-00.typ
@@ -0,0 +1,9 @@
+// Different number of equals signs.
+
+= Level 1
+== Level 2
+=== Level 3
+
+// After three, it stops shrinking.
+=========== Level 11
+
diff --git a/test/typ/meta/heading-01.typ b/test/typ/meta/heading-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/heading-01.typ
@@ -0,0 +1,13 @@
+// Heading vs. no heading.
+
+// Parsed as headings if at start of the context.
+/**/ = Level 1
+#[== Level 2]
+#box[=== Level 3]
+
+// Not at the start of the context.
+No = heading
+
+// Escaped.
+\= No heading
+
diff --git a/test/typ/meta/heading-02.typ b/test/typ/meta/heading-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/heading-02.typ
@@ -0,0 +1,10 @@
+// Blocks can continue the heading.
+
+= #[This
+is
+multiline.
+]
+
+= This
+  is not.
+
diff --git a/test/typ/meta/heading-03.typ b/test/typ/meta/heading-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/heading-03.typ
@@ -0,0 +1,9 @@
+// Test styling.
+#show heading.where(level: 5): it => block(
+  text(font: "Roboto", fill: eastern, it.body + [!])
+)
+
+= Heading
+===== Heading 🌍
+#heading(level: 5)[Heading]
+
diff --git a/test/typ/meta/heading-04.typ b/test/typ/meta/heading-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/heading-04.typ
@@ -0,0 +1,5 @@
+// Edge cases.
+#set heading(numbering: "1.")
+=
+Not in heading
+=Nope
diff --git a/test/typ/meta/link-00.typ b/test/typ/meta/link-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-00.typ
@@ -0,0 +1,13 @@
+// Link syntax.
+https://example.com/
+
+// Link with body.
+#link("https://typst.org/")[Some text text text]
+
+// With line break.
+This link appears #link("https://google.com/")[in the middle of] a paragraph.
+
+// Certain prefixes are trimmed when using the `link` function.
+Contact #link("mailto:hi@typst.app") or
+call #link("tel:123") for more information.
+
diff --git a/test/typ/meta/link-01.typ b/test/typ/meta/link-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-01.typ
@@ -0,0 +1,7 @@
+// Test that the period is trimmed.
+#show link: underline
+https://a.b.?q=%10#. \
+Wahttp://link \
+Nohttps:\//link \
+Nohttp\://comment
+
diff --git a/test/typ/meta/link-02.typ b/test/typ/meta/link-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-02.typ
@@ -0,0 +1,5 @@
+// Verify that brackets are included in links.
+https://[::1]:8080/ \
+https://example.com/(paren) \
+https://example.com/#(((nested))) \
+
diff --git a/test/typ/meta/link-03.typ b/test/typ/meta/link-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-03.typ
@@ -0,0 +1,4 @@
+// Check that unbalanced brackets are not included in links.
+#[https://example.com/] \
+https://example.com/)
+
diff --git a/test/typ/meta/link-04.typ b/test/typ/meta/link-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-04.typ
@@ -0,0 +1,4 @@
+// Verify that opening brackets without closing brackets throw an error.
+// Error: 22-22 expected closing bracket in link
+https://exam(ple.com/
+
diff --git a/test/typ/meta/link-05.typ b/test/typ/meta/link-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-05.typ
@@ -0,0 +1,5 @@
+// Styled with underline and color.
+#show link: it => underline(text(fill: rgb("283663"), it))
+You could also make the
+#link("https://html5zombo.com/")[link look way more typical.]
+
diff --git a/test/typ/meta/link-06.typ b/test/typ/meta/link-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-06.typ
@@ -0,0 +1,5 @@
+// Transformed link.
+#set page(height: 60pt)
+#let mylink = link("https://typst.org/")[LINK]
+My cool #box(move(dx: 0.7cm, dy: 0.7cm, rotate(10deg, scale(200%, mylink))))
+
diff --git a/test/typ/meta/link-07.typ b/test/typ/meta/link-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-07.typ
@@ -0,0 +1,6 @@
+// Link containing a block.
+#link("https://example.com/", block[
+  My cool rhino
+  #box(move(dx: 10pt, image("test/assets/files/rhino.png", width: 1cm)))
+])
+
diff --git a/test/typ/meta/link-08.typ b/test/typ/meta/link-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-08.typ
@@ -0,0 +1,3 @@
+// Link to page one.
+#link((page: 1, x: 10pt, y: 20pt))[Back to the start]
+
diff --git a/test/typ/meta/link-09.typ b/test/typ/meta/link-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-09.typ
@@ -0,0 +1,4 @@
+// Test link to label.
+Text <hey>
+#link(<hey>)[Go to text.]
+
diff --git a/test/typ/meta/link-10.typ b/test/typ/meta/link-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-10.typ
@@ -0,0 +1,3 @@
+// Error: 2-20 label does not exist in the document
+#link(<hey>)[Nope.]
+
diff --git a/test/typ/meta/link-11.typ b/test/typ/meta/link-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/link-11.typ
@@ -0,0 +1,4 @@
+Text <hey>
+Text <hey>
+// Error: 2-20 label occurs multiple times in the document
+#link(<hey>)[Nope.]
diff --git a/test/typ/meta/numbering-00.typ b/test/typ/meta/numbering-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/numbering-00.typ
@@ -0,0 +1,7 @@
+#for i in range(0, 9) {
+  numbering("*", i)
+  [ and ]
+  numbering("I.a", i, i)
+  [ for #i \ ]
+}
+
diff --git a/test/typ/meta/numbering-01.typ b/test/typ/meta/numbering-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/numbering-01.typ
@@ -0,0 +1,15 @@
+#for i in range(0, 4) {
+  numbering("A", i)
+  [ for #i \ ]
+}
+... \
+#for i in range(26, 30) {
+  numbering("A", i)
+  [ for #i \ ]
+}
+... \
+#for i in range(702, 706) {
+  numbering("A", i)
+  [ for #i \ ]
+}
+
diff --git a/test/typ/meta/numbering-02.typ b/test/typ/meta/numbering-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/numbering-02.typ
@@ -0,0 +1,6 @@
+#set text(lang: "he")
+#for i in range(9, 21, step: 2) {
+  numbering("א.", i)
+  [ עבור #i \ ]
+}
+
diff --git a/test/typ/meta/numbering-03.typ b/test/typ/meta/numbering-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/numbering-03.typ
@@ -0,0 +1,8 @@
+#set text(lang: "zh")
+#for i in range(9,21, step: 2){
+  numbering("一", i)
+  [ and ]
+  numbering("壹", i)
+  [ for #i \ ]
+}
+
diff --git a/test/typ/meta/numbering-04.typ b/test/typ/meta/numbering-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/numbering-04.typ
@@ -0,0 +1,19 @@
+#for i in range(0, 4) {
+  numbering("イ", i)
+  [ (or ]
+  numbering("い", i)
+  [) for #i \ ]
+}
+... \
+#for i in range(47, 51) {
+  numbering("イ", i)
+  [ (or ]
+  numbering("い", i)
+  [) for #i \ ]
+}
+... \
+#for i in range(2256, 2260) {
+  numbering("イ", i)
+  [ for #i \ ]
+}
+
diff --git a/test/typ/meta/numbering-05.typ b/test/typ/meta/numbering-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/numbering-05.typ
@@ -0,0 +1,2 @@
+// Error: 17-19 number must be at least zero
+#numbering("1", -1)
diff --git a/test/typ/meta/outline-00.typ b/test/typ/meta/outline-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/outline-00.typ
@@ -0,0 +1,36 @@
+#set page("a7", margin: 20pt, numbering: "1")
+#set heading(numbering: "(1/a)")
+#show heading.where(level: 1): set text(12pt)
+#show heading.where(level: 2): set text(10pt)
+
+#outline()
+
+= Einleitung
+#lorem(12)
+
+= Analyse
+#lorem(10)
+
+#[
+  #set heading(outlined: false)
+  == Methodik
+  #lorem(6)
+]
+
+== Verarbeitung
+#lorem(4)
+
+== Programmierung
+```rust
+fn main() {
+  panic!("in the disco");
+}
+```
+
+==== Deep Stuff
+Ok ...
+
+#set heading(numbering: "(I)")
+
+= #text(blue)[Zusammen]fassung
+#lorem(10)
diff --git a/test/typ/meta/query-before-after-00.typ b/test/typ/meta/query-before-after-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/query-before-after-00.typ
@@ -0,0 +1,47 @@
+#set page(
+  paper: "a7",
+  numbering: "1 / 1",
+  margin: (bottom: 1cm, rest: 0.5cm),
+)
+
+#show heading.where(level: 1, outlined: true): it => [
+  #it
+
+  #set text(size: 12pt, weight: "regular")
+  #outline(
+    title: "Chapter outline",
+    indent: true,
+    target: heading
+      .where(level: 1)
+      .or(heading.where(level: 2))
+      .after(it.location(), inclusive: true)
+      .before(
+        heading
+          .where(level: 1, outlined: true)
+          .after(it.location(), inclusive: false),
+        inclusive: false,
+      )
+  )
+]
+
+#set heading(outlined: true, numbering: "1.")
+
+= Section 1
+== Subsection 1
+== Subsection 2
+=== Subsubsection 1
+=== Subsubsection 2
+== Subsection 3
+
+= Section 2
+== Subsection 1
+== Subsection 2
+
+= Section 3
+== Subsection 1
+== Subsection 2
+=== Subsubsection 1
+=== Subsubsection 2
+=== Subsubsection 3
+== Subsection 3
+
diff --git a/test/typ/meta/query-before-after-01.typ b/test/typ/meta/query-before-after-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/query-before-after-01.typ
@@ -0,0 +1,20 @@
+
+#set page(
+  paper: "a7",
+  numbering: "1 / 1",
+  margin: (bottom: 1cm, rest: 0.5cm),
+)
+
+#set heading(outlined: true, numbering: "1.")
+
+// This is purposefully an empty
+#locate(loc => [
+  Non-outlined elements:
+  #(query(selector(heading).and(heading.where(outlined: false)), loc)
+    .map(it => it.body).join(", "))
+])
+
+#heading("A", outlined: false)
+#heading("B", outlined: true)
+#heading("C", outlined: true)
+#heading("D", outlined: false)
diff --git a/test/typ/meta/query-figure-00.typ b/test/typ/meta/query-figure-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/query-figure-00.typ
@@ -0,0 +1,38 @@
+#set page(
+  paper: "a7",
+  numbering: "1 / 1",
+  margin: (bottom: 1cm, rest: 0.5cm),
+)
+
+#set figure(numbering: "I")
+#show figure: set image(width: 80%)
+
+= List of Figures
+#locate(it => {
+  let elements = query(selector(figure).after(it), it)
+  for it in elements [
+    Figure
+    #numbering(it.numbering,
+      ..counter(figure).at(it.location())):
+    #it.caption
+    #box(width: 1fr, repeat[.])
+    #counter(page).at(it.location()).first() \
+  ]
+})
+
+#figure(
+  image("test/assets/files/glacier.jpg"),
+  caption: [Glacier melting],
+)
+
+#figure(
+  rect[Just some stand-in text],
+  kind: image,
+  supplement: "Figure",
+  caption: [Stand-in text],
+)
+
+#figure(
+  image("test/assets/files/tiger.jpg"),
+  caption: [Tiger world],
+)
diff --git a/test/typ/meta/query-header-00.typ b/test/typ/meta/query-header-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/query-header-00.typ
@@ -0,0 +1,29 @@
+#set page(
+  paper: "a7",
+  margin: (y: 1cm, x: 0.5cm),
+  header: {
+    smallcaps[Typst Academy]
+    h(1fr)
+    locate(it => {
+      let after = query(selector(heading).after(it), it)
+      let before = query(selector(heading).before(it), it)
+      let elem = if before.len() != 0 {
+        before.last()
+      } else if after.len() != 0 {
+        after.first()
+      }
+      emph(elem.body)
+    })
+  }
+)
+
+#outline()
+
+= Introduction
+#lorem(35)
+
+= Background
+#lorem(35)
+
+= Approach
+#lorem(60)
diff --git a/test/typ/meta/ref-00.typ b/test/typ/meta/ref-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/ref-00.typ
@@ -0,0 +1,8 @@
+#set heading(numbering: "1.")
+
+= Introduction <intro>
+See @setup.
+
+== Setup <setup>
+As seen in @intro, we proceed.
+
diff --git a/test/typ/meta/ref-01.typ b/test/typ/meta/ref-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/ref-01.typ
@@ -0,0 +1,3 @@
+// Error: 1-5 label does not exist in the document
+@foo
+
diff --git a/test/typ/meta/ref-02.typ b/test/typ/meta/ref-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/ref-02.typ
@@ -0,0 +1,6 @@
+= First <foo>
+= Second <foo>
+
+// Error: 1-5 label occurs multiple times in the document
+@foo
+
diff --git a/test/typ/meta/ref-03.typ b/test/typ/meta/ref-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/ref-03.typ
@@ -0,0 +1,39 @@
+
+#show ref: it => {
+  if it.element != none and it.element.func() == figure {
+    let element = it.element
+    "["
+    element.supplement
+    "-"
+    str(element.counter.at(element.location()).at(0))
+    "]"
+    // it
+  } else {
+    it
+  }
+}
+
+#figure(
+  image("test/assets/files/cylinder.svg", height: 3cm),
+  caption: [A sylinder.],
+  supplement: "Fig",
+) <fig1>
+
+#figure(
+  image("test/assets/files/tiger.jpg", height: 3cm),
+  caption: [A tiger.],
+  supplement: "Figg",
+) <fig2>
+
+#figure(
+  $ A = 1 $,
+  kind: "equation",
+  supplement: "Equa",
+
+) <eq1>
+@fig1
+
+@fig2
+
+@eq1
+
diff --git a/test/typ/meta/ref-04.typ b/test/typ/meta/ref-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/ref-04.typ
@@ -0,0 +1,29 @@
+#set heading(numbering: (..nums) => {
+  nums.pos().map(str).join(".")
+  }, supplement: [Chapt])
+
+#show ref: it => {
+  if it.element != none and it.element.func() == heading {
+    let element = it.element
+    "["
+    emph(element.supplement)
+    "-"
+    numbering(element.numbering, ..counter(heading).at(element.location()))
+    "]"
+  } else {
+    it
+  }
+}
+
+= Introduction <intro>
+
+= Summary <sum>
+
+== Subsection <sub>
+
+@intro
+
+@sum
+
+@sub
+
diff --git a/test/typ/meta/ref-05.typ b/test/typ/meta/ref-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/ref-05.typ
@@ -0,0 +1,29 @@
+
+#show ref: it => {
+  if it.element != none {
+    if it.element.func() == text {
+      let element = it.element
+      "["
+      element
+      "]"
+    } else if it.element.func() == underline {
+      let element = it.element
+      "{"
+      element
+      "}"
+    } else {
+      it
+    }
+  } else {
+    it
+  }
+}
+
+@txt
+
+Ref something unreferable <txt>
+
+@under
+#underline[
+Some underline text.
+] <under>
diff --git a/test/typ/meta/state-00.typ b/test/typ/meta/state-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/state-00.typ
@@ -0,0 +1,14 @@
+#let s = state("hey", "a")
+#let double(it) = 2 * it
+
+#s.update(double)
+#s.update(double)
+$ 2 + 3 $
+#s.update(double)
+
+Is: #s.display(),
+Was: #locate(location => {
+  let it = query(math.equation, location).first()
+  s.at(it.location())
+}).
+
diff --git a/test/typ/meta/state-01.typ b/test/typ/meta/state-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/meta/state-01.typ
@@ -0,0 +1,21 @@
+#set page(width: 200pt)
+#set text(8pt)
+
+#let ls = state("lorem", lorem(1000).split("."))
+#let loremum(count) = {
+  ls.display(list => list.slice(0, count).join(".").trim() + ".")
+  ls.update(list => list.slice(count))
+}
+
+#let fs = state("fader", red)
+#let trait(title) = block[
+  #fs.display(color => text(fill: color)[
+    *#title:* #loremum(1)
+  ])
+  #fs.update(color => color.lighten(30%))
+]
+
+#trait[Boldness]
+#trait[Adventure]
+#trait[Fear]
+#trait[Anger]
diff --git a/test/typ/text/baseline-00.typ b/test/typ/text/baseline-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/baseline-00.typ
@@ -0,0 +1,12 @@
+// Test baseline handling.
+
+---
+Hi #text(1.5em)[You], #text(0.75em)[how are you?]
+
+Our cockatoo was one of the
+#text(baseline: -0.2em)[#box(circle(radius: 2pt)) first]
+#text(baseline: 0.2em)[birds #box(circle(radius: 2pt))]
+that ever learned to mimic a human voice.
+
+---
+Hey #box(baseline: 40%, image("test/assets/files/tiger.jpg", width: 1.5cm)) there!
diff --git a/test/typ/text/case-00.typ b/test/typ/text/case-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/case-00.typ
@@ -0,0 +1,5 @@
+#let memes = "ArE mEmEs gReAt?";
+#test(lower(memes), "are memes great?")
+#test(upper(memes), "ARE MEMES GREAT?")
+#test(upper("Ελλάδα"), "ΕΛΛΆΔΑ")
+
diff --git a/test/typ/text/case-01.typ b/test/typ/text/case-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/case-01.typ
@@ -0,0 +1,2 @@
+// Error: 8-9 expected string or content, found integer
+#upper(1)
diff --git a/test/typ/text/chinese-00.typ b/test/typ/text/chinese-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/chinese-00.typ
@@ -0,0 +1,6 @@
+#set text(font: "Noto Serif CJK SC")
+
+是美国广播公司电视剧《迷失》第3季的第22和23集，也是全剧的第71集和72集
+由执行制作人戴蒙·林道夫和卡尔顿·库斯编剧，导演则是另一名执行制作人杰克·本德
+节目于2007年5月23日在美国和加拿大首播，共计吸引了1400万美国观众收看
+本集加上插播广告一共也持续有两个小时
diff --git a/test/typ/text/copy-paste-00.typ b/test/typ/text/copy-paste-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/copy-paste-00.typ
@@ -0,0 +1,4 @@
+The after fira 🏳️‍🌈!
+
+#set text(lang: "ar", font: "Noto Sans Arabic")
+مرحبًا
diff --git a/test/typ/text/deco-00.typ b/test/typ/text/deco-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/deco-00.typ
@@ -0,0 +1,17 @@
+#let red = rgb("fc0030")
+
+// Basic strikethrough.
+#strike[Statements dreamt up by the utterly deranged.]
+
+// Move underline down.
+#underline(offset: 5pt)[Further below.]
+
+// Different color.
+#underline(stroke: red, evade: false)[Critical information is conveyed here.]
+
+// Inherits font color.
+#text(fill: red, underline[Change with the wind.])
+
+// Both over- and underline.
+#overline(underline[Running amongst the wolves.])
+
diff --git a/test/typ/text/deco-01.typ b/test/typ/text/deco-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/deco-01.typ
@@ -0,0 +1,8 @@
+#let redact = strike.with(stroke: 10pt, extent: 0.05em)
+#let highlight = strike.with(stroke: 10pt + rgb("abcdef88"), extent: 0.05em)
+
+// Abuse thickness and transparency for redacting and highlighting stuff.
+Sometimes, we work #redact[in secret].
+There might be #highlight[redacted] things.
+ underline()
+
diff --git a/test/typ/text/deco-02.typ b/test/typ/text/deco-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/deco-02.typ
@@ -0,0 +1,3 @@
+// Test stroke folding.
+#set underline(stroke: 2pt, offset: 2pt)
+#underline(text(red, [DANGER!]))
diff --git a/test/typ/text/edge-00.typ b/test/typ/text/edge-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/edge-00.typ
@@ -0,0 +1,15 @@
+#set page(width: 160pt)
+#set text(size: 8pt)
+
+#let try(top, bottom) = rect(inset: 0pt, fill: green)[
+  #set text(font: "IBM Plex Mono", top-edge: top, bottom-edge: bottom)
+  From #top to #bottom
+]
+
+#try("ascender", "descender")
+#try("ascender", "baseline")
+#try("cap-height", "baseline")
+#try("x-height", "baseline")
+#try(4pt, -2pt)
+#try(1pt + 0.3em, -0.15em)
+
diff --git a/test/typ/text/edge-01.typ b/test/typ/text/edge-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/edge-01.typ
@@ -0,0 +1,3 @@
+// Error: 21-23 expected "ascender", "cap-height", "x-height", "baseline", "descender", or length, found array
+#set text(top-edge: ())
+
diff --git a/test/typ/text/edge-02.typ b/test/typ/text/edge-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/edge-02.typ
@@ -0,0 +1,2 @@
+// Error: 24-26 expected "ascender", "cap-height", "x-height", "baseline", "descender", or length
+#set text(bottom-edge: "")
diff --git a/test/typ/text/em-00.typ b/test/typ/text/em-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/em-00.typ
@@ -0,0 +1,15 @@
+#set text(size: 5pt)
+A // 5pt
+#[
+  #set text(size: 2em)
+  B // 10pt
+  #[
+    #set text(size: 1.5em + 1pt)
+    C // 16pt
+    #text(size: 2em)[D] // 32pt
+    E // 16pt
+  ]
+  F // 10pt
+]
+G // 5pt
+
diff --git a/test/typ/text/em-01.typ b/test/typ/text/em-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/em-01.typ
@@ -0,0 +1,14 @@
+// Test using ems in arbitrary places.
+#set text(size: 5pt)
+#set text(size: 2em)
+#set square(fill: red)
+
+#let size = {
+  let size = 0.25em + 1pt
+  for _ in range(3) {
+    size *= 2
+  }
+  size - 3pt
+}
+
+#stack(dir: ltr, spacing: 1fr, square(size: size), square(size: 25pt))
diff --git a/test/typ/text/emoji-00.typ b/test/typ/text/emoji-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emoji-00.typ
@@ -0,0 +1,12 @@
+// This should form a three-member family.
+👩‍👩‍👦
+
+// This should form a pride flag.
+🏳️‍🌈
+
+// Skin tone modifier should be applied.
+👍🏿
+
+// This should be a 1 in a box.
+1️⃣
+
diff --git a/test/typ/text/emoji-01.typ b/test/typ/text/emoji-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emoji-01.typ
@@ -0,0 +1,2 @@
+// These two shouldn't be affected by a zero-width joiner.
+🏞‍🌋
diff --git a/test/typ/text/emphasis-00.typ b/test/typ/text/emphasis-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emphasis-00.typ
@@ -0,0 +1,11 @@
+// Basic.
+_Emphasized and *strong* words!_
+
+// Inside of a word it's a normal underscore or star.
+hello_world Nutzer*innen
+
+// Can contain paragraph in nested content block.
+_Still #[
+
+] emphasized._
+
diff --git a/test/typ/text/emphasis-01.typ b/test/typ/text/emphasis-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emphasis-01.typ
@@ -0,0 +1,3 @@
+// Inside of words can still use the functions.
+P#strong[art]ly em#emph[phas]ized.
+
diff --git a/test/typ/text/emphasis-02.typ b/test/typ/text/emphasis-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emphasis-02.typ
@@ -0,0 +1,9 @@
+// Adjusting the delta that strong applies on the weight.
+Normal
+
+#set strong(delta: 300)
+*Bold*
+
+#set strong(delta: 150)
+*Medium* and *#[*Bold*]*
+
diff --git a/test/typ/text/emphasis-03.typ b/test/typ/text/emphasis-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emphasis-03.typ
@@ -0,0 +1,3 @@
+// Error: 13 expected underscore
+#box[_Scoped] to body.
+
diff --git a/test/typ/text/emphasis-04.typ b/test/typ/text/emphasis-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emphasis-04.typ
@@ -0,0 +1,6 @@
+// Ends at paragraph break.
+// Error: 7 expected underscore
+_Hello
+
+World
+
diff --git a/test/typ/text/emphasis-05.typ b/test/typ/text/emphasis-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/emphasis-05.typ
@@ -0,0 +1,3 @@
+// Error: 26 expected star
+// Error: 26 expected underscore
+#[_Cannot *be interleaved]
diff --git a/test/typ/text/escape-00.typ b/test/typ/text/escape-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/escape-00.typ
@@ -0,0 +1,24 @@
+// Escapable symbols.
+\\ \/ \[ \] \{ \} \# \* \_ \+ \= \~ \
+\` \$ \" \' \< \> \@ \( \) \A
+
+// No need to escape.
+( ) ;
+
+// Escaped comments.
+\//
+\/\* \*\/
+\/* \*/ *
+
+// Unicode escape sequence.
+\u{1F3D5} == 🏕
+
+// Escaped escape sequence.
+\u{41} vs. \\u\{41\}
+
+// Some code stuff in text.
+let f() , ; : | + - /= == 12 "string"
+
+// Escaped dot.
+10\. May
+
diff --git a/test/typ/text/escape-01.typ b/test/typ/text/escape-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/escape-01.typ
@@ -0,0 +1,4 @@
+// Unicode codepoint does not exist.
+// Error: 1-11 invalid unicode codepoint: FFFFFF
+\u{FFFFFF}
+
diff --git a/test/typ/text/escape-02.typ b/test/typ/text/escape-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/escape-02.typ
@@ -0,0 +1,3 @@
+// Unterminated.
+// Error: 6 expected closing brace
+\u{41[*Bold*]
diff --git a/test/typ/text/fallback-00.typ b/test/typ/text/fallback-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/fallback-00.typ
@@ -0,0 +1,17 @@
+// Font fallback for emoji.
+A😀B
+
+// Font fallback for entire text.
+دع النص يمطر عليك
+
+// Font fallback in right-to-left text.
+ب🐈😀سم
+
+// Multi-layer font fallback.
+Aب😀🏞سمB
+
+// Font fallback with composed emojis and multiple fonts.
+01️⃣2
+
+// Tofus are rendered with the first font.
+A🐈ዲሞB
diff --git a/test/typ/text/features-00.typ b/test/typ/text/features-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-00.typ
@@ -0,0 +1,4 @@
+// Test turning kerning off.
+#text(kerning: true)[Tq] \
+#text(kerning: false)[Tq]
+
diff --git a/test/typ/text/features-01.typ b/test/typ/text/features-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-01.typ
@@ -0,0 +1,3 @@
+// Test smallcaps.
+#smallcaps[Smallcaps]
+
diff --git a/test/typ/text/features-02.typ b/test/typ/text/features-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-02.typ
@@ -0,0 +1,5 @@
+// Test alternates and stylistic sets.
+#set text(font: "IBM Plex Serif")
+a vs #text(alternates: true)[a] \
+ß vs #text(stylistic-set: 5)[ß]
+
diff --git a/test/typ/text/features-03.typ b/test/typ/text/features-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-03.typ
@@ -0,0 +1,3 @@
+// Test ligatures.
+fi vs. #text(ligatures: false)[No fi]
+
diff --git a/test/typ/text/features-04.typ b/test/typ/text/features-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-04.typ
@@ -0,0 +1,5 @@
+// Test number type.
+#set text(number-type: "old-style")
+0123456789 \
+#text(number-type: auto)[0123456789]
+
diff --git a/test/typ/text/features-05.typ b/test/typ/text/features-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-05.typ
@@ -0,0 +1,5 @@
+// Test number width.
+#text(number-width: "proportional")[0123456789] \
+#text(number-width: "tabular")[3456789123] \
+#text(number-width: "tabular")[0123456789]
+
diff --git a/test/typ/text/features-06.typ b/test/typ/text/features-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-06.typ
@@ -0,0 +1,5 @@
+// Test extra number stuff.
+#set text(font: "IBM Plex Serif")
+0 vs. #text(slashed-zero: true)[0] \
+1/2 vs. #text(fractions: true)[1/2]
+
diff --git a/test/typ/text/features-07.typ b/test/typ/text/features-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-07.typ
@@ -0,0 +1,4 @@
+// Test raw features.
+#text(features: ("smcp",))[Smcp] \
+fi vs. #text(features: (liga: 0))[No fi]
+
diff --git a/test/typ/text/features-08.typ b/test/typ/text/features-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-08.typ
@@ -0,0 +1,3 @@
+// Error: 26-31 expected integer or none, found boolean
+#set text(stylistic-set: false)
+
diff --git a/test/typ/text/features-09.typ b/test/typ/text/features-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-09.typ
@@ -0,0 +1,3 @@
+// Error: 26-28 stylistic set must be between 1 and 20
+#set text(stylistic-set: 25)
+
diff --git a/test/typ/text/features-10.typ b/test/typ/text/features-10.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-10.typ
@@ -0,0 +1,3 @@
+// Error: 24-25 expected "lining", "old-style", or auto, found integer
+#set text(number-type: 2)
+
diff --git a/test/typ/text/features-11.typ b/test/typ/text/features-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-11.typ
@@ -0,0 +1,3 @@
+// Error: 21-26 expected array or dictionary, found boolean
+#set text(features: false)
+
diff --git a/test/typ/text/features-12.typ b/test/typ/text/features-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/features-12.typ
@@ -0,0 +1,2 @@
+// Error: 21-35 expected string, found boolean
+#set text(features: ("tag", false))
diff --git a/test/typ/text/font-00.typ b/test/typ/text/font-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/font-00.typ
@@ -0,0 +1,34 @@
+// Set same font size in three different ways.
+#text(20pt)[A]
+#text(2em)[A]
+#text(size: 15pt + 0.5em)[A]
+
+// Do nothing.
+#text()[Normal]
+
+// Set style (is available).
+#text(style: "italic")[Italic]
+
+// Set weight (is available).
+#text(weight: "bold")[Bold]
+
+// Set stretch (not available, matching closest).
+#text(stretch: 50%)[Condensed]
+
+// Set font family.
+#text(font: "IBM Plex Serif")[Serif]
+
+// Emoji.
+Emoji: 🐪, 🌋, 🏞
+
+// Colors.
+#[
+  #set text(fill: eastern)
+  This is #text(rgb("FA644B"))[way more] colorful.
+]
+
+// Disable font fallback beyond the user-specified list.
+// Without disabling, New Computer Modern Math would come to the rescue.
+#set text(font: ("PT Sans", "Twitter Color Emoji"), fallback: false)
+2π = 𝛼 + 𝛽. ✅
+
diff --git a/test/typ/text/font-01.typ b/test/typ/text/font-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/font-01.typ
@@ -0,0 +1,7 @@
+// Test string body.
+#text("Text") \
+#text(red, "Text") \
+#text(font: "Ubuntu", blue, "Text") \
+#text([Text], teal, font: "IBM Plex Serif") \
+#text(red, font: "New Computer Modern", [Text]) \
+
diff --git a/test/typ/text/font-02.typ b/test/typ/text/font-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/font-02.typ
@@ -0,0 +1,3 @@
+// Error: 11-16 unexpected argument
+#set text(false)
+
diff --git a/test/typ/text/font-03.typ b/test/typ/text/font-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/font-03.typ
@@ -0,0 +1,3 @@
+// Error: 18-24 expected "normal", "italic", or "oblique"
+#set text(style: "bold", weight: "thin")
+
diff --git a/test/typ/text/font-04.typ b/test/typ/text/font-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/font-04.typ
@@ -0,0 +1,3 @@
+// Error: 23-27 unexpected argument
+#set text(size: 10pt, 12pt)
+
diff --git a/test/typ/text/font-05.typ b/test/typ/text/font-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/font-05.typ
@@ -0,0 +1,2 @@
+// Error: 11-31 unexpected argument: something
+#set text(something: "invalid")
diff --git a/test/typ/text/hyphenate-00.typ b/test/typ/text/hyphenate-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/hyphenate-00.typ
@@ -0,0 +1,9 @@
+// Test hyphenating english and greek.
+#set text(hyphenate: true)
+#set page(width: auto)
+#grid(
+  columns: (50pt, 50pt),
+  [Warm welcomes to Typst.],
+  text(lang: "el")[διαμερίσματα. \ λατρευτός],
+)
+
diff --git a/test/typ/text/hyphenate-01.typ b/test/typ/text/hyphenate-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/hyphenate-01.typ
@@ -0,0 +1,14 @@
+// Test disabling hyphenation for short passages.
+#set page(width: 110pt)
+#set text(hyphenate: true)
+
+Welcome to wonderful experiences. \
+Welcome to `wonderful` experiences. \
+Welcome to #text(hyphenate: false)[wonderful] experiences. \
+Welcome to wonde#text(hyphenate: false)[rf]ul experiences. \
+
+// Test enabling hyphenation for short passages.
+#set text(hyphenate: false)
+Welcome to wonderful experiences. \
+Welcome to wo#text(hyphenate: true)[nd]erful experiences. \
+
diff --git a/test/typ/text/hyphenate-02.typ b/test/typ/text/hyphenate-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/hyphenate-02.typ
@@ -0,0 +1,5 @@
+// Hyphenate between shape runs.
+#set page(width: 80pt)
+#set text(hyphenate: true)
+It's a #emph[Tree]beard.
+
diff --git a/test/typ/text/hyphenate-03.typ b/test/typ/text/hyphenate-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/hyphenate-03.typ
@@ -0,0 +1,9 @@
+// Test shy hyphens.
+#set text(lang: "de", hyphenate: true)
+#grid(
+  columns: 2 * (20pt,),
+  gutter: 20pt,
+  [Barankauf],
+  [Bar-?ankauf],
+)
+
diff --git a/test/typ/text/hyphenate-04.typ b/test/typ/text/hyphenate-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/hyphenate-04.typ
@@ -0,0 +1,7 @@
+// This sequence would confuse hypher if we passed trailing / leading
+// punctuation instead of just the words. So this tests that we don't
+// do that. The test passes if there's just one hyphenation between
+// "net" and "works".
+#set page(width: 60pt)
+#set text(hyphenate: true)
+#h(6pt) networks, the rest.
diff --git a/test/typ/text/lang-00.typ b/test/typ/text/lang-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-00.typ
@@ -0,0 +1,9 @@
+// Ensure that setting the language does have effects.
+#set text(hyphenate: true)
+#grid(
+  columns: 2 * (20pt,),
+  gutter: 1fr,
+  text(lang: "en")["Eingabeaufforderung"],
+  text(lang: "de")["Eingabeaufforderung"],
+)
+
diff --git a/test/typ/text/lang-01.typ b/test/typ/text/lang-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-01.typ
@@ -0,0 +1,11 @@
+// Test that the language passed to the shaper has an effect.
+#set text(font: "Ubuntu")
+
+// Some lowercase letters are different in Serbian Cyrillic compared to other
+// Cyrillic languages. Since there is only one set of Unicode codepoints for
+// Cyrillic, these can only be seen when setting the language to Serbian and
+// selecting one of the few fonts that support these letterforms.
+Бб
+#text(lang: "uk")[Бб]
+#text(lang: "sr")[Бб]
+
diff --git a/test/typ/text/lang-02.typ b/test/typ/text/lang-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-02.typ
@@ -0,0 +1,3 @@
+// Error: 17-21 expected string, found none
+#set text(lang: none)
+
diff --git a/test/typ/text/lang-03.typ b/test/typ/text/lang-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-03.typ
@@ -0,0 +1,3 @@
+// Error: 17-20 expected two or three letter language code (ISO 639-1/2/3)
+#set text(lang: "ӛ")
+
diff --git a/test/typ/text/lang-04.typ b/test/typ/text/lang-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-04.typ
@@ -0,0 +1,3 @@
+// Error: 17-20 expected two or three letter language code (ISO 639-1/2/3)
+#set text(lang: "😃")
+
diff --git a/test/typ/text/lang-05.typ b/test/typ/text/lang-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-05.typ
@@ -0,0 +1,2 @@
+// Error: 19-24 expected two letter region code (ISO 3166-1 alpha-2)
+#set text(region: "hey")
diff --git a/test/typ/text/lang-with-region-00.typ b/test/typ/text/lang-with-region-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-with-region-00.typ
@@ -0,0 +1,4 @@
+// without any region
+#set text(lang: "zh")
+#outline()
+
diff --git a/test/typ/text/lang-with-region-01.typ b/test/typ/text/lang-with-region-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-with-region-01.typ
@@ -0,0 +1,4 @@
+// with unknown region configured
+#set text(lang: "zh", region: "XX")
+#outline()
+
diff --git a/test/typ/text/lang-with-region-02.typ b/test/typ/text/lang-with-region-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lang-with-region-02.typ
@@ -0,0 +1,3 @@
+// with region configured
+#set text(lang: "zh", region: "TW")
+#outline()
diff --git a/test/typ/text/linebreak-00.typ b/test/typ/text/linebreak-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-00.typ
@@ -0,0 +1,3 @@
+// Test overlong word that is not directly after a hard break.
+This is a spaceexceedinglylongy.
+
diff --git a/test/typ/text/linebreak-01.typ b/test/typ/text/linebreak-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-01.typ
@@ -0,0 +1,3 @@
+// Test two overlong words in a row.
+Supercalifragilisticexpialidocious Expialigoricmetrioxidation.
+
diff --git a/test/typ/text/linebreak-02.typ b/test/typ/text/linebreak-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-02.typ
@@ -0,0 +1,3 @@
+// Test that there are no unwanted line break opportunities on run change.
+This is partly emp#emph[has]ized.
+
diff --git a/test/typ/text/linebreak-03.typ b/test/typ/text/linebreak-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-03.typ
@@ -0,0 +1,2 @@
+Hard #linebreak() break.
+
diff --git a/test/typ/text/linebreak-04.typ b/test/typ/text/linebreak-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-04.typ
@@ -0,0 +1,3 @@
+// Test hard break directly after normal break.
+Hard break directly after \ normal break.
+
diff --git a/test/typ/text/linebreak-05.typ b/test/typ/text/linebreak-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-05.typ
@@ -0,0 +1,3 @@
+// Test consecutive breaks.
+Two consecutive \ \ breaks and three \ \ more.
+
diff --git a/test/typ/text/linebreak-06.typ b/test/typ/text/linebreak-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-06.typ
@@ -0,0 +1,3 @@
+// Test forcing an empty trailing line.
+Trailing break \ \
+
diff --git a/test/typ/text/linebreak-07.typ b/test/typ/text/linebreak-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-07.typ
@@ -0,0 +1,7 @@
+// Test justified breaks.
+#set par(justify: true)
+With a soft #linebreak(justify: true)
+break you can force a break without #linebreak(justify: true)
+breaking justification. #linebreak(justify: false)
+Nice!
+
diff --git a/test/typ/text/linebreak-08.typ b/test/typ/text/linebreak-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-08.typ
@@ -0,0 +1,7 @@
+// Test comments at the end of a line
+First part//
+Second part
+
+// Test comments at the end of a line with pre-spacing
+First part          //
+Second part
diff --git a/test/typ/text/linebreak-obj-00.typ b/test/typ/text/linebreak-obj-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-obj-00.typ
@@ -0,0 +1,8 @@
+// Test punctuation after citations.
+#set page(width: 162pt)
+
+They can look for the details in @netwok,
+which is the authoritative source.
+
+#bibliography("/works.bib")
+
diff --git a/test/typ/text/linebreak-obj-01.typ b/test/typ/text/linebreak-obj-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/linebreak-obj-01.typ
@@ -0,0 +1,12 @@
+// Test punctuation after math equations.
+#set page(width: 85pt)
+
+We prove $1 < 2$. \
+We prove $1 < 2$! \
+We prove $1 < 2$? \
+We prove $1 < 2$, \
+We prove $1 < 2$; \
+We prove $1 < 2$: \
+We prove $1 < 2$- \
+We prove $1 < 2$– \
+We prove $1 < 2$— \
diff --git a/test/typ/text/lorem-00.typ b/test/typ/text/lorem-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lorem-00.typ
@@ -0,0 +1,3 @@
+// Test basic call.
+#lorem(19)
+
diff --git a/test/typ/text/lorem-01.typ b/test/typ/text/lorem-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lorem-01.typ
@@ -0,0 +1,22 @@
+// Test custom paragraphs with user code.
+#set text(8pt)
+
+#{
+  let sentences = lorem(59)
+    .split(".")
+    .filter(s => s != "")
+    .map(s => s + ".")
+
+  let used = 0
+  for s in sentences {
+    if used < 2 {
+      used += 1
+    } else {
+      parbreak()
+      used = 0
+    }
+    s.trim()
+    [ ]
+  }
+}
+
diff --git a/test/typ/text/lorem-02.typ b/test/typ/text/lorem-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/lorem-02.typ
@@ -0,0 +1,2 @@
+// Error: 7-9 missing argument: words
+#lorem()
diff --git a/test/typ/text/microtype-00.typ b/test/typ/text/microtype-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/microtype-00.typ
@@ -0,0 +1,14 @@
+// Test hanging punctuation.
+#set page(width: 130pt, margin: 15pt)
+#set par(justify: true, linebreaks: "simple")
+#set text(size: 9pt)
+#rect(inset: 0pt, fill: rgb(0, 0, 0, 0), width: 100%)[
+  This is a little bit of text that builds up to
+  hang-ing hyphens and dash---es and then, you know,
+  some punctuation in the margin.
+]
+
+// Test hanging punctuation with RTL.
+#set text(lang: "he", font: ("PT Sans", "Noto Serif Hebrew"))
+בנייה נכונה של משפטים ארוכים דורשת ידע בשפה. אז בואו נדבר על מזג האוויר.
+
diff --git a/test/typ/text/microtype-01.typ b/test/typ/text/microtype-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/microtype-01.typ
@@ -0,0 +1,5 @@
+// Test that lone punctuation doesn't overhang into the margin.
+#set page(margin: 0pt)
+#set align(end)
+#set text(dir: rtl)
+:
diff --git a/test/typ/text/quotes-00.typ b/test/typ/text/quotes-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/quotes-00.typ
@@ -0,0 +1,33 @@
+#set page(width: 250pt)
+
+// Test simple quotations in various languages.
+#set text(lang: "en")
+"The horse eats no cucumber salad" was the first sentence ever uttered on the 'telephone.'
+
+#set text(lang: "de")
+"Das Pferd frisst keinen Gurkensalat" war der erste jemals am 'Fernsprecher' gesagte Satz.
+
+#set text(lang: "de", region: "CH")
+"Das Pferd frisst keinen Gurkensalat" war der erste jemals am 'Fernsprecher' gesagte Satz.
+
+#set text(lang: "es", region: none)
+"El caballo no come ensalada de pepino" fue la primera frase pronunciada por 'teléfono'.
+
+#set text(lang: "es", region: "MX")
+"El caballo no come ensalada de pepino" fue la primera frase pronunciada por 'teléfono'.
+
+#set text(lang: "fr", region: none)
+"Le cheval ne mange pas de salade de concombres" est la première phrase jamais prononcée au 'téléphone'.
+
+#set text(lang: "fi")
+"Hevonen ei syö kurkkusalaattia" oli ensimmäinen koskaan 'puhelimessa' lausuttu lause.
+
+#set text(lang: "he")
+"הסוס לא אוכל סלט מלפפונים" היה המשפט ההראשון שנאמר ב 'טלפון'.
+
+#set text(lang: "ro")
+"Calul nu mănâncă salată de castraveți" a fost prima propoziție rostită vreodată la 'telefon'.
+
+#set text(lang: "ru")
+"Лошадь не ест салат из огурцов" - это была первая фраза, сказанная по 'телефону'.
+
diff --git a/test/typ/text/quotes-01.typ b/test/typ/text/quotes-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/quotes-01.typ
@@ -0,0 +1,3 @@
+// Test single pair of quotes.
+""
+
diff --git a/test/typ/text/quotes-02.typ b/test/typ/text/quotes-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/quotes-02.typ
@@ -0,0 +1,5 @@
+// Test sentences with numbers and apostrophes.
+The 5'11" 'quick' brown fox jumps over the "lazy" dog's ear.
+
+He said "I'm a big fella."
+
diff --git a/test/typ/text/quotes-03.typ b/test/typ/text/quotes-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/quotes-03.typ
@@ -0,0 +1,3 @@
+// Test escape sequences.
+The 5\'11\" 'quick\' brown fox jumps over the \"lazy" dog\'s ear.
+
diff --git a/test/typ/text/quotes-04.typ b/test/typ/text/quotes-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/quotes-04.typ
@@ -0,0 +1,6 @@
+// Test turning smart quotes off.
+He's told some books contain questionable "example text".
+
+#set smartquote(enabled: false)
+He's told some books contain questionable "example text".
+
diff --git a/test/typ/text/quotes-05.typ b/test/typ/text/quotes-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/quotes-05.typ
@@ -0,0 +1,4 @@
+// Test changing properties within text.
+"She suddenly started speaking french: #text(lang: "fr")['Je suis une banane.']" Roman told me.
+
+Some people's thought on this would be #[#set smartquote(enabled: false); "strange."]
diff --git a/test/typ/text/raw-00.typ b/test/typ/text/raw-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-00.typ
@@ -0,0 +1,3 @@
+// No extra space.
+`A``B`
+
diff --git a/test/typ/text/raw-01.typ b/test/typ/text/raw-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-01.typ
@@ -0,0 +1,4 @@
+// Typst syntax inside.
+```typ #let x = 1``` \
+```typ #f(1)```
+
diff --git a/test/typ/text/raw-02.typ b/test/typ/text/raw-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-02.typ
@@ -0,0 +1,8 @@
+// Multiline block splits paragraphs.
+
+Text
+```rust
+fn code() {}
+```
+Text
+
diff --git a/test/typ/text/raw-03.typ b/test/typ/text/raw-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-03.typ
@@ -0,0 +1,5 @@
+// Lots of backticks inside.
+````
+```backticks```
+````
+
diff --git a/test/typ/text/raw-04.typ b/test/typ/text/raw-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-04.typ
@@ -0,0 +1,12 @@
+// Trimming.
+
+// Space between "rust" and "let" is trimmed.
+The keyword ```rust let```.
+
+// Trimming depends on number backticks.
+(``) \
+(` untrimmed `) \
+(``` trimmed` ```) \
+(``` trimmed ```) \
+(``` trimmed```) \
+
diff --git a/test/typ/text/raw-05.typ b/test/typ/text/raw-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-05.typ
@@ -0,0 +1,3 @@
+// Single ticks should not have a language.
+`rust let`
+
diff --git a/test/typ/text/raw-06.typ b/test/typ/text/raw-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-06.typ
@@ -0,0 +1,6 @@
+// First line is not dedented and leading space is still possible.
+     ```   A
+        B
+       C
+     ```
+
diff --git a/test/typ/text/raw-07.typ b/test/typ/text/raw-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-07.typ
@@ -0,0 +1,4 @@
+// Text show rule
+#show raw: set text(font: "Roboto")
+`Roboto`
+
diff --git a/test/typ/text/raw-08.typ b/test/typ/text/raw-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-08.typ
@@ -0,0 +1,3 @@
+// Unterminated.
+// Error: 2:1 expected 1 backtick
+`endless
diff --git a/test/typ/text/raw-align-00.typ b/test/typ/text/raw-align-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-align-00.typ
@@ -0,0 +1,17 @@
+// Text inside raw block should be unaffected by outer alignment by default.
+#set align(center)
+#set page(width: 180pt)
+#set text(6pt)
+
+#lorem(20)
+
+```py
+def something(x):
+  return x
+
+a = 342395823859823958329
+b = 324923
+```
+
+#lorem(20)
+
diff --git a/test/typ/text/raw-align-01.typ b/test/typ/text/raw-align-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-align-01.typ
@@ -0,0 +1,13 @@
+// Text inside raw block should follow the specified alignment.
+#set page(width: 180pt)
+#set text(6pt)
+
+#lorem(20)
+#align(center, raw(
+  lang: "typ",
+  block: true,
+  align: right,
+  "#let f(x) = x\n#align(center, line(length: 1em))",
+))
+#lorem(20)
+
diff --git a/test/typ/text/raw-align-02.typ b/test/typ/text/raw-align-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-align-02.typ
@@ -0,0 +1,2 @@
+// Error: 17-20 alignment must be horizontal
+#set raw(align: top)
diff --git a/test/typ/text/raw-code-00.typ b/test/typ/text/raw-code-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-code-00.typ
@@ -0,0 +1,10 @@
+#set page(width: 180pt)
+#set text(6pt)
+```typ
+= Chapter 1
+#lorem(100)
+
+#let hi = "Hello World"
+#show heading: emph
+```
+
diff --git a/test/typ/text/raw-code-01.typ b/test/typ/text/raw-code-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-code-01.typ
@@ -0,0 +1,13 @@
+#set page(width: 180pt)
+#set text(6pt)
+
+```rust
+/// A carefully designed state machine.
+#[derive(Debug)]
+enum State<'a> { A(u8), B(&'a str) }
+
+fn advance(state: State<'_>) -> State<'_> {
+    unimplemented!("state machine")
+}
+```
+
diff --git a/test/typ/text/raw-code-02.typ b/test/typ/text/raw-code-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-code-02.typ
@@ -0,0 +1,10 @@
+#set page(width: 180pt)
+#set text(6pt)
+
+```py
+import this
+
+def hi():
+  print("Hi!")
+```
+
diff --git a/test/typ/text/raw-code-03.typ b/test/typ/text/raw-code-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-code-03.typ
@@ -0,0 +1,11 @@
+#set page(width: 180pt)
+#set text(6pt)
+
+```cpp
+#include <iostream>
+
+int main() {
+  std::cout << "Hello, world!";
+}
+```
+
diff --git a/test/typ/text/raw-code-04.typ b/test/typ/text/raw-code-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/raw-code-04.typ
@@ -0,0 +1,22 @@
+#set page(width: 180pt)
+#set text(6pt)
+
+#rect(inset: (x: 4pt, y: 5pt), radius: 4pt, fill: rgb(239, 241, 243))[
+  ```html
+  <!DOCTYPE html>
+  <html>
+    <head>
+      <meta charset="utf-8">
+    </head>
+    <body>
+      <h1>Topic</h1>
+      <p>The Hypertext Markup Language.</p>
+      <script>
+        function foo(a, b) {
+          return a + b + "string";
+        }
+      </script>
+    </body>
+  </html>
+  ```
+]
diff --git a/test/typ/text/shaping-00.typ b/test/typ/text/shaping-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/shaping-00.typ
@@ -0,0 +1,10 @@
+// Test separation by script.
+ABCअपार्टमेंट
+
+// This is how it should look like.
+अपार्टमेंट
+
+// This (without the spaces) is how it would look
+// if we didn't separate by script.
+अ पा र् ट में ट
+
diff --git a/test/typ/text/shaping-01.typ b/test/typ/text/shaping-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/shaping-01.typ
@@ -0,0 +1,4 @@
+// Test that RTL safe-to-break doesn't panic even though newline
+// doesn't exist in shaping output.
+#set text(dir: rtl, font: "Noto Serif Hebrew")
+\ ט
diff --git a/test/typ/text/shift-00.typ b/test/typ/text/shift-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/shift-00.typ
@@ -0,0 +1,7 @@
+#table(
+  columns: 3,
+  [Typo.], [Fallb.], [Synth],
+  [x#super[1]], [x#super[5n]], [x#super[2 #box(square(size: 6pt))]],
+  [x#sub[1]], [x#sub[5n]], [x#sub[2 #box(square(size: 6pt))]],
+)
+
diff --git a/test/typ/text/shift-01.typ b/test/typ/text/shift-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/shift-01.typ
@@ -0,0 +1,3 @@
+#set super(typographic: false, baseline: -0.25em, size: 0.7em)
+n#super[1], n#sub[2], ... n#super[N]
+
diff --git a/test/typ/text/shift-02.typ b/test/typ/text/shift-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/shift-02.typ
@@ -0,0 +1,4 @@
+#set underline(stroke: 0.5pt, offset: 0.15em)
+#underline[The claim#super[\[4\]]] has been disputed. \
+The claim#super[#underline[\[4\]]] has been disputed. \
+It really has been#super(box(text(baseline: 0pt, underline[\[4\]]))) \
diff --git a/test/typ/text/space-00.typ b/test/typ/text/space-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/space-00.typ
@@ -0,0 +1,14 @@
+// Spacing around code constructs.
+A#let x = 1;B  #test(x, 1) \
+C #let x = 2;D #test(x, 2) \
+E#if true [F]G \
+H #if true{"I"} J \
+K #if true [L] else []M \
+#let c = true; N#while c [#(c = false)O] P \
+#let c = true; Q #while c { c = false; "R" } S \
+T#for _ in (none,) {"U"}V
+#let foo = "A" ; \
+#foo;B \
+#foo; B \
+#foo ;B
+
diff --git a/test/typ/text/space-01.typ b/test/typ/text/space-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/space-01.typ
@@ -0,0 +1,5 @@
+// Test spacing with comments.
+A/**/B/**/C \
+A /**/ B/**/C \
+A /**/B/**/ C
+
diff --git a/test/typ/text/space-02.typ b/test/typ/text/space-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/space-02.typ
@@ -0,0 +1,3 @@
+// Test that a run consisting only of whitespace isn't trimmed.
+A#text(font: "IBM Plex Serif")[ ]B
+
diff --git a/test/typ/text/space-03.typ b/test/typ/text/space-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/space-03.typ
@@ -0,0 +1,3 @@
+// Test font change after space.
+Left #text(font: "IBM Plex Serif")[Right].
+
diff --git a/test/typ/text/space-04.typ b/test/typ/text/space-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/space-04.typ
@@ -0,0 +1,3 @@
+// Test that linebreak consumed surrounding spaces.
+#align(center)[A \ B \ C]
+
diff --git a/test/typ/text/space-05.typ b/test/typ/text/space-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/space-05.typ
@@ -0,0 +1,3 @@
+// Test that space at start of non-backslash-linebreak line isn't trimmed.
+A#"\n" B
+
diff --git a/test/typ/text/space-06.typ b/test/typ/text/space-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/space-06.typ
@@ -0,0 +1,2 @@
+// Test that trailing space does not force a line break.
+LLLLLLLLLLLLLLLLLL R _L_
diff --git a/test/typ/text/symbol-00.typ b/test/typ/text/symbol-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/symbol-00.typ
@@ -0,0 +1,12 @@
+#emoji.face
+#emoji.woman.old
+#emoji.turtle
+
+#set text(font: "New Computer Modern Math")
+#sym.arrow
+#sym.arrow.l
+#sym.arrow.r.squiggly
+#sym.arrow.tr.hook
+
+#sym.arrow.r;this and this#sym.arrow.l;
+
diff --git a/test/typ/text/symbol-01.typ b/test/typ/text/symbol-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/symbol-01.typ
@@ -0,0 +1,2 @@
+// Error: 13-20 unknown symbol modifier
+#emoji.face.garbage
diff --git a/test/typ/text/tracking-spacing-00.typ b/test/typ/text/tracking-spacing-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/tracking-spacing-00.typ
@@ -0,0 +1,4 @@
+// Test tracking.
+#set text(tracking: -0.01em)
+I saw Zoe yӛsterday, on the tram.
+
diff --git a/test/typ/text/tracking-spacing-01.typ b/test/typ/text/tracking-spacing-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/tracking-spacing-01.typ
@@ -0,0 +1,3 @@
+// Test tracking for only part of paragraph.
+I'm in#text(tracking: 0.15em + 1.5pt)[ spaace]!
+
diff --git a/test/typ/text/tracking-spacing-02.typ b/test/typ/text/tracking-spacing-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/tracking-spacing-02.typ
@@ -0,0 +1,5 @@
+// Test that tracking doesn't disrupt mark placement.
+#set text(font: ("PT Sans", "Noto Serif Hebrew"))
+#set text(tracking: 0.3em)
+טֶקסט
+
diff --git a/test/typ/text/tracking-spacing-03.typ b/test/typ/text/tracking-spacing-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/tracking-spacing-03.typ
@@ -0,0 +1,4 @@
+// Test tracking in arabic text (makes no sense whatsoever)
+#set text(tracking: 0.3em)
+النص
+
diff --git a/test/typ/text/tracking-spacing-04.typ b/test/typ/text/tracking-spacing-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/tracking-spacing-04.typ
@@ -0,0 +1,4 @@
+// Test word spacing.
+#set text(spacing: 1em)
+My text has spaces.
+
diff --git a/test/typ/text/tracking-spacing-05.typ b/test/typ/text/tracking-spacing-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/text/tracking-spacing-05.typ
@@ -0,0 +1,3 @@
+// Test word spacing relative to the font's space width.
+#set text(spacing: 50% + 1pt)
+This is tight.
diff --git a/test/typ/visualize/image-00.typ b/test/typ/visualize/image-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-00.typ
@@ -0,0 +1,9 @@
+// Test loading different image formats.
+
+// Load an RGBA PNG image.
+#image("test/assets/files/rhino.png")
+
+// Load an RGB JPEG image.
+#set page(height: 60pt)
+#image("test/assets/files/tiger.jpg")
+
diff --git a/test/typ/visualize/image-01.typ b/test/typ/visualize/image-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-01.typ
@@ -0,0 +1,12 @@
+// Test configuring the size and fitting behaviour of images.
+
+// Set width and height explicitly.
+#box(image("test/assets/files/rhino.png", width: 30pt))
+#box(image("test/assets/files/rhino.png", height: 30pt))
+
+// Set width and height explicitly and force stretching.
+#image("test/assets/files/monkey.svg", width: 100%, height: 20pt, fit: "stretch")
+
+// Make sure the bounding-box of the image is correct.
+#align(bottom + right, image("test/assets/files/tiger.jpg", width: 40pt, alt: "A tiger"))
+
diff --git a/test/typ/visualize/image-02.typ b/test/typ/visualize/image-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-02.typ
@@ -0,0 +1,11 @@
+// Test all three fit modes.
+#set page(height: 50pt, margin: 0pt)
+#grid(
+  columns: (1fr, 1fr, 1fr),
+  rows: 100%,
+  gutter: 3pt,
+  image("test/assets/files/tiger.jpg", width: 100%, height: 100%, fit: "contain"),
+  image("test/assets/files/tiger.jpg", width: 100%, height: 100%, fit: "cover"),
+  image("test/assets/files/monkey.svg", width: 100%, height: 100%, fit: "stretch"),
+)
+
diff --git a/test/typ/visualize/image-03.typ b/test/typ/visualize/image-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-03.typ
@@ -0,0 +1,5 @@
+// Does not fit to remaining height of page.
+#set page(height: 60pt)
+Stuff
+#image("test/assets/files/rhino.png")
+
diff --git a/test/typ/visualize/image-04.typ b/test/typ/visualize/image-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-04.typ
@@ -0,0 +1,3 @@
+// Test baseline.
+A #box(image("test/assets/files/tiger.jpg", height: 1cm, width: 80%)) B
+
diff --git a/test/typ/visualize/image-05.typ b/test/typ/visualize/image-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-05.typ
@@ -0,0 +1,3 @@
+// Test advanced SVG features.
+#image("test/assets/files/pattern.svg")
+
diff --git a/test/typ/visualize/image-06.typ b/test/typ/visualize/image-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-06.typ
@@ -0,0 +1,3 @@
+// Error: 8-29 file not found (searched at typ/visualize/path/does/not/exist)
+#image("path/does/not/exist")
+
diff --git a/test/typ/visualize/image-07.typ b/test/typ/visualize/image-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-07.typ
@@ -0,0 +1,3 @@
+// Error: 8-21 unknown image format
+#image("./image.typ")
+
diff --git a/test/typ/visualize/image-08.typ b/test/typ/visualize/image-08.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/image-08.typ
@@ -0,0 +1,2 @@
+// Error: 8-18 failed to parse svg: found closing tag 'g' instead of 'style' in line 4
+#image("test/assets/files/bad.svg")
diff --git a/test/typ/visualize/line-00.typ b/test/typ/visualize/line-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/line-00.typ
@@ -0,0 +1,10 @@
+#set page(height: 60pt)
+#box({
+  set line(stroke: 0.75pt)
+  place(line(end: (0.4em, 0pt)))
+  place(line(start: (0pt, 0.4em), end: (0pt, 0pt)))
+  line(end: (0.6em, 0.6em))
+}) Hello #box(line(length: 1cm))!
+
+#line(end: (70%, 50%))
+
diff --git a/test/typ/visualize/line-01.typ b/test/typ/visualize/line-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/line-01.typ
@@ -0,0 +1,28 @@
+// Test the angle argument and positioning.
+
+#set page(fill: rgb("0B1026"))
+#set line(stroke: white)
+
+#let star(size, ..args) = box(width: size, height: size)[
+  #set text(spacing: 0%)
+  #set line(..args)
+  #set align(left)
+  #v(30%)
+  #place(line(length: +30%, start: (09.0%, 02%)))
+  #place(line(length: +30%, start: (38.7%, 02%), angle: -72deg))
+  #place(line(length: +30%, start: (57.5%, 02%), angle: 252deg))
+  #place(line(length: +30%, start: (57.3%, 02%)))
+  #place(line(length: -30%, start: (88.0%, 02%), angle: -36deg))
+  #place(line(length: +30%, start: (73.3%, 48%), angle: 252deg))
+  #place(line(length: -30%, start: (73.5%, 48%), angle: 36deg))
+  #place(line(length: +30%, start: (25.4%, 48%), angle: -36deg))
+  #place(line(length: +30%, start: (25.6%, 48%), angle: -72deg))
+  #place(line(length: +32%, start: (8.50%, 02%), angle: 34deg))
+]
+
+#align(center, grid(
+  columns: 3,
+  column-gutter: 10pt,
+  ..((star(20pt, stroke: 0.5pt),) * 9)
+))
+
diff --git a/test/typ/visualize/line-02.typ b/test/typ/visualize/line-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/line-02.typ
@@ -0,0 +1,5 @@
+// Test errors.
+
+// Error: 12-19 point array must contain exactly two entries
+#line(end: (50pt,))
+
diff --git a/test/typ/visualize/line-03.typ b/test/typ/visualize/line-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/line-03.typ
@@ -0,0 +1,2 @@
+// Error: 14-26 expected relative length, found angle
+#line(start: (3deg, 10pt), length: 5cm)
diff --git a/test/typ/visualize/path-00.typ b/test/typ/visualize/path-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/path-00.typ
@@ -0,0 +1,38 @@
+#set page(height: 200pt, width: 200pt)
+#table(
+  columns: (1fr, 1fr),
+  rows: (1fr, 1fr),
+  align: center + horizon,
+  path(
+    fill: red,
+    closed: true,
+    ((0%, 0%), (4%, -4%)),
+    ((50%, 50%), (4%, -4%)),
+    ((0%, 50%), (4%, 4%)),
+    ((50%, 0%), (4%, 4%)),
+  ),
+  path(
+    fill: purple,
+    stroke: 1pt,
+    (0pt, 0pt),
+    (30pt, 30pt),
+    (0pt, 30pt),
+    (30pt, 0pt),
+  ),
+  path(
+    fill: blue,
+    stroke: 1pt,
+    closed: true,
+    ((30%, 0%), (35%, 30%), (-20%, 0%)),
+    ((30%, 60%), (-20%, 0%), (0%, 0%)),
+    ((50%, 30%), (60%, -30%), (60%, 0%)),
+  ),
+  path(
+    stroke: 5pt,
+    closed: true,
+    (0pt,  30pt),
+    (30pt, 30pt),
+    (15pt, 0pt),
+  ),
+)
+
diff --git a/test/typ/visualize/path-01.typ b/test/typ/visualize/path-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/path-01.typ
@@ -0,0 +1,3 @@
+// Error: 7-9 path vertex must have 1, 2, or 3 points
+#path(())
+
diff --git a/test/typ/visualize/path-02.typ b/test/typ/visualize/path-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/path-02.typ
@@ -0,0 +1,3 @@
+// Error: 7-47 path vertex must have 1, 2, or 3 points
+#path(((0%, 0%), (0%, 0%), (0%, 0%), (0%, 0%)))
+
diff --git a/test/typ/visualize/path-03.typ b/test/typ/visualize/path-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/path-03.typ
@@ -0,0 +1,2 @@
+// Error: 7-31 point array must contain exactly two entries
+#path(((0%, 0%), (0%, 0%, 0%)))
diff --git a/test/typ/visualize/polygon-00.typ b/test/typ/visualize/polygon-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/polygon-00.typ
@@ -0,0 +1,26 @@
+#set page(width: 50pt)
+#set polygon(stroke: 0.75pt, fill: blue)
+
+// These are not visible, but should also not give an error
+#polygon()
+#polygon((0em, 0pt))
+#polygon((0pt, 0pt), (10pt, 0pt))
+
+#polygon((5pt, 0pt), (0pt, 10pt), (10pt, 10pt))
+#polygon(
+  (0pt, 0pt), (5pt, 5pt), (10pt, 0pt),
+  (15pt, 5pt),
+  (5pt, 10pt)
+)
+#polygon(stroke: none, (5pt, 0pt), (0pt, 10pt), (10pt, 10pt))
+#polygon(stroke: 3pt, fill: none, (5pt, 0pt), (0pt, 10pt), (10pt, 10pt))
+
+// Relative size
+#polygon((0pt, 0pt), (100%, 5pt), (50%, 10pt))
+
+// Antiparallelogram
+#polygon((0pt, 5pt), (5pt, 0pt), (0pt, 10pt), (5pt, 15pt))
+
+// Self-intersections
+#polygon((0pt, 10pt), (30pt, 20pt), (0pt, 30pt), (20pt, 0pt), (20pt, 35pt))
+
diff --git a/test/typ/visualize/polygon-01.typ b/test/typ/visualize/polygon-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/polygon-01.typ
@@ -0,0 +1,2 @@
+// Error: 10-17 point array must contain exactly two entries
+#polygon((50pt,))
diff --git a/test/typ/visualize/shape-aspect-00.typ b/test/typ/visualize/shape-aspect-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-aspect-00.typ
@@ -0,0 +1,16 @@
+// Test relative width and height and size that is smaller
+// than default size.
+#set page(width: 120pt, height: 70pt)
+#set align(bottom)
+#let centered = align.with(center + horizon)
+#stack(
+  dir: ltr,
+  spacing: 1fr,
+  square(width: 50%, centered[A]),
+  square(height: 50%),
+  stack(
+    square(size: 10pt),
+    square(size: 20pt, centered[B])
+  ),
+)
+
diff --git a/test/typ/visualize/shape-aspect-01.typ b/test/typ/visualize/shape-aspect-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-aspect-01.typ
@@ -0,0 +1,7 @@
+// Test alignment in automatically sized square and circle.
+#set text(8pt)
+#box(square(inset: 4pt)[
+  Hey there, #align(center + bottom, rotate(180deg, [you!]))
+])
+#box(circle(align(center + horizon, [Hey.])))
+
diff --git a/test/typ/visualize/shape-aspect-02.typ b/test/typ/visualize/shape-aspect-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-aspect-02.typ
@@ -0,0 +1,8 @@
+// Test that minimum wins if both width and height are given.
+#stack(
+  dir: ltr,
+  spacing: 2pt,
+  square(width: 20pt, height: 40pt),
+  circle(width: 20%, height: 100pt),
+)
+
diff --git a/test/typ/visualize/shape-aspect-03.typ b/test/typ/visualize/shape-aspect-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-aspect-03.typ
@@ -0,0 +1,4 @@
+// Test square that is limited by region size.
+#set page(width: 20pt, height: 10pt, margin: 0pt)
+#stack(dir: ltr, square(fill: red), square(fill: green))
+
diff --git a/test/typ/visualize/shape-aspect-04.typ b/test/typ/visualize/shape-aspect-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-aspect-04.typ
@@ -0,0 +1,10 @@
+// Test different ways of sizing.
+#set page(width: 120pt, height: 40pt)
+#stack(
+  dir: ltr,
+  spacing: 2pt,
+  circle(radius: 5pt),
+  circle(width: 10%),
+  circle(height: 50%),
+)
+
diff --git a/test/typ/visualize/shape-aspect-05.typ b/test/typ/visualize/shape-aspect-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-aspect-05.typ
@@ -0,0 +1,5 @@
+// Test that square doesn't overflow due to its aspect ratio.
+#set page(width: 40pt, height: 25pt, margin: 5pt)
+#square(width: 100%)
+#square(width: 100%)[Hello there]
+
diff --git a/test/typ/visualize/shape-aspect-06.typ b/test/typ/visualize/shape-aspect-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-aspect-06.typ
@@ -0,0 +1,4 @@
+// Size cannot be relative because we wouldn't know
+// relative to which axis.
+// Error: 15-18 expected length or auto, found ratio
+#square(size: 50%)
diff --git a/test/typ/visualize/shape-circle-00.typ b/test/typ/visualize/shape-circle-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-circle-00.typ
@@ -0,0 +1,4 @@
+// Default circle.
+#box(circle())
+#box(circle[Hey])
+
diff --git a/test/typ/visualize/shape-circle-01.typ b/test/typ/visualize/shape-circle-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-circle-01.typ
@@ -0,0 +1,26 @@
+// Test auto sizing.
+#set circle(inset: 0pt)
+
+Auto-sized circle.
+#circle(fill: rgb("eb5278"), stroke: 2pt + black,
+  align(center + horizon)[But, soft!]
+)
+
+Center-aligned rect in auto-sized circle.
+#circle(fill: red, stroke: green,
+  align(center + horizon,
+    rect(fill: green, inset: 5pt)[But, soft!]
+  )
+)
+
+Rect in auto-sized circle.
+#circle(fill: red,
+  rect(fill: green, stroke: white, inset: 4pt)[
+    #set text(8pt)
+    But, soft! what light through yonder window breaks?
+  ]
+)
+
+Expanded by height.
+#circle(stroke: black, align(center)[A \ B \ C])
+
diff --git a/test/typ/visualize/shape-circle-02.typ b/test/typ/visualize/shape-circle-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-circle-02.typ
@@ -0,0 +1,4 @@
+// Ensure circle directly in rect works.
+#rect(width: 40pt, height: 30pt, fill: red,
+  circle(fill: green))
+
diff --git a/test/typ/visualize/shape-circle-03.typ b/test/typ/visualize/shape-circle-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-circle-03.typ
@@ -0,0 +1,14 @@
+// Test relative sizing.
+#set text(fill: white)
+#show: rect.with(width: 100pt, height: 50pt, inset: 0pt, fill: rgb("aaa"))
+#set align(center + horizon)
+#stack(
+  dir: ltr,
+  spacing: 1fr,
+  1fr,
+  circle(radius: 10pt, fill: eastern, [A]),      // D=20pt
+  circle(height: 60%, fill: eastern, [B]),       // D=30pt
+  circle(width: 20% + 20pt, fill: eastern, [C]), // D=40pt
+  1fr,
+)
+
diff --git a/test/typ/visualize/shape-circle-04.typ b/test/typ/visualize/shape-circle-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-circle-04.typ
@@ -0,0 +1,3 @@
+// Radius wins over width and height.
+// Error: 23-34 unexpected argument: width
+#circle(radius: 10pt, width: 50pt, height: 100pt, fill: eastern)
diff --git a/test/typ/visualize/shape-ellipse-00.typ b/test/typ/visualize/shape-ellipse-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-ellipse-00.typ
@@ -0,0 +1,3 @@
+// Default ellipse.
+#ellipse()
+
diff --git a/test/typ/visualize/shape-ellipse-01.typ b/test/typ/visualize/shape-ellipse-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-ellipse-01.typ
@@ -0,0 +1,24 @@
+#set rect(inset: 0pt)
+#set ellipse(inset: 0pt)
+
+Rect in ellipse in fixed rect.
+#rect(width: 3cm, height: 2cm, fill: rgb("2a631a"),
+  ellipse(fill: red, width: 100%, height: 100%,
+    rect(fill: green, width: 100%, height: 100%,
+      align(center + horizon)[
+        Stuff inside an ellipse!
+      ]
+    )
+  )
+)
+
+Auto-sized ellipse.
+#ellipse(fill: green, stroke: 3pt + red, inset: 3pt)[
+  #set text(8pt)
+  But, soft! what light through yonder window breaks?
+]
+
+
+An inline
+#box(ellipse(width: 8pt, height: 6pt, outset: (top: 3pt, rest: 5.5pt)))
+ellipse.
diff --git a/test/typ/visualize/shape-fill-stroke-00.typ b/test/typ/visualize/shape-fill-stroke-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-fill-stroke-00.typ
@@ -0,0 +1,24 @@
+#let variant = rect.with(width: 20pt, height: 10pt)
+#let items = for (i, item) in (
+  variant(stroke: none),
+  variant(),
+  variant(fill: none),
+  variant(stroke: 2pt),
+  variant(stroke: eastern),
+  variant(stroke: eastern + 2pt),
+  variant(fill: eastern),
+  variant(fill: eastern, stroke: none),
+  variant(fill: red, stroke: none),
+  variant(fill: red, stroke: green),
+  variant(fill: red, stroke: black + 2pt),
+  variant(fill: red, stroke: green + 2pt),
+).enumerate() {
+  (align(horizon)[#(i + 1).], item, [])
+}
+
+#grid(
+  columns: (auto, auto, 1fr, auto, auto, 0fr),
+  gutter: 5pt,
+  ..items,
+)
+
diff --git a/test/typ/visualize/shape-fill-stroke-01.typ b/test/typ/visualize/shape-fill-stroke-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-fill-stroke-01.typ
@@ -0,0 +1,13 @@
+// Test stroke folding.
+#let sq(..args) = box(square(size: 10pt, ..args))
+
+#set square(stroke: none)
+#sq()
+#set square(stroke: auto)
+#sq()
+#sq(fill: teal)
+#sq(stroke: 2pt)
+#sq(stroke: blue)
+#sq(fill: teal, stroke: blue)
+#sq(fill: teal, stroke: 2pt + blue)
+
diff --git a/test/typ/visualize/shape-fill-stroke-02.typ b/test/typ/visualize/shape-fill-stroke-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-fill-stroke-02.typ
@@ -0,0 +1,8 @@
+// Test stroke composition.
+#set square(stroke: 4pt)
+#set text(font: "Roboto")
+#square(
+  stroke: (left: red, top: yellow, right: green, bottom: blue),
+  radius: 100%, align(center+horizon)[*G*],
+  inset: 8pt
+)
diff --git a/test/typ/visualize/shape-rect-00.typ b/test/typ/visualize/shape-rect-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-rect-00.typ
@@ -0,0 +1,3 @@
+// Default rectangle.
+#rect()
+
diff --git a/test/typ/visualize/shape-rect-01.typ b/test/typ/visualize/shape-rect-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-rect-01.typ
@@ -0,0 +1,41 @@
+#set page(width: 150pt)
+
+// Fit to text.
+#rect(fill: green)[Textbox]
+
+// Empty with fixed width and height.
+#block(rect(
+  height: 15pt,
+  fill: rgb("46b3c2"),
+  stroke: 2pt + rgb("234994"),
+))
+
+// Fixed width, text height.
+#rect(width: 2cm, fill: rgb("9650d6"))[Fixed and padded]
+
+// Page width, fixed height.
+#rect(height: 1cm, width: 100%, fill: rgb("734ced"))[Topleft]
+
+// These are inline with text.
+{#box(rect(width: 0.5in, height: 7pt, fill: rgb("d6cd67")))
+ #box(rect(width: 0.5in, height: 7pt, fill: rgb("edd466")))
+ #box(rect(width: 0.5in, height: 7pt, fill: rgb("e3be62")))}
+
+// Rounded corners.
+#stack(
+  dir: ltr,
+  spacing: 1fr,
+  rect(width: 2cm, radius: 60%),
+  rect(width: 1cm, radius: (left: 10pt, right: 5pt)),
+  rect(width: 1.25cm, radius: (
+    top-left: 2pt,
+    top-right: 5pt,
+    bottom-right: 8pt,
+    bottom-left: 11pt
+  )),
+)
+
+// Different strokes.
+#set rect(stroke: (right: red))
+#rect(width: 100%, fill: lime, stroke: (x: 5pt, y: 1pt))
+
diff --git a/test/typ/visualize/shape-rect-02.typ b/test/typ/visualize/shape-rect-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-rect-02.typ
@@ -0,0 +1,3 @@
+// Error: 15-38 unexpected key "cake", valid keys are "top-left", "top-right", "bottom-right", "bottom-left", "left", "top", "right", "bottom", and "rest"
+#rect(radius: (left: 10pt, cake: 5pt))
+
diff --git a/test/typ/visualize/shape-rect-03.typ b/test/typ/visualize/shape-rect-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-rect-03.typ
@@ -0,0 +1,2 @@
+// Error: 15-21 expected length, color, dictionary, stroke, none, or auto, found array
+#rect(stroke: (1, 2))
diff --git a/test/typ/visualize/shape-rounded-00.typ b/test/typ/visualize/shape-rounded-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-rounded-00.typ
@@ -0,0 +1,3 @@
+// Ensure that radius is clamped.
+#rect(radius: -20pt)
+#square(radius: 30pt)
diff --git a/test/typ/visualize/shape-square-00.typ b/test/typ/visualize/shape-square-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-square-00.typ
@@ -0,0 +1,4 @@
+// Default square.
+#box(square())
+#box(square[hey!])
+
diff --git a/test/typ/visualize/shape-square-01.typ b/test/typ/visualize/shape-square-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-square-01.typ
@@ -0,0 +1,6 @@
+// Test auto-sized square.
+#square(fill: eastern)[
+  #set text(fill: white, weight: "bold")
+  Typst
+]
+
diff --git a/test/typ/visualize/shape-square-02.typ b/test/typ/visualize/shape-square-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-square-02.typ
@@ -0,0 +1,6 @@
+// Test relative-sized child.
+#square(fill: eastern)[
+  #rect(width: 10pt, height: 5pt, fill: green)
+  #rect(width: 40%, height: 5pt, stroke: green)
+]
+
diff --git a/test/typ/visualize/shape-square-03.typ b/test/typ/visualize/shape-square-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-square-03.typ
@@ -0,0 +1,6 @@
+// Test text overflowing height.
+#set page(width: 75pt, height: 100pt)
+#square(fill: green)[
+  But, soft! what light through yonder window breaks?
+]
+
diff --git a/test/typ/visualize/shape-square-04.typ b/test/typ/visualize/shape-square-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-square-04.typ
@@ -0,0 +1,6 @@
+// Test that square does not overflow page.
+#set page(width: 100pt, height: 75pt)
+#square(fill: green)[
+  But, soft! what light through yonder window breaks?
+]
+
diff --git a/test/typ/visualize/shape-square-05.typ b/test/typ/visualize/shape-square-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/shape-square-05.typ
@@ -0,0 +1,3 @@
+// Size wins over width and height.
+// Error: 09-20 unexpected argument: width
+#square(width: 10cm, height: 20cm, size: 1cm, fill: rgb("eb5278"))
diff --git a/test/typ/visualize/stroke-00.typ b/test/typ/visualize/stroke-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-00.typ
@@ -0,0 +1,11 @@
+// Some simple test lines
+#line(length: 60pt, stroke: red)
+#v(3pt)
+#line(length: 60pt, stroke: 2pt)
+#v(3pt)
+#line(length: 60pt, stroke: blue + 1.5pt)
+#v(3pt)
+#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: "dashed"))
+#v(3pt)
+#line(length: 60pt, stroke: (paint: red, thickness: 4pt, cap: "round"))
+
diff --git a/test/typ/visualize/stroke-01.typ b/test/typ/visualize/stroke-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-01.typ
@@ -0,0 +1,8 @@
+// Set rules with stroke
+#set line(stroke: (paint: red, thickness: 1pt, cap: "butt", dash: "dash-dotted"))
+#line(length: 60pt)
+#v(3pt)
+#line(length: 60pt, stroke: blue)
+#v(3pt)
+#line(length: 60pt, stroke: (dash: none))
+
diff --git a/test/typ/visualize/stroke-02.typ b/test/typ/visualize/stroke-02.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-02.typ
@@ -0,0 +1,7 @@
+// Rectangle strokes
+#rect(width: 20pt, height: 20pt, stroke: red)
+#v(3pt)
+#rect(width: 20pt, height: 20pt, stroke: (rest: red, top: (paint: blue, dash: "dashed")))
+#v(3pt)
+#rect(width: 20pt, height: 20pt, stroke: (thickness: 5pt, join: "round"))
+
diff --git a/test/typ/visualize/stroke-03.typ b/test/typ/visualize/stroke-03.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-03.typ
@@ -0,0 +1,11 @@
+// Dashing
+#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: ("dot", 1pt)))
+#v(3pt)
+#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: ("dot", 1pt, 4pt, 2pt)))
+#v(3pt)
+#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: (array: ("dot", 1pt, 4pt, 2pt), phase: 5pt)))
+#v(3pt)
+#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: ()))
+#v(3pt)
+#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: (1pt, 3pt, 9pt)))
+
diff --git a/test/typ/visualize/stroke-04.typ b/test/typ/visualize/stroke-04.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-04.typ
@@ -0,0 +1,13 @@
+// Line joins
+#stack(
+  dir: ltr,
+  spacing: 1em,
+  polygon(stroke: (thickness: 4pt, paint: blue, join: "round"),
+    (0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
+  polygon(stroke: (thickness: 4pt, paint: blue, join: "bevel"),
+    (0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
+  polygon(stroke: (thickness: 4pt, paint: blue, join: "miter"),
+    (0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
+  polygon(stroke: (thickness: 4pt, paint: blue, join: "miter", miter-limit: 20.0),
+    (0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
+)
diff --git a/test/typ/visualize/stroke-05.typ b/test/typ/visualize/stroke-05.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-05.typ
@@ -0,0 +1,4 @@
+
+// Error: 29-56 unexpected key "thicknes", valid keys are "paint", "thickness", "cap", "join", "dash", and "miter-limit"
+#line(length: 60pt, stroke: (paint: red, thicknes: 1pt))
+
diff --git a/test/typ/visualize/stroke-06.typ b/test/typ/visualize/stroke-06.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-06.typ
@@ -0,0 +1,4 @@
+
+// Error: 29-55 expected "solid", "dotted", "densely-dotted", "loosely-dotted", "dashed", "densely-dashed", "loosely-dashed", "dash-dotted", "densely-dash-dotted", "loosely-dash-dotted", array, dictionary, dash pattern, or none
+#line(length: 60pt, stroke: (paint: red, dash: "dash"))
+
diff --git a/test/typ/visualize/stroke-07.typ b/test/typ/visualize/stroke-07.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/stroke-07.typ
@@ -0,0 +1,32 @@
+// 0pt strokes must function exactly like 'none' strokes and not draw anything
+
+#rect(width: 10pt, height: 10pt, stroke: none)
+#rect(width: 10pt, height: 10pt, stroke: 0pt)
+#rect(width: 10pt, height: 10pt, stroke: none, fill: blue)
+#rect(width: 10pt, height: 10pt, stroke: 0pt + red, fill: blue)
+
+#line(length: 30pt, stroke: 0pt)
+#line(length: 30pt, stroke: (paint: red, thickness: 0pt, dash: ("dot", 1pt)))
+
+#table(columns: 2, stroke: none)[A][B]
+#table(columns: 2, stroke: 0pt)[A][B]
+
+#path(
+  fill: red,
+  stroke: none,
+  closed: true,
+  ((0%, 0%), (4%, -4%)),
+  ((50%, 50%), (4%, -4%)),
+  ((0%, 50%), (4%, 4%)),
+  ((50%, 0%), (4%, 4%)),
+)
+
+#path(
+  fill: red,
+  stroke: 0pt,
+  closed: true,
+  ((0%, 0%), (4%, -4%)),
+  ((50%, 50%), (4%, -4%)),
+  ((0%, 50%), (4%, 4%)),
+  ((50%, 0%), (4%, 4%)),
+)
diff --git a/test/typ/visualize/svg-text-00.typ b/test/typ/visualize/svg-text-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/svg-text-00.typ
@@ -0,0 +1,6 @@
+#set page(width: 250pt)
+
+#figure(
+  image("test/assets/files/diagram.svg"),
+  caption: [A textful diagram],
+)
diff --git a/typst.cabal b/typst.cabal
new file mode 100644
--- /dev/null
+++ b/typst.cabal
@@ -0,0 +1,117 @@
+cabal-version:      2.4
+name:               typst
+version:            0.1.0.0
+synopsis:           Parsing and evaluating typst syntax.
+description:        A library for parsing and evaluating typst syntax.
+                    Typst (<https://typst.app>) is a document layout and
+                    formatting language. This library targets typst 0.4
+                    and currently offers only partial support.
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             John MacFarlane
+maintainer:         jgm@berkeley.edu
+copyright:          Copyright 2023 John MacFarlane
+category:           Text
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+extra-source-files: test/typ/**/*.typ
+                    test/out/**/*.out
+                    test/assets/files/*.png
+                    test/assets/files/*.jpg
+                    test/assets/files/*.bib
+                    test/assets/files/*.csv
+                    test/assets/files/*.json
+                    test/assets/files/*.svg
+                    test/assets/files/*.toml
+                    test/assets/files/*.xml
+                    test/assets/files/*.txt
+                    test/assets/files/*.yaml
+                    test/assets/files/*.html
+tested-with:        GHC == 8.10.7 || == 9.0.2 || == 9.2.7 || == 9.4.5 || == 9.6.2
+
+source-repository head
+  type: git
+  location: https://github.com/jgm/typst-hs.git
+
+common warnings
+    ghc-options: -Wall
+
+library
+    import:           warnings
+    exposed-modules:  Typst
+                      Typst.Syntax
+                      Typst.Parse
+                      Typst.Types
+                      Typst.Evaluate
+                      Typst.Methods
+                      Typst.Util
+    other-modules:
+                      Typst.Bind
+                      Typst.Regex
+                      Typst.Show
+                      Typst.Module.Standard
+                      Typst.Module.Math
+                      Typst.Module.Calc
+
+    -- other-extensions:
+    build-depends:    base >= 4.14 && <= 5,
+                      typst-symbols >= 0.1 && < 0.2,
+                      mtl,
+                      vector,
+                      parsec,
+                      filepath,
+                      containers,
+                      ordered-containers,
+                      text,
+                      bytestring,
+                      cassava,
+                      aeson,
+                      scientific,
+                      xml-conduit,
+                      yaml,
+                      regex-tdfa,
+                      array,
+                      pretty
+    hs-source-dirs:   src
+    default-language: Haskell2010
+
+Flag executable
+  description:       Compile executable to be used in testing and development.
+  default:           False
+
+executable typst-hs
+    import:           warnings
+    main-is:          Main.hs
+    hs-source-dirs:   app
+    default-language: Haskell2010
+    if flag(executable)
+      Buildable:         True
+      Build-depends:
+        base,
+        typst,
+        parsec,
+        mtl,
+        vector,
+        containers,
+        text,
+        bytestring,
+        pretty-show,
+        ordered-containers
+    else
+      Buildable:         False
+
+test-suite typst-test
+    import:           warnings
+    default-language: Haskell2010
+    type:             exitcode-stdio-1.0
+    hs-source-dirs:   test
+    main-is:          Main.hs
+    build-depends:
+        base,
+        typst,
+        text,
+        bytestring,
+        filepath,
+        pretty-show,
+        tasty,
+        tasty-golden
