diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,41 @@
 # Revision history for typst-hs
 
+## 0.11
+
+  * Fall back on defaults for settable element fields (#100).
+    In typst, settable fields like list.marker are materialized when
+    an element is passed to a show rule, so e.g. `it.marker` works in
+    `#show list: it => ..` even when no explicit marker was given.
+    Previously such accesses caused an evaluation failure in typst-hs
+    (e.g. with the cheq package).
+
+  * flake.nix: also ensure presence of typst compiler, for testing.
+
+  * Support for typst 0.15 features:
+
+    + Switch to typst-symbols 0.3 (typst 0.15 symbols).
+    + Add `calc.asinh`, `calc.acosh`, `calc.atanh`, and `calc.erf`.
+        This adds a dependency on the erf package.
+    + Add `inclusive` parameter to `range`.
+    + Add `map` and `filter` methods on dictionaries and arguments.
+    + Support `base` parameter in the `int` constructor, and add
+      `int.min` and `int.max`. Field access on a type now falls back to
+      the type's scope, which also makes `str.to-unicode` and
+      `str.from-unicode` accessible.
+    + Make delimiter symbols (e.g. `chevron.l`) callable in math mode to
+      produce an `lr` element.
+    + Add `html` module, with `html.elem`, `html.frame`, and the typed
+      HTML element functions (`html.div`, `html.span`, etc.).
+    + Add the `path` type [API change: adds `VPath` to `Val` and `TPath`
+      to `ValType`]. Relative paths are resolved at construction time,
+      relative to the constructing file. Paths are accepted wherever
+      file-path strings are accepted (`read`, `csv`, `json`, `image`,
+      `bibliography`, etc.); in element fields they are coerced to
+      strings. The deprecated `path` visualize element is removed.
+    + Add `curve` element (the replacement for the removed `path`
+      element), with its `curve.move`, `curve.line`, `curve.quad`,
+      `curve.cubic`, and `curve.close` functions.
+
 ## 0.10
 
   * Add --input option to cli for passing key-value pairs to the
diff --git a/src/Typst/Constructors.hs b/src/Typst/Constructors.hs
--- a/src/Typst/Constructors.hs
+++ b/src/Typst/Constructors.hs
@@ -24,15 +24,31 @@
 import qualified Data.Text.Encoding as TE
 import Typst.Regex (makeRE)
 import Data.List (genericTake)
-import Control.Monad.Reader (asks)
+import Control.Monad.Reader (asks, lift)
+import Typst.Module.Standard (getPath)
 import Control.Monad (mplus)
-import Data.Char (ord, chr)
+import Data.Char (ord, chr, isDigit, isAsciiLower, isAsciiUpper)
 
 getConstructor :: ValType -> Maybe Val
 getConstructor typ =
   case typ of
     TFloat -> Just $ makeFunction $ VFloat <$> nthArg 1
-    TInteger -> Just $ makeFunction $ VInteger <$> nthArg 1
+    TInteger -> Just $ makeFunctionWithScope
+      (do
+        val <- nthArg 1
+        (base :: Integer) <- namedArg "base" 10
+        case val of
+          _ | base == 10 -> VInteger <$> fromVal val
+          VString s
+            | base >= 2 && base <= 36 ->
+                maybe (fail "invalid digits for the given base")
+                      (pure . VInteger)
+                      (parseInBase base s)
+            | otherwise -> fail "base must be between 2 and 36"
+          _ -> fail "base is only supported when parsing strings")
+      [ ("min", VInteger (-9223372036854775808)),  -- i64 bounds, as in typst
+        ("max", VInteger 9223372036854775807)
+      ]
     TRegex -> Just $ makeFunction $ VRegex <$> (nthArg 1 >>= makeRE)
     TVersion -> Just $ makeFunction $ VVersion <$> (asks positional >>= mapM fromVal)
     TString -> Just $ makeFunctionWithScope
@@ -99,6 +115,15 @@
       case a of
         VModule _ m -> pure $ VDict $ OM.fromList $ M.toList m
         _ -> fail "dictionary constructor requires a module as argument"
+    TPath -> Just $ makeFunction $ do
+      v <- nthArg 1
+      case v of
+        -- paths are returned unchanged
+        VPath _ -> pure v
+        -- relative paths are resolved at construction time,
+        -- relative to the constructing file
+        VString fp -> VPath <$> lift (getPath (T.unpack fp))
+        _ -> fail "expected string or path"
     TBytes -> Just $ makeFunction $ do
       x <- nthArg 1
       let extractWord8 (VInteger w) = Just $ fromIntegral w
@@ -115,6 +140,29 @@
     -- TODO https://typst.app/docs/reference/introspection/counter/
     _ -> Nothing
 
+
+-- | Parse an integer (with optional sign) in the given base (2-36).
+parseInBase :: Integer -> Text -> Maybe Integer
+parseInBase base t =
+  case T.uncons t of
+    Just ('-', rest) -> negate <$> go rest
+    Just ('+', rest) -> go rest
+    _ -> go t
+  where
+    go s
+      | T.null s = Nothing
+      | otherwise = T.foldl' step (Just 0) s
+    step macc c = do
+      acc <- macc
+      d <- digitVal c
+      if d < base
+        then Just (acc * base + d)
+        else Nothing
+    digitVal c
+      | isDigit c = Just $ fromIntegral (ord c - ord '0')
+      | isAsciiLower c = Just $ fromIntegral (ord c - ord 'a' + 10)
+      | isAsciiUpper c = Just $ fromIntegral (ord c - ord 'A' + 10)
+      | otherwise = Nothing
 
 -- mDigitsRev, mDigits from the unmaintained digits package
 -- https://hackage.haskell.org/package/digits-0.3.1
diff --git a/src/Typst/Evaluate.hs b/src/Typst/Evaluate.hs
--- a/src/Typst/Evaluate.hs
+++ b/src/Typst/Evaluate.hs
@@ -35,7 +35,8 @@
 import Typst.Bind (destructuringBind, doBind)
 import Typst.Constructors (getConstructor)
 import Typst.Methods (getMethod)
-import Typst.Module.Standard (loadFileText, standardModule, symModule, getPath)
+import Typst.Module.Standard (loadFileText, standardModule, symModule, getPath,
+                              elementDefaults)
 import Typst.Module.Math (mathModule)
 import Typst.MathClass (mathClassOf, MathClass(Relation))
 import Typst.Parse (parseTypst)
@@ -203,6 +204,32 @@
 single :: Content -> Seq Content
 single = Seq.singleton
 
+-- | Opening delimiters that, when called as functions in math mode,
+-- produce an lr element with the matching closing delimiter.
+matchedDelimiters :: M.Map Text Text
+matchedDelimiters =
+  M.fromList
+    [ ("(", ")"),
+      ("[", "]"),
+      ("{", "}"),
+      ("⟨", "⟩"),
+      ("⟪", "⟫"),
+      ("⟦", "⟧"),
+      ("⟮", "⟯"),
+      ("⌈", "⌉"),
+      ("⌊", "⌋"),
+      ("⌜", "⌝"),
+      ("⌞", "⌟"),
+      ("|", "|"),
+      ("‖", "‖"),
+      ("⧘", "⧙"),
+      ("⧚", "⧛"),
+      ("⦃", "⦄"),
+      ("⦅", "⦆"),
+      ("〔", "〕"),
+      ("❲", "❳")
+    ]
+
 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:
@@ -577,10 +604,23 @@
             case M.lookup (Identifier fld) m of
               Just x -> pure x
               Nothing -> fail $ "Function scope does not contain " <> show fld
+          VType ty ->
+            case getConstructor ty of
+              Just (VFunction _ m _)
+                | Just x <- M.lookup (Identifier fld) m -> pure x
+              _ -> fail $ "Type " <> show ty <> " 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"
+          -- fall back on default values for settable element fields,
+          -- e.g. it.marker in #show list: it => .. (see #100)
+          VContent cs
+            | [Elt eltname _ _] <- toList cs,
+              Just v <-
+                M.lookup eltname elementDefaults
+                  >>= M.lookup (Identifier fld) ->
+                pure v
           _ -> fail "FieldAccess requires a dictionary"
     FieldAccess _ _ -> fail "FieldAccess requires an identifier"
     FuncCall e args -> do
@@ -604,6 +644,26 @@
                 toArguments args
                   >>= f . (\a -> a {positional = positional a ++ [val]})
               _ -> fail "accent not defined"
+        -- delimiter symbols are callable and produce an lr element
+        -- (typst 0.15)
+        VSymbol (Symbol t False _)
+          | mathMode,
+            Just closer <- M.lookup t matchedDelimiters -> do
+              val' <- lookupIdentifier "lr"
+              case val' of
+                VFunction _ _ (Function f) -> do
+                  args' <- toArguments args
+                  let body =
+                        VContent $
+                          single (Txt t)
+                            <> mconcat
+                              ( intersperse
+                                  (single ",")
+                                  (map valToContent (positional args'))
+                              )
+                            <> single (Txt closer)
+                  f Arguments {positional = [body], named = OM.empty}
+                _ -> fail "lr not defined"
         _
           | mathMode -> do
               args' <- toArguments args
diff --git a/src/Typst/Methods.hs b/src/Typst/Methods.hs
--- a/src/Typst/Methods.hs
+++ b/src/Typst/Methods.hs
@@ -12,7 +12,7 @@
   )
 where
 
-import Control.Monad (MonadPlus (mplus), foldM, void)
+import Control.Monad (MonadPlus (mplus), filterM, foldM, void)
 import Control.Monad.Reader (MonadReader (ask), MonadTrans (lift))
 import qualified Data.Array as Array
 import qualified Data.Foldable as F
@@ -105,6 +105,22 @@
               Just oldval -> do
                 lift $ updateVal $ VDict $ OM.delete (Identifier key) m
                 pure oldval
+        "map" ->
+          pure $ makeFunction $ do
+            Function fn <- nthArg 1
+            let f (k, v) =
+                  (,) k
+                    <$> lift (fn Arguments {positional = [v], named = OM.empty})
+            VDict . OM.fromList <$> mapM f (OM.assocs m)
+        "filter" ->
+          pure $ makeFunction $ do
+            Function fn <- nthArg 1
+            let predicate (_, v) = do
+                  res <- lift $ fn Arguments {positional = [v], named = OM.empty}
+                  case res of
+                    VBoolean b -> pure b
+                    _ -> fail "function does not return a boolean"
+            VDict . OM.fromList <$> filterM predicate (OM.assocs m)
         _ -> case OM.lookup (Identifier fld) m of
           Just x -> pure x
           Nothing -> fail $ show (Identifier fld) <> " not found"
@@ -679,6 +695,28 @@
                   Nothing -> pure defval
               _ -> pure defval
         "named" -> pure $ makeFunction $ pure $ VDict $ named args
+        "map" ->
+          pure $ makeFunction $ do
+            Function fn <- nthArg 1
+            let f v = lift $ fn Arguments {positional = [v], named = OM.empty}
+            pos' <- mapM f (positional args)
+            named' <-
+              OM.fromList
+                <$> mapM (\(k, v) -> (,) k <$> f v) (OM.assocs (named args))
+            pure $ VArguments $ Arguments pos' named'
+        "filter" ->
+          pure $ makeFunction $ do
+            Function fn <- nthArg 1
+            let predicate v = do
+                  res <- lift $ fn Arguments {positional = [v], named = OM.empty}
+                  case res of
+                    VBoolean b -> pure b
+                    _ -> fail "function does not return a boolean"
+            pos' <- filterM predicate (positional args)
+            named' <-
+              OM.fromList
+                <$> filterM (predicate . snd) (OM.assocs (named args))
+            pure $ VArguments $ Arguments pos' named'
         _ -> noMethod "Arguments" fld
     VDateTime mbdate mbtime -> do
       let toSeconds = (floor :: Double -> Integer) . realToFrac
diff --git a/src/Typst/Module/Calc.hs b/src/Typst/Module/Calc.hs
--- a/src/Typst/Module/Calc.hs
+++ b/src/Typst/Module/Calc.hs
@@ -8,6 +8,7 @@
 
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe, mapMaybe)
+import Data.Number.Erf (erf)
 import Typst.Types
 import Typst.Util
 
@@ -202,6 +203,22 @@
       ("asin", makeFunction $ VAngle . asin <$> nthArg 1),
       ("atan", makeFunction $ VAngle . atan <$> nthArg 1),
       ("atan2", makeFunction $ VAngle <$> (atan2 <$> nthArg 1 <*> nthArg 2)),
+      ("asinh", makeFunction $ VFloat . asinh <$> nthArg 1),
+      ( "acosh",
+        makeFunction $ do
+          (x :: Double) <- nthArg 1
+          if x < 1
+            then fail "value must be greater than or equal to 1"
+            else pure $ VFloat $ acosh x
+      ),
+      ( "atanh",
+        makeFunction $ do
+          (x :: Double) <- nthArg 1
+          if x <= -1 || x >= 1
+            then fail "value must be strictly between -1 and 1"
+            else pure $ VFloat $ atanh x
+      ),
+      ("erf", makeFunction $ VFloat . erf <$> nthArg 1),
       ("e", VFloat (exp 1)),
       ("pi", VFloat pi),
       ("tau", VFloat (2 * pi))
diff --git a/src/Typst/Module/Standard.hs b/src/Typst/Module/Standard.hs
--- a/src/Typst/Module/Standard.hs
+++ b/src/Typst/Module/Standard.hs
@@ -9,7 +9,8 @@
     symModule,
     loadFileText,
     getPath,
-    applyPureFunction
+    applyPureFunction,
+    elementDefaults
   )
 where
 
@@ -49,7 +50,8 @@
     [ ("math", VModule "math" mathModule),
       ("sym", VModule "sym" symModule),
       ("emoji", VModule "emoji" emojiModule),
-      ("calc", VModule "calc" calcModule)
+      ("calc", VModule "calc" calcModule),
+      ("html", VModule "html" htmlModule)
       -- sys module is added in initialEvalState
     ]
       ++ types
@@ -65,12 +67,102 @@
       ++ time
       ++ dataLoading
 
+-- | Default values for the settable fields of certain elements.
+-- In typst, these fields are materialized when an element is
+-- passed to a show rule, so e.g. @it.marker@ works in
+-- @#show list: it => ..@ even if no explicit marker was given.
+elementDefaults :: M.Map Identifier (M.Map Identifier Val)
+elementDefaults =
+  M.fromList
+    [ ( "list",
+        M.fromList
+          [ ("tight", VBoolean True),
+            ("marker", VArray
+              [ VContent [Txt "\x2022"],   -- •
+                VContent [Txt "\x2023"],   -- ‣
+                VContent [Txt "\x2013"] ]), -- –
+            ("indent", VLength (LExact 0 LPt)),
+            ("body-indent", VLength (LExact 0.5 LEm)),
+            ("spacing", VAuto)
+          ]
+      ),
+      ( "enum",
+        M.fromList
+          [ ("tight", VBoolean True),
+            ("numbering", VString "1."),
+            ("start", VAuto),
+            ("full", VBoolean False),
+            ("reversed", VBoolean False),
+            ("indent", VLength (LExact 0 LPt)),
+            ("body-indent", VLength (LExact 0.5 LEm)),
+            ("spacing", VAuto),
+            ("number-align", VAlignment (Just HorizEnd) (Just VertTop))
+          ]
+      ),
+      ( "terms",
+        M.fromList
+          [ ("tight", VBoolean True),
+            ("separator", VContent
+              [ Elt "h" Nothing
+                  [ ("amount", VLength (LExact 0.6 LEm)),
+                    ("weak", VBoolean True) ] ]),
+            ("indent", VLength (LExact 0 LPt)),
+            ("hanging-indent", VLength (LExact 2 LEm)),
+            ("spacing", VAuto)
+          ]
+      )
+    ]
+
 symModule :: M.Map Identifier Val
 symModule = M.map VSymbol $ makeSymbolMap typstSymbols
 
 emojiModule :: M.Map Identifier Val
 emojiModule = M.map VSymbol $ makeSymbolMap typstEmojis
 
+htmlModule :: M.Map Identifier Val
+htmlModule =
+  M.fromList $
+    [ makeElement
+        (Just "html")
+        "elem"
+        [ ("tag", One TString),
+          ("body", One (TContent :|: TNone))
+        ],
+      makeElement (Just "html") "frame" [("body", One TContent)]
+    ]
+      ++ map mkTag htmlTags
+      ++ map mkVoidTag htmlVoidTags
+  where
+    mkTag tag =
+      makeElement (Just "html") tag [("body", One (TContent :|: TNone))]
+    mkVoidTag tag = makeElement (Just "html") tag []
+
+-- | Typed HTML elements (https://typst.app/docs/reference/html/typed/),
+-- excluding void elements.
+htmlTags :: [Identifier]
+htmlTags =
+  [ "a", "abbr", "address", "article", "aside", "audio", "b", "bdi",
+    "bdo", "blockquote", "body", "button", "canvas", "caption", "cite",
+    "code", "colgroup", "data", "datalist", "dd", "del", "details",
+    "dfn", "dialog", "div", "dl", "dt", "em", "fieldset", "figcaption",
+    "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6",
+    "head", "header", "hgroup", "html", "i", "iframe", "ins", "kbd",
+    "label", "legend", "li", "main", "map", "mark", "menu", "meter",
+    "nav", "noscript", "object", "ol", "optgroup", "option", "output",
+    "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s",
+    "samp", "script", "search", "section", "select", "slot", "small",
+    "span", "strong", "style", "sub", "summary", "sup", "table",
+    "tbody", "td", "template", "textarea", "tfoot", "th", "thead",
+    "time", "title", "tr", "u", "ul", "var", "video"
+  ]
+
+-- | Void HTML elements, which take no body.
+htmlVoidTags :: [Identifier]
+htmlVoidTags =
+  [ "area", "base", "br", "col", "embed", "hr", "img", "input", "link",
+    "meta", "source", "track", "wbr"
+  ]
+
 textual :: [(Identifier, Val)]
 textual =
   [ makeElement
@@ -210,10 +302,30 @@
 visualize :: [(Identifier, Val)]
 visualize =
   [ makeElement Nothing "circle" [("body", One (TContent :|: TNone))],
+    makeElementWithScope
+      Nothing
+      "curve"
+      [("components", Many TContent)]
+      [ makeElement (Just "curve") "move" [("start", One TArray)],
+        makeElement (Just "curve") "line" [("end", One TArray)],
+        makeElement
+          (Just "curve")
+          "quad"
+          [ ("control", One (TArray :|: TAuto :|: TNone)),
+            ("end", One TArray)
+          ],
+        makeElement
+          (Just "curve")
+          "cubic"
+          [ ("control-start", One (TArray :|: TAuto :|: TNone)),
+            ("control-end", One (TArray :|: TNone)),
+            ("end", One TArray)
+          ],
+        makeElement (Just "curve") "close" []
+      ],
     makeElement Nothing "ellipse" [("body", One (TContent :|: TNone))],
     makeElement Nothing "image" [("source", One (TString :|: TBytes))],
     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))]
@@ -231,6 +343,7 @@
       [("body", One TContent)]
       [makeElement (Just "figure") "caption" [("body", One TContent)]],
     makeElement Nothing "heading" [("body", One TContent)],
+    makeElement Nothing "divider" [],
     makeElement Nothing "quote" [("body", One TContent)],
     makeElement Nothing "layout" [("func", One TFunction)],
     makeElement
@@ -292,6 +405,7 @@
   , ("label", VType TLabel)
   , ("version", VType TVersion)
   , ("bytes", VType TBytes)
+  , ("path", VType TPath)
   ]
 
 colors :: [(Identifier, Val)]
@@ -394,19 +508,24 @@
         first <- nthArg 1
         mbsecond <- nthArg 2
         step <- namedArg "step" 1
+        inclusive <- namedArg "inclusive" False
         pure $
           VArray $
             V.fromList $
               map VInteger $
                 case (first, mbsecond) of
-                  (end, Nothing) -> enumFromThenTo 0 step (end - 1)
+                  (end, Nothing) ->
+                    enumFromThenTo 0 step (if inclusive then end else end - 1)
                   (start, Just end) ->
                     enumFromThenTo
                       start
                       (start + step)
-                      ( if start < end
-                          then end - 1
-                          else end + 1
+                      ( if inclusive
+                          then end
+                          else
+                            if start < end
+                              then end - 1
+                              else end + 1
                       )
     ),
     ( "rgb",
@@ -462,18 +581,26 @@
     _ -> fail "could not read string as hex color"
 hexToRGB _ = fail "expected string"
 
-loadFileLazyBytes :: Monad m => FilePath -> MP m BL.ByteString
-loadFileLazyBytes fp = do
+loadResolvedLazyBytes :: Monad m => FilePath -> MP m BL.ByteString
+loadResolvedLazyBytes path = do
   operations <- evalOperations <$> getState
-  path <- getPath fp
   lift $ BL.fromStrict <$> loadBytes operations path
 
 loadFileText :: Monad m => FilePath -> MP m T.Text
-loadFileText fp = do
+loadFileText fp = getPath fp >>= loadResolvedText
+
+loadResolvedText :: Monad m => FilePath -> MP m T.Text
+loadResolvedText path = do
   operations <- evalOperations <$> getState
-  path <- getPath fp
   lift $ TE.decodeUtf8 <$> loadBytes operations path
 
+-- | Resolve a string or path value to a 'FilePath'. Paths are
+-- already resolved; strings are resolved relative to the current file.
+resolvePathVal :: Monad m => Val -> MP m FilePath
+resolvePathVal (VPath fp) = pure fp
+resolvePathVal (VString fp) = getPath (T.unpack fp)
+resolvePathVal v = fail $ "expected string or path, got " <> show (valType v)
+
 -- a leading / = relative to package root
 getPath :: Monad m => FilePath -> MP m FilePath
 getPath ('/':fp') = do
@@ -515,8 +642,8 @@
 dataLoading =
   [ ( "csv",
       makeFunction $ do
-        fp <- nthArg 1
-        bs <- lift $ loadFileLazyBytes fp
+        arg <- nthArg 1
+        bs <- lift $ resolvePathVal arg >>= loadResolvedLazyBytes
         case Csv.decode Csv.NoHeader bs of
           Left e -> fail e
           Right (v :: V.Vector (V.Vector String)) ->
@@ -538,12 +665,13 @@
     ),
     ( "read",
       makeFunction $ do
-        fp <- nthArg 1
+        v <- nthArg 1
+        fp <- lift $ resolvePathVal v
         enc <- namedArg "encoding" (VString "utf-8")
         case enc of
-          VNone -> do bs <- lift $ loadFileLazyBytes fp
+          VNone -> do bs <- lift $ loadResolvedLazyBytes fp
                       pure $ VBytes $ BL.toStrict bs
-          _ -> do t <- lift $ loadFileText fp
+          _ -> do t <- lift $ loadResolvedText fp
                   pure $ VString t
     ),
     ( "toml",
@@ -609,6 +737,5 @@
 getFileOrBytes = do
   v <- nthArg 1
   case v of
-    VString fp -> lift $ loadFileLazyBytes (T.unpack fp)
     VBytes bs -> pure $ BL.fromStrict bs
-    _ -> fail "expecting file path or bytes"
+    _ -> lift $ resolvePathVal v >>= loadResolvedLazyBytes
diff --git a/src/Typst/Parse.hs b/src/Typst/Parse.hs
--- a/src/Typst/Parse.hs
+++ b/src/Typst/Parse.hs
@@ -426,13 +426,8 @@
    lexeme (Code pos <$> choice (map toShorthandParser shorthands))
  where
   shorthands = reverse (sortOn (T.length . fst) mathSymbolShorthands)
-  toShorthandParser (short, symname) =
-    toSym symname <$ try (string (T.unpack short))
-  toSym name =
-    case map (Ident . Identifier) $ T.split (== '.') name of
-      [] -> Literal None
-      [i] -> i
-      (i:is) -> foldr FieldAccess i is
+  toShorthandParser (short, txt) =
+    Literal (String txt) <$ try (string (T.unpack short))
 
 mSymbol :: P Markup
 mSymbol =
diff --git a/src/Typst/Types.hs b/src/Typst/Types.hs
--- a/src/Typst/Types.hs
+++ b/src/Typst/Types.hs
@@ -146,6 +146,9 @@
   | VStyles -- just a placeholder for now
   | VVersion [Integer]
   | VBytes ByteString
+  -- | A @path@ value, referring to a file. The path is stored
+  -- already resolved (relative to the file in which it was constructed).
+  | VPath !FilePath
   | VType !ValType
   deriving (Show, Eq, Typeable)
 
@@ -207,6 +210,7 @@
   | TLocation
   | TVersion
   | TBytes
+  | TPath
   | TType
   | TAny
   | ValType :|: ValType
@@ -244,6 +248,7 @@
     VStyles {} -> TStyles
     VVersion {} -> TVersion
     VBytes {} -> TBytes
+    VPath {} -> TPath
     VType {} -> TType
 
 hasType :: ValType -> Val -> Bool
@@ -404,6 +409,7 @@
   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 (VPath p1) (VPath p2) = Just $ compare p1 p2
   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
@@ -929,6 +935,7 @@
     VStyles -> mempty
     VVersion xs -> text $ T.intercalate "." (map (T.pack . show) xs)
     VBytes bs -> text $ "bytes(" <> T.pack (show (BS.length bs)) <> ")"
+    VPath fp -> "path(\"" <> escString (T.pack fp) <> "\")"
     VType ty -> text $ prettyType ty
 
 prettyType :: ValType -> Text
diff --git a/src/Typst/Util.hs b/src/Typst/Util.hs
--- a/src/Typst/Util.hs
+++ b/src/Typst/Util.hs
@@ -76,8 +76,14 @@
     hasType' TContent VString {} = True
     hasType' TContent VSymbol {} = True
     hasType' TString (VContent _) = True
+    hasType' TString VPath {} = True
     hasType' TTermItem VArray {} = True
+    hasType' (t1 :|: t2) v@VPath {} = hasType' t1 v || hasType' t2 v
     hasType' x y = hasType x y
+    toType TString (VPath fp) = VString (T.pack fp)
+    toType (t1 :|: t2) v@VPath {}
+      | hasType' t1 v = toType t1 v
+      | otherwise = toType t2 v
     toType TContent x = VContent $ valToContent x
     toType TTermItem (VArray [VContent t, VContent d]) = VTermItem t d
     toType TTermItem (VArray [VContent t]) = VTermItem t mempty
diff --git a/test/typ/bugs/math-realize-00.out b/test/typ/bugs/math-realize-00.out
--- a/test/typ/bugs/math-realize-00.out
+++ b/test/typ/bugs/math-realize-00.out
@@ -130,7 +130,7 @@
     , Code
         "typ/bugs/math-realize-00.typ"
         ( line 11 , column 12 )
-        (FieldAccess (Ident (Identifier "op")) (Ident (Identifier "ast")))
+        (Literal (String "\8727"))
     , Text "2"
     ]
 , ParBreak
diff --git a/test/typ/bugs/math-realize-01.out b/test/typ/bugs/math-realize-01.out
--- a/test/typ/bugs/math-realize-01.out
+++ b/test/typ/bugs/math-realize-01.out
@@ -16,7 +16,7 @@
                        [ Code
                            "typ/bugs/math-realize-01.typ"
                            ( line 1 , column 15 )
-                           (FieldAccess (Ident (Identifier "eq")) (Ident (Identifier "gt")))
+                           (Literal (String "\8805"))
                        , Code
                            "typ/bugs/math-realize-01.typ"
                            ( line 1 , column 18 )
@@ -61,8 +61,7 @@
                , Code
                    "typ/bugs/math-realize-01.typ"
                    ( line 3 , column 18 )
-                   (FieldAccess
-                      (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+                   (Literal (String "\8788"))
                , MAttach Nothing (Just (Text "2")) (Text "x")
                ]
            ]
diff --git a/test/typ/compiler/args-00.out b/test/typ/compiler/args-00.out
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/args-00.out
@@ -0,0 +1,153 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 2 , column 2 )
+    (LetFunc
+       (Identifier "collect")
+       [ SinkParam (Just (Identifier "args")) ]
+       (Ident (Identifier "args")))
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 3 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "args")))
+       (FuncCall
+          (Ident (Identifier "collect"))
+          [ NormalArg (Literal (Int 1))
+          , NormalArg (Literal (Int 2))
+          , KeyValArg (Identifier "x") (Literal (Int 3))
+          ]))
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 4 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "doubled")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "map")) (Ident (Identifier "args")))
+          [ NormalArg
+              (FuncExpr
+                 [ NormalParam (Identifier "v") ]
+                 (Times (Ident (Identifier "v")) (Literal (Int 2))))
+          ]))
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "pos")) (Ident (Identifier "doubled")))
+              [])
+       , NormalArg
+           (Array [ Reg (Literal (Int 2)) , Reg (Literal (Int 4)) ])
+       ])
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "named")) (Ident (Identifier "doubled")))
+              [])
+       , NormalArg
+           (Dict [ Reg ( Ident (Identifier "x") , Literal (Int 6) ) ])
+       ])
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 7 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "filtered")))
+       (FuncCall
+          (FieldAccess
+             (Ident (Identifier "filter")) (Ident (Identifier "args")))
+          [ NormalArg
+              (FuncExpr
+                 [ NormalParam (Identifier "v") ]
+                 (GreaterThan (Ident (Identifier "v")) (Literal (Int 1))))
+          ]))
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "pos")) (Ident (Identifier "filtered")))
+              [])
+       , NormalArg (Array [ Reg (Literal (Int 2)) ])
+       ])
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "named")) (Ident (Identifier "filtered")))
+              [])
+       , NormalArg
+           (Dict [ Reg ( Ident (Identifier "x") , Literal (Int 3) ) ])
+       ])
+, SoftBreak
+, Code
+    "typ/compiler/args-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "pos"))
+                 (FuncCall
+                    (FieldAccess
+                       (Ident (Identifier "map"))
+                       (FuncCall (Ident (Identifier "collect")) []))
+                    [ NormalArg
+                        (FuncExpr
+                           [ NormalParam (Identifier "v") ] (Ident (Identifier "v")))
+                    ]))
+              [])
+       , NormalArg (Array [])
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(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/typ/compiler/args-00.typ b/test/typ/compiler/args-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/args-00.typ
@@ -0,0 +1,10 @@
+// Test map and filter on arguments.
+#let collect(..args) = args
+#let args = collect(1, 2, x: 3)
+#let doubled = args.map(v => v * 2)
+#test(doubled.pos(), (2, 4))
+#test(doubled.named(), (x: 6))
+#let filtered = args.filter(v => v > 1)
+#test(filtered.pos(), (2,))
+#test(filtered.named(), (x: 3))
+#test(collect().map(v => v).pos(), ())
diff --git a/test/typ/compiler/dict-11.out b/test/typ/compiler/dict-11.out
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-11.out
@@ -0,0 +1,104 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/compiler/dict-11.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "dict")))
+       (Dict
+          [ Reg ( Ident (Identifier "a") , Literal (Int 1) )
+          , Reg ( Ident (Identifier "b") , Negated (Literal (Int 2)) )
+          , Reg ( Ident (Identifier "c") , Literal (Int 3) )
+          ]))
+, SoftBreak
+, Code
+    "typ/compiler/dict-11.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "map")) (Ident (Identifier "dict")))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "v") ]
+                     (Times (Ident (Identifier "v")) (Literal (Int 10))))
+              ])
+       , NormalArg
+           (Dict
+              [ Reg ( Ident (Identifier "a") , Literal (Int 10) )
+              , Reg ( Ident (Identifier "b") , Negated (Literal (Int 20)) )
+              , Reg ( Ident (Identifier "c") , Literal (Int 30) )
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compiler/dict-11.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "filter")) (Ident (Identifier "dict")))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "v") ]
+                     (GreaterThan (Ident (Identifier "v")) (Literal (Int 0))))
+              ])
+       , NormalArg
+           (Dict
+              [ Reg ( Ident (Identifier "a") , Literal (Int 1) )
+              , Reg ( Ident (Identifier "c") , Literal (Int 3) )
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compiler/dict-11.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "map")) (Dict []))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "v") ] (Ident (Identifier "v")))
+              ])
+       , NormalArg (Dict [])
+       ])
+, SoftBreak
+, Code
+    "typ/compiler/dict-11.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess (Ident (Identifier "filter")) (Dict []))
+              [ NormalArg
+                  (FuncExpr
+                     [ NormalParam (Identifier "v") ] (Literal (Boolean True)))
+              ])
+       , NormalArg (Dict [])
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(body: { text(body: [
+]), 
+                 text(body: [
+]), 
+                 text(body: [✅]), 
+                 text(body: [
+]), 
+                 text(body: [✅]), 
+                 text(body: [
+]), 
+                 text(body: [✅]), 
+                 text(body: [
+]), 
+                 text(body: [✅]), 
+                 parbreak() })
diff --git a/test/typ/compiler/dict-11.typ b/test/typ/compiler/dict-11.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compiler/dict-11.typ
@@ -0,0 +1,6 @@
+// Test dictionary map and filter.
+#let dict = (a: 1, b: -2, c: 3)
+#test(dict.map(v => v * 10), (a: 10, b: -20, c: 30))
+#test(dict.filter(v => v > 0), (a: 1, c: 3))
+#test((:).map(v => v), (:))
+#test((:).filter(v => true), (:))
diff --git a/test/typ/compute/calc-41.out b/test/typ/compute/calc-41.out
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-41.out
@@ -0,0 +1,195 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "asinh")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Float 0.0))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "acosh")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 1)) ])
+       , NormalArg (Literal (Float 0.0))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "atanh")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Float 0.0))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "round")) (Ident (Identifier "calc")))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "asinh")) (Ident (Identifier "calc")))
+                     [ NormalArg
+                         (FuncCall
+                            (FieldAccess
+                               (Ident (Identifier "sinh")) (Ident (Identifier "calc")))
+                            [ NormalArg (Literal (Int 2)) ])
+                     ])
+              , KeyValArg (Identifier "digits") (Literal (Int 10))
+              ])
+       , NormalArg (Literal (Float 2.0))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "round")) (Ident (Identifier "calc")))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "acosh")) (Ident (Identifier "calc")))
+                     [ NormalArg
+                         (FuncCall
+                            (FieldAccess
+                               (Ident (Identifier "cosh")) (Ident (Identifier "calc")))
+                            [ NormalArg (Literal (Int 2)) ])
+                     ])
+              , KeyValArg (Identifier "digits") (Literal (Int 10))
+              ])
+       , NormalArg (Literal (Float 2.0))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "round")) (Ident (Identifier "calc")))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "atanh")) (Ident (Identifier "calc")))
+                     [ NormalArg
+                         (FuncCall
+                            (FieldAccess
+                               (Ident (Identifier "tanh")) (Ident (Identifier "calc")))
+                            [ NormalArg (Literal (Float 0.5)) ])
+                     ])
+              , KeyValArg (Identifier "digits") (Literal (Int 10))
+              ])
+       , NormalArg (Literal (Float 0.5))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "erf")) (Ident (Identifier "calc")))
+              [ NormalArg (Literal (Int 0)) ])
+       , NormalArg (Literal (Float 0.0))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "round")) (Ident (Identifier "calc")))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "erf")) (Ident (Identifier "calc")))
+                     [ NormalArg (Literal (Int 1)) ])
+              , KeyValArg (Identifier "digits") (Literal (Int 7))
+              ])
+       , NormalArg (Literal (Float 0.8427008))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-41.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "round")) (Ident (Identifier "calc")))
+              [ NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "erf")) (Ident (Identifier "calc")))
+                     [ NormalArg (Negated (Literal (Int 1))) ])
+              , KeyValArg (Identifier "digits") (Literal (Int 7))
+              ])
+       , NormalArg (Negated (Literal (Float 0.8427008)))
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(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/typ/compute/calc-41.typ b/test/typ/compute/calc-41.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-41.typ
@@ -0,0 +1,10 @@
+// Test inverse hyperbolic functions and the error function.
+#test(calc.asinh(0), 0.0)
+#test(calc.acosh(1), 0.0)
+#test(calc.atanh(0), 0.0)
+#test(calc.round(calc.asinh(calc.sinh(2)), digits: 10), 2.0)
+#test(calc.round(calc.acosh(calc.cosh(2)), digits: 10), 2.0)
+#test(calc.round(calc.atanh(calc.tanh(0.5)), digits: 10), 0.5)
+#test(calc.erf(0), 0.0)
+#test(calc.round(calc.erf(1), digits: 7), 0.8427008)
+#test(calc.round(calc.erf(-1), digits: 7), -0.8427008)
diff --git a/test/typ/compute/calc-42.out b/test/typ/compute/calc-42.out
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-42.out
@@ -0,0 +1,183 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Literal (String "ff"))
+              , KeyValArg (Identifier "base") (Literal (Int 16))
+              ])
+       , NormalArg (Literal (Int 255))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Literal (String "FF"))
+              , KeyValArg (Identifier "base") (Literal (Int 16))
+              ])
+       , NormalArg (Literal (Int 255))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Literal (String "-ff"))
+              , KeyValArg (Identifier "base") (Literal (Int 16))
+              ])
+       , NormalArg (Negated (Literal (Int 255)))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Literal (String "+101"))
+              , KeyValArg (Identifier "base") (Literal (Int 2))
+              ])
+       , NormalArg (Literal (Int 5))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Literal (String "777"))
+              , KeyValArg (Identifier "base") (Literal (Int 8))
+              ])
+       , NormalArg (Literal (Int 511))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Literal (String "z"))
+              , KeyValArg (Identifier "base") (Literal (Int 36))
+              ])
+       , NormalArg (Literal (Int 35))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "int"))
+              [ NormalArg (Literal (String "42"))
+              , KeyValArg (Identifier "base") (Literal (Int 10))
+              ])
+       , NormalArg (Literal (Int 42))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 9 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess (Ident (Identifier "min")) (Ident (Identifier "int")))
+       , NormalArg (Negated (Literal (Int 9223372036854775808)))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FieldAccess (Ident (Identifier "max")) (Ident (Identifier "int")))
+       , NormalArg (Literal (Int 9223372036854775807))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "to-unicode")) (Ident (Identifier "str")))
+              [ NormalArg (Literal (String "a")) ])
+       , NormalArg (Literal (Int 97))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/calc-42.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "from-unicode")) (Ident (Identifier "str")))
+              [ NormalArg (Literal (Int 97)) ])
+       , NormalArg (Literal (String "a"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(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/typ/compute/calc-42.typ b/test/typ/compute/calc-42.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/calc-42.typ
@@ -0,0 +1,12 @@
+// Test int with base parameter, and int.min/int.max.
+#test(int("ff", base: 16), 255)
+#test(int("FF", base: 16), 255)
+#test(int("-ff", base: 16), -255)
+#test(int("+101", base: 2), 5)
+#test(int("777", base: 8), 511)
+#test(int("z", base: 36), 35)
+#test(int("42", base: 10), 42)
+#test(int.min, -9223372036854775808)
+#test(int.max, 9223372036854775807)
+#test(str.to-unicode("a"), 97)
+#test(str.from-unicode(97), "a")
diff --git a/test/typ/compute/construct-12.out b/test/typ/compute/construct-12.out
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-12.out
@@ -0,0 +1,174 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/compute/construct-12.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 3))
+              , KeyValArg (Identifier "inclusive") (Literal (Boolean True))
+              ])
+       , NormalArg
+           (Array
+              [ Reg (Literal (Int 0))
+              , Reg (Literal (Int 1))
+              , Reg (Literal (Int 2))
+              , Reg (Literal (Int 3))
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compute/construct-12.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 3))
+              , KeyValArg (Identifier "inclusive") (Literal (Boolean False))
+              ])
+       , NormalArg
+           (Array
+              [ Reg (Literal (Int 0))
+              , Reg (Literal (Int 1))
+              , Reg (Literal (Int 2))
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compute/construct-12.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 2))
+              , NormalArg (Literal (Int 5))
+              , KeyValArg (Identifier "inclusive") (Literal (Boolean True))
+              ])
+       , NormalArg
+           (Array
+              [ Reg (Literal (Int 2))
+              , Reg (Literal (Int 3))
+              , Reg (Literal (Int 4))
+              , Reg (Literal (Int 5))
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compute/construct-12.typ"
+    ( line 5 , 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)))
+              , KeyValArg (Identifier "inclusive") (Literal (Boolean True))
+              ])
+       , NormalArg
+           (Array
+              [ Reg (Literal (Int 5))
+              , Reg (Literal (Int 4))
+              , Reg (Literal (Int 3))
+              , Reg (Literal (Int 2))
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compute/construct-12.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Int 10))
+              , KeyValArg (Identifier "step") (Literal (Int 3))
+              , KeyValArg (Identifier "inclusive") (Literal (Boolean True))
+              ])
+       , NormalArg
+           (Array
+              [ Reg (Literal (Int 0))
+              , Reg (Literal (Int 3))
+              , Reg (Literal (Int 6))
+              , Reg (Literal (Int 9))
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compute/construct-12.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Int 9))
+              , KeyValArg (Identifier "step") (Literal (Int 3))
+              , KeyValArg (Identifier "inclusive") (Literal (Boolean True))
+              ])
+       , NormalArg
+           (Array
+              [ Reg (Literal (Int 0))
+              , Reg (Literal (Int 3))
+              , Reg (Literal (Int 6))
+              , Reg (Literal (Int 9))
+              ])
+       ])
+, SoftBreak
+, Code
+    "typ/compute/construct-12.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "range"))
+              [ NormalArg (Literal (Int 0))
+              , NormalArg (Literal (Int 9))
+              , KeyValArg (Identifier "step") (Literal (Int 3))
+              , KeyValArg (Identifier "inclusive") (Literal (Boolean False))
+              ])
+       , NormalArg
+           (Array
+              [ Reg (Literal (Int 0))
+              , Reg (Literal (Int 3))
+              , Reg (Literal (Int 6))
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(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/typ/compute/construct-12.typ b/test/typ/compute/construct-12.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/construct-12.typ
@@ -0,0 +1,8 @@
+// Test the inclusive parameter of range.
+#test(range(3, inclusive: true), (0, 1, 2, 3))
+#test(range(3, inclusive: false), (0, 1, 2))
+#test(range(2, 5, inclusive: true), (2, 3, 4, 5))
+#test(range(5, 2, step: -1, inclusive: true), (5, 4, 3, 2))
+#test(range(0, 10, step: 3, inclusive: true), (0, 3, 6, 9))
+#test(range(0, 9, step: 3, inclusive: true), (0, 3, 6, 9))
+#test(range(0, 9, step: 3, inclusive: false), (0, 3, 6))
diff --git a/test/typ/compute/path-00.out b/test/typ/compute/path-00.out
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/path-00.out
@@ -0,0 +1,153 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 2 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "p")))
+       (FuncCall
+          (Ident (Identifier "path"))
+          [ NormalArg (Literal (String "/assets/files/hello.txt")) ]))
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "type")) [ NormalArg (Ident (Identifier "p")) ])
+       , NormalArg (Ident (Identifier "path"))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (FuncCall
+                 (Ident (Identifier "type")) [ NormalArg (Ident (Identifier "p")) ])
+              (Ident (Identifier "path")))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "path")) [ NormalArg (Ident (Identifier "p")) ])
+       , NormalArg (Ident (Identifier "p"))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 7 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Ident (Identifier "p"))
+              (FuncCall
+                 (Ident (Identifier "path"))
+                 [ NormalArg (Literal (String "/assets/files/hello.txt")) ]))
+       , NormalArg (Literal (Boolean True))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 8 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (Equals
+              (Ident (Identifier "p"))
+              (FuncCall
+                 (Ident (Identifier "path"))
+                 [ NormalArg (Literal (String "/assets/files/data.csv")) ]))
+       , NormalArg (Literal (Boolean False))
+       ])
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 10 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "read")) [ NormalArg (Ident (Identifier "p")) ])
+       , NormalArg (Literal (String "Hello, world!"))
+       ])
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 11 , column 2 )
+    (FuncCall
+       (Ident (Identifier "test"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "csv"))
+              [ NormalArg
+                  (FuncCall
+                     (Ident (Identifier "path"))
+                     [ NormalArg (Literal (String "/assets/files/data.csv")) ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "csv"))
+              [ NormalArg (Literal (String "/assets/files/data.csv")) ])
+       ])
+, SoftBreak
+, Code
+    "typ/compute/path-00.typ"
+    ( line 12 , column 2 )
+    (FuncCall
+       (Ident (Identifier "image"))
+       [ NormalArg
+           (FuncCall
+              (Ident (Identifier "path"))
+              [ NormalArg (Literal (String "/assets/files/rhino.png")) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(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: [
+]), 
+                 image(source: "./assets/files/rhino.png"), 
+                 parbreak() })
diff --git a/test/typ/compute/path-00.typ b/test/typ/compute/path-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/compute/path-00.typ
@@ -0,0 +1,12 @@
+// Test the path type.
+#let p = path("/assets/files/hello.txt")
+#test(type(p), path)
+#test(type(p) == path, true)
+// constructing a path from a path returns it unchanged
+#test(path(p), p)
+#test(p == path("/assets/files/hello.txt"), true)
+#test(p == path("/assets/files/data.csv"), false)
+// paths are accepted where file-path strings are accepted
+#test(read(p), "Hello, world!")
+#test(csv(path("/assets/files/data.csv")), csv("/assets/files/data.csv"))
+#image(path("/assets/files/rhino.png"))
diff --git a/test/typ/html/elem-00.out b/test/typ/html/elem-00.out
new file mode 100644
--- /dev/null
+++ b/test/typ/html/elem-00.out
@@ -0,0 +1,74 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/html/elem-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "elem")) (Ident (Identifier "html")))
+       [ NormalArg (Literal (String "section"))
+       , KeyValArg
+           (Identifier "attrs")
+           (Dict
+              [ Reg ( Ident (Identifier "id") , Literal (String "intro") ) ])
+       , BlockArg [ Text "Hello" ]
+       ])
+, SoftBreak
+, Code
+    "typ/html/elem-00.typ"
+    ( line 3 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "div")) (Ident (Identifier "html")))
+       [ KeyValArg (Identifier "class") (Literal (String "container"))
+       , BlockArg [ Text "Some" , Space , Text "text" ]
+       ])
+, SoftBreak
+, Code
+    "typ/html/elem-00.typ"
+    ( line 4 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "span")) (Ident (Identifier "html")))
+       [ BlockArg [ Text "inline" ] ])
+, SoftBreak
+, Code
+    "typ/html/elem-00.typ"
+    ( line 5 , column 2 )
+    (FuncCall
+       (FieldAccess (Ident (Identifier "br")) (Ident (Identifier "html")))
+       [])
+, SoftBreak
+, Code
+    "typ/html/elem-00.typ"
+    ( line 6 , column 2 )
+    (FuncCall
+       (FieldAccess
+          (Ident (Identifier "img")) (Ident (Identifier "html")))
+       [ KeyValArg (Identifier "src") (Literal (String "foo.png"))
+       , KeyValArg (Identifier "alt") (Literal (String "Foo"))
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(body: { text(body: [
+]), 
+                 html.elem(attrs: (id: "intro"), 
+                           body: text(body: [Hello]), 
+                           tag: "section"), 
+                 text(body: [
+]), 
+                 html.div(body: text(body: [Some text]), 
+                          class: "container"), 
+                 text(body: [
+]), 
+                 html.span(body: text(body: [inline])), 
+                 text(body: [
+]), 
+                 html.br(), 
+                 text(body: [
+]), 
+                 html.img(alt: "Foo", 
+                          src: "foo.png"), 
+                 parbreak() })
diff --git a/test/typ/html/elem-00.typ b/test/typ/html/elem-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/html/elem-00.typ
@@ -0,0 +1,6 @@
+// Test html.elem and typed html elements.
+#html.elem("section", attrs: (id: "intro"))[Hello]
+#html.div(class: "container")[Some text]
+#html.span[inline]
+#html.br()
+#html.img(src: "foo.png", alt: "Foo")
diff --git a/test/typ/layout/container-02.out b/test/typ/layout/container-02.out
--- a/test/typ/layout/container-02.out
+++ b/test/typ/layout/container-02.out
@@ -11,27 +11,47 @@
        , KeyValArg (Identifier "fill") (Ident (Identifier "yellow"))
        , NormalArg
            (FuncCall
-              (Ident (Identifier "path"))
+              (Ident (Identifier "curve"))
               [ KeyValArg (Identifier "fill") (Ident (Identifier "purple"))
               , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 0.0 Pt))
-                     , Reg (Literal (Numeric 0.0 Pt))
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "move")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 0.0 Pt))
+                            , Reg (Literal (Numeric 0.0 Pt))
+                            ])
                      ])
               , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 30.0 Pt))
-                     , Reg (Literal (Numeric 30.0 Pt))
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 30.0 Pt))
+                            , Reg (Literal (Numeric 30.0 Pt))
+                            ])
                      ])
               , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 0.0 Pt))
-                     , Reg (Literal (Numeric 30.0 Pt))
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 0.0 Pt))
+                            , Reg (Literal (Numeric 30.0 Pt))
+                            ])
                      ])
               , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 30.0 Pt))
-                     , Reg (Literal (Numeric 0.0 Pt))
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 30.0 Pt))
+                            , Reg (Literal (Numeric 0.0 Pt))
+                            ])
                      ])
               ])
        ])
@@ -40,13 +60,15 @@
 --- evaluated ---
 document(body: { 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))), 
+                 box(body: curve(components: (curve.move(start: (0.0pt, 
+                                                                 0.0pt)), 
+                                              curve.line(end: (30.0pt, 
+                                                               30.0pt)), 
+                                              curve.line(end: (0.0pt, 
+                                                               30.0pt)), 
+                                              curve.line(end: (30.0pt, 
+                                                               0.0pt))), 
+                                 fill: rgb(69%,5%,78%,100%)), 
                      fill: rgb(100%,86%,0%,100%), 
                      height: 50.0pt, 
                      width: 50.0pt), 
diff --git a/test/typ/layout/container-02.typ b/test/typ/layout/container-02.typ
--- a/test/typ/layout/container-02.typ
+++ b/test/typ/layout/container-02.typ
@@ -3,12 +3,11 @@
   width: 50pt,
   height: 50pt,
   fill: yellow,
-  path(
+  curve(
     fill: purple,
-    (0pt, 0pt),
-    (30pt, 30pt),
-    (0pt, 30pt),
-    (30pt, 0pt),
+    curve.move((0pt, 0pt)),
+    curve.line((30pt, 30pt)),
+    curve.line((0pt, 30pt)),
+    curve.line((30pt, 0pt)),
   ),
 )
-
diff --git a/test/typ/math/accent-02.out b/test/typ/math/accent-02.out
--- a/test/typ/math/accent-02.out
+++ b/test/typ/math/accent-02.out
@@ -20,7 +20,7 @@
                [ Code
                    "typ/math/accent-02.typ"
                    ( line 2 , column 26 )
-                   (FieldAccess (Ident (Identifier "l")) (Ident (Identifier "arrow")))
+                   (Literal (String "\8592"))
                ]
            ])
     , Text ","
diff --git a/test/typ/math/accent-05.out b/test/typ/math/accent-05.out
--- a/test/typ/math/accent-05.out
+++ b/test/typ/math/accent-05.out
@@ -7,7 +7,7 @@
     , Code
         "typ/math/accent-05.typ"
         ( line 2 , column 6 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , MAttach
         Nothing
         (Just (Text "x"))
@@ -18,7 +18,7 @@
     , Code
         "typ/math/accent-05.typ"
         ( line 2 , column 18 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , MAttach
         Nothing
         (Just (Text "x"))
diff --git a/test/typ/math/attach-01.out b/test/typ/math/attach-01.out
--- a/test/typ/math/attach-01.out
+++ b/test/typ/math/attach-01.out
@@ -27,7 +27,7 @@
                      , Code
                          "typ/math/attach-01.typ"
                          ( line 4 , column 47 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      ]))
            ])
     , Text ","
@@ -59,7 +59,7 @@
                      [ Code
                          "typ/math/attach-01.typ"
                          ( line 5 , column 56 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]))
            , KeyValArg (Identifier "tl") (Block (Content [ Text "0" ]))
diff --git a/test/typ/math/attach-06.out b/test/typ/math/attach-06.out
--- a/test/typ/math/attach-06.out
+++ b/test/typ/math/attach-06.out
@@ -12,7 +12,7 @@
            [ Code
                "typ/math/attach-06.typ"
                ( line 2 , column 4 )
-               (Ident (Identifier "minus"))
+               (Literal (String "\8722"))
            , Text "1"
            ])
     , Text "+"
@@ -25,7 +25,7 @@
               [ Code
                   "typ/math/attach-06.typ"
                   ( line 2 , column 23 )
-                  (Ident (Identifier "minus"))
+                  (Literal (String "\8722"))
               , MFrac (Text "1") (Text "2")
               ]))
         (MGroup
diff --git a/test/typ/math/attach-07.out b/test/typ/math/attach-07.out
--- a/test/typ/math/attach-07.out
+++ b/test/typ/math/attach-07.out
@@ -134,7 +134,7 @@
     , Code
         "typ/math/attach-07.typ"
         ( line 8 , column 24 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , MAttach
         (Just (Text "1"))
         (Just (Text "1"))
diff --git a/test/typ/math/attach-08.out b/test/typ/math/attach-08.out
--- a/test/typ/math/attach-08.out
+++ b/test/typ/math/attach-08.out
@@ -12,7 +12,7 @@
               , Code
                   "typ/math/attach-08.typ"
                   ( line 2 , column 9 )
-                  (FieldAccess (Ident (Identifier "r")) (Ident (Identifier "arrow")))
+                  (Literal (String "\8594"))
               , Code
                   "typ/math/attach-08.typ"
                   ( line 2 , column 11 )
diff --git a/test/typ/math/attach-09.out b/test/typ/math/attach-09.out
--- a/test/typ/math/attach-09.out
+++ b/test/typ/math/attach-09.out
@@ -13,7 +13,7 @@
     , Code
         "typ/math/attach-09.typ"
         ( line 2 , column 17 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , MAttach (Just (Text "1")) (Just (Text "2")) (Text "A")
     ]
 , SoftBreak
@@ -37,7 +37,7 @@
     , Code
         "typ/math/attach-09.typ"
         ( line 3 , column 20 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , MAttach
         (Just (Text "1"))
         (Just (Text "2"))
@@ -67,7 +67,7 @@
     , Code
         "typ/math/attach-09.typ"
         ( line 4 , column 24 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , MAttach
         (Just (Text "a"))
         (Just (Text "b"))
diff --git a/test/typ/math/cancel-00.out b/test/typ/math/cancel-00.out
--- a/test/typ/math/cancel-00.out
+++ b/test/typ/math/cancel-00.out
@@ -16,7 +16,7 @@
     , Code
         "typ/math/cancel-00.typ"
         ( line 2 , column 24 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-00.typ"
         ( line 2 , column 26 )
diff --git a/test/typ/math/cancel-01.out b/test/typ/math/cancel-01.out
--- a/test/typ/math/cancel-01.out
+++ b/test/typ/math/cancel-01.out
@@ -23,7 +23,7 @@
     , Code
         "typ/math/cancel-01.typ"
         ( line 3 , column 25 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-01.typ"
         ( line 3 , column 27 )
@@ -31,7 +31,7 @@
     , Code
         "typ/math/cancel-01.typ"
         ( line 3 , column 37 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-01.typ"
         ( line 3 , column 39 )
@@ -39,7 +39,7 @@
     , Code
         "typ/math/cancel-01.typ"
         ( line 3 , column 49 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Text "5"
     , Text "+"
     , Code
@@ -49,7 +49,7 @@
     , Code
         "typ/math/cancel-01.typ"
         ( line 3 , column 65 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-01.typ"
         ( line 3 , column 67 )
diff --git a/test/typ/math/cancel-02.out b/test/typ/math/cancel-02.out
--- a/test/typ/math/cancel-02.out
+++ b/test/typ/math/cancel-02.out
@@ -16,7 +16,7 @@
     , Code
         "typ/math/cancel-02.typ"
         ( line 2 , column 33 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-02.typ"
         ( line 2 , column 35 )
@@ -35,7 +35,7 @@
     , Code
         "typ/math/cancel-02.typ"
         ( line 2 , column 79 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-02.typ"
         ( line 2 , column 81 )
diff --git a/test/typ/math/cancel-04.out b/test/typ/math/cancel-04.out
--- a/test/typ/math/cancel-04.out
+++ b/test/typ/math/cancel-04.out
@@ -25,7 +25,7 @@
     , Code
         "typ/math/cancel-04.typ"
         ( line 3 , column 31 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-04.typ"
         ( line 3 , column 33 )
@@ -56,7 +56,7 @@
     , Code
         "typ/math/cancel-04.typ"
         ( line 4 , column 32 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-04.typ"
         ( line 4 , column 34 )
diff --git a/test/typ/math/cancel-05.out b/test/typ/math/cancel-05.out
--- a/test/typ/math/cancel-05.out
+++ b/test/typ/math/cancel-05.out
@@ -16,7 +16,7 @@
     , Code
         "typ/math/cancel-05.typ"
         ( line 2 , column 34 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-05.typ"
         ( line 2 , column 36 )
@@ -45,7 +45,7 @@
     , Code
         "typ/math/cancel-05.typ"
         ( line 3 , column 31 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Code
         "typ/math/cancel-05.typ"
         ( line 3 , column 33 )
diff --git a/test/typ/math/cases-00.out b/test/typ/math/cases-00.out
--- a/test/typ/math/cases-00.out
+++ b/test/typ/math/cases-00.out
@@ -10,8 +10,7 @@
     , Code
         "typ/math/cases-00.typ"
         ( line 1 , column 11 )
-        (FieldAccess
-           (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+        (Literal (String "\8788"))
     , Code
         "typ/math/cases-00.typ"
         ( line 1 , column 14 )
@@ -40,7 +39,7 @@
                , Code
                    "typ/math/cases-00.typ"
                    ( line 2 , column 28 )
-                   (FieldAccess (Ident (Identifier "eq")) (Ident (Identifier "lt")))
+                   (Literal (String "\8804"))
                , Text "0"
                ]
            , BlockArg
diff --git a/test/typ/math/content-01.out b/test/typ/math/content-01.out
--- a/test/typ/math/content-01.out
+++ b/test/typ/math/content-01.out
@@ -7,8 +7,7 @@
     , Code
         "typ/math/content-01.typ"
         ( line 2 , column 5 )
-        (FieldAccess
-           (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+        (Literal (String "\8788"))
     , MFrac
         (Code
            "typ/math/content-01.typ"
diff --git a/test/typ/math/content-03.out b/test/typ/math/content-03.out
--- a/test/typ/math/content-03.out
+++ b/test/typ/math/content-03.out
@@ -20,8 +20,7 @@
     , Code
         "typ/math/content-03.typ"
         ( line 3 , column 11 )
-        (FieldAccess
-           (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+        (Literal (String "\8788"))
     , Code
         "typ/math/content-03.typ"
         ( line 3 , column 15 )
diff --git a/test/typ/math/delimited-01.out b/test/typ/math/delimited-01.out
--- a/test/typ/math/delimited-01.out
+++ b/test/typ/math/delimited-01.out
@@ -23,7 +23,7 @@
                 , Code
                     "typ/math/delimited-01.typ"
                     ( line 2 , column 16 )
-                    (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+                    (Literal (String "\8800"))
                 , Code
                     "typ/math/delimited-01.typ"
                     ( line 2 , column 19 )
diff --git a/test/typ/math/delimited-02.out b/test/typ/math/delimited-02.out
--- a/test/typ/math/delimited-02.out
+++ b/test/typ/math/delimited-02.out
@@ -6,22 +6,16 @@
     [ Code
         "typ/math/delimited-02.typ"
         ( line 2 , column 3 )
-        (FieldAccess
-           (Ident (Identifier "l"))
-           (FieldAccess
-              (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+        (Literal (String "\10214"))
     , MFrac (Text "a") (Text "b")
     , Code
         "typ/math/delimited-02.typ"
         ( line 2 , column 8 )
-        (FieldAccess
-           (Ident (Identifier "r"))
-           (FieldAccess
-              (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+        (Literal (String "\10215"))
     , Code
         "typ/math/delimited-02.typ"
         ( line 2 , column 11 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , Code
         "typ/math/delimited-02.typ"
         ( line 2 , column 14 )
@@ -31,24 +25,18 @@
                [ Code
                    "typ/math/delimited-02.typ"
                    ( line 2 , column 17 )
-                   (FieldAccess
-                      (Ident (Identifier "r"))
-                      (FieldAccess
-                         (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+                   (Literal (String "\10215"))
                , MFrac (Text "a") (Text "b")
                , Code
                    "typ/math/delimited-02.typ"
                    ( line 2 , column 22 )
-                   (FieldAccess
-                      (Ident (Identifier "r"))
-                      (FieldAccess
-                         (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+                   (Literal (String "\10215"))
                ]
            ])
     , Code
         "typ/math/delimited-02.typ"
         ( line 2 , column 26 )
-        (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+        (Literal (String "\8800"))
     , MGroup
         (Just "[") Nothing [ MFrac (Text "a") (Text "b") , Text ")" ]
     ]
diff --git a/test/typ/math/delimited-09.out b/test/typ/math/delimited-09.out
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-09.out
@@ -0,0 +1,109 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "typ/math/delimited-09.typ"
+        ( line 2 , column 3 )
+        (FuncCall
+           (FieldAccess
+              (Ident (Identifier "l")) (Ident (Identifier "chevron")))
+           [ BlockArg [ MFrac (Text "a") (Text "b") ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "typ/math/delimited-09.typ"
+        ( line 3 , column 3 )
+        (FuncCall
+           (FieldAccess
+              (Ident (Identifier "double"))
+              (FieldAccess
+                 (Ident (Identifier "l")) (Ident (Identifier "chevron"))))
+           [ BlockArg [ Text "x" ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "typ/math/delimited-09.typ"
+        ( line 4 , column 3 )
+        (FuncCall
+           (FieldAccess (Ident (Identifier "l")) (Ident (Identifier "paren")))
+           [ BlockArg [ Text "a" ] , BlockArg [ Text "b" ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "typ/math/delimited-09.typ"
+        ( line 5 , column 3 )
+        (FuncCall
+           (FieldAccess (Ident (Identifier "v")) (Ident (Identifier "bar")))
+           [ BlockArg [ Text "x" ] ])
+    ]
+, SoftBreak
+, Equation
+    True
+    [ Code
+        "typ/math/delimited-09.typ"
+        ( line 6 , column 3 )
+        (FuncCall
+           (FieldAccess (Ident (Identifier "l")) (Ident (Identifier "brace")))
+           [ BlockArg [ Text "x" ] ])
+    , Text "+"
+    , Code
+        "typ/math/delimited-09.typ"
+        ( line 6 , column 16 )
+        (FuncCall
+           (FieldAccess (Ident (Identifier "l")) (Ident (Identifier "fence")))
+           [ BlockArg [ Text "y" ] ])
+    ]
+, ParBreak
+]
+--- evaluated ---
+document(body: { text(body: [
+]), 
+                 math.equation(block: true, 
+                               body: math.lr(body: ({ [⟨], 
+                                                      math.frac(denom: text(body: [b]), 
+                                                                num: text(body: [a])), 
+                                                      [⟩] })), 
+                               numbering: none), 
+                 text(body: [
+]), 
+                 math.equation(block: true, 
+                               body: math.lr(body: ({ [⟪], 
+                                                      text(body: [x]), 
+                                                      [⟫] })), 
+                               numbering: none), 
+                 text(body: [
+]), 
+                 math.equation(block: true, 
+                               body: math.lr(body: ({ [(], 
+                                                      text(body: [a]), 
+                                                      [,], 
+                                                      text(body: [b]), 
+                                                      [)] })), 
+                               numbering: none), 
+                 text(body: [
+]), 
+                 math.equation(block: true, 
+                               body: math.lr(body: ({ [|], 
+                                                      text(body: [x]), 
+                                                      [|] })), 
+                               numbering: none), 
+                 text(body: [
+]), 
+                 math.equation(block: true, 
+                               body: { math.lr(body: ({ [{], 
+                                                        text(body: [x]), 
+                                                        [}] })), 
+                                       text(body: [+]), 
+                                       math.lr(body: ({ [⧘], 
+                                                        text(body: [y]), 
+                                                        [⧙] })) }, 
+                               numbering: none), 
+                 parbreak() })
diff --git a/test/typ/math/delimited-09.typ b/test/typ/math/delimited-09.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/math/delimited-09.typ
@@ -0,0 +1,6 @@
+// Test calling delimiter symbols to produce an lr element.
+$ chevron.l(a/b) $
+$ chevron.l.double(x) $
+$ paren.l(a, b) $
+$ bar.v(x) $
+$ brace.l(x) + fence.l(y) $
diff --git a/test/typ/math/frac-02.out b/test/typ/math/frac-02.out
--- a/test/typ/math/frac-02.out
+++ b/test/typ/math/frac-02.out
@@ -12,7 +12,7 @@
            [ Code
                "typ/math/frac-02.typ"
                ( line 2 , column 8 )
-               (Ident (Identifier "minus"))
+               (Literal (String "\8722"))
            , Text "b"
            , Code
                "typ/math/frac-02.typ"
@@ -29,7 +29,7 @@
                       , Code
                           "typ/math/frac-02.typ"
                           ( line 2 , column 31 )
-                          (Ident (Identifier "minus"))
+                          (Literal (String "\8722"))
                       , Text "4"
                       , Text "a"
                       , Text "c"
diff --git a/test/typ/math/frac-06.out b/test/typ/math/frac-06.out
--- a/test/typ/math/frac-06.out
+++ b/test/typ/math/frac-06.out
@@ -25,19 +25,13 @@
     , Code
         "typ/math/frac-06.typ"
         ( line 2 , column 36 )
-        (FieldAccess
-           (Ident (Identifier "l"))
-           (FieldAccess
-              (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+        (Literal (String "\10214"))
     , Text "x"
     , MFrac
         (Code
            "typ/math/frac-06.typ"
            ( line 2 , column 39 )
-           (FieldAccess
-              (Ident (Identifier "r"))
-              (FieldAccess
-                 (Ident (Identifier "stroked")) (Ident (Identifier "bracket")))))
+           (Literal (String "\10215")))
         (Text "2")
     , HardBreak
     , MFrac (Text "1.2") (Text "3.7")
diff --git a/test/typ/math/matrix-01.out b/test/typ/math/matrix-01.out
--- a/test/typ/math/matrix-01.out
+++ b/test/typ/math/matrix-01.out
@@ -14,7 +14,7 @@
                  , Code
                      "typ/math/matrix-01.typ"
                      ( line 3 , column 9 )
-                     (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                     (Literal (String "\8230"))
                  , Text "10"
                  ]
                , [ Text "2"
@@ -22,7 +22,7 @@
                  , Code
                      "typ/math/matrix-01.typ"
                      ( line 4 , column 9 )
-                     (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                     (Literal (String "\8230"))
                  , Text "10"
                  ]
                , [ Code
@@ -48,7 +48,7 @@
                  , Code
                      "typ/math/matrix-01.typ"
                      ( line 6 , column 11 )
-                     (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                     (Literal (String "\8230"))
                  , Text "10"
                  ]
                ]
diff --git a/test/typ/math/matrix-alignment-05.out b/test/typ/math/matrix-alignment-05.out
--- a/test/typ/math/matrix-alignment-05.out
+++ b/test/typ/math/matrix-alignment-05.out
@@ -96,7 +96,7 @@
                      [ Code
                          "typ/math/matrix-alignment-05.typ"
                          ( line 5 , column 17 )
-                         (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                         (Literal (String "\8230"))
                      , Text "."
                      , Text "."
                      , MAlignPoint
@@ -105,7 +105,7 @@
                      , Code
                          "typ/math/matrix-alignment-05.typ"
                          ( line 5 , column 25 )
-                         (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                         (Literal (String "\8230"))
                      , Text "."
                      , Text "."
                      ]
diff --git a/test/typ/math/matrix-alignment-06.out b/test/typ/math/matrix-alignment-06.out
--- a/test/typ/math/matrix-alignment-06.out
+++ b/test/typ/math/matrix-alignment-06.out
@@ -15,7 +15,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 2 , column 7 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  , Text "1"
@@ -28,7 +28,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 2 , column 20 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  , Text "1"
@@ -41,7 +41,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 2 , column 33 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  ]
@@ -63,7 +63,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 3 , column 7 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      , MAlignPoint
                      ]
@@ -77,7 +77,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 3 , column 24 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      , MAlignPoint
                      ]
@@ -91,7 +91,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 3 , column 41 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      , MAlignPoint
                      ]
@@ -114,7 +114,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 4 , column 7 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      , MAlignPoint
                      ]
@@ -128,7 +128,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 4 , column 23 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  , Text "1"
@@ -141,7 +141,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 4 , column 36 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  ]
@@ -164,7 +164,7 @@
                      , Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 5 , column 8 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  , MGroup Nothing Nothing [ MAlignPoint , Text "1" ]
@@ -177,7 +177,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 5 , column 23 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  , Text "1"
@@ -190,7 +190,7 @@
                      [ Code
                          "typ/math/matrix-alignment-06.typ"
                          ( line 5 , column 36 )
-                         (Ident (Identifier "minus"))
+                         (Literal (String "\8722"))
                      , Text "1"
                      ]
                  ]
diff --git a/test/typ/math/multiline-03.out b/test/typ/math/multiline-03.out
--- a/test/typ/math/multiline-03.out
+++ b/test/typ/math/multiline-03.out
@@ -7,8 +7,7 @@
     , Code
         "typ/math/multiline-03.typ"
         ( line 2 , column 5 )
-        (FieldAccess
-           (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+        (Literal (String "\8788"))
     , Code
         "typ/math/multiline-03.typ"
         ( line 2 , column 8 )
diff --git a/test/typ/math/multiline-05.out b/test/typ/math/multiline-05.out
--- a/test/typ/math/multiline-05.out
+++ b/test/typ/math/multiline-05.out
@@ -22,7 +22,7 @@
               , Code
                   "typ/math/multiline-05.typ"
                   ( line 2 , column 20 )
-                  (FieldAccess (Ident (Identifier "eq")) (Ident (Identifier "lt")))
+                  (Literal (String "\8804"))
               , Text "5"
               ]))
         Nothing
diff --git a/test/typ/math/numbering-00.out b/test/typ/math/numbering-00.out
--- a/test/typ/math/numbering-00.out
+++ b/test/typ/math/numbering-00.out
@@ -38,8 +38,7 @@
     , Code
         "typ/math/numbering-00.typ"
         ( line 5 , column 11 )
-        (FieldAccess
-           (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+        (Literal (String "\8788"))
     , MFrac
         (MGroup
            (Just "(")
diff --git a/test/typ/math/op-00.out b/test/typ/math/op-00.out
--- a/test/typ/math/op-00.out
+++ b/test/typ/math/op-00.out
@@ -12,12 +12,12 @@
               , Code
                   "typ/math/op-00.typ"
                   ( line 2 , column 9 )
-                  (FieldAccess (Ident (Identifier "eq")) (Ident (Identifier "lt")))
+                  (Literal (String "\8804"))
               , Text "n"
               , Code
                   "typ/math/op-00.typ"
                   ( line 2 , column 12 )
-                  (FieldAccess (Ident (Identifier "eq")) (Ident (Identifier "lt")))
+                  (Literal (String "\8804"))
               , Text "m"
               ]))
         Nothing
diff --git a/test/typ/math/op-02.out b/test/typ/math/op-02.out
--- a/test/typ/math/op-02.out
+++ b/test/typ/math/op-02.out
@@ -23,7 +23,7 @@
               , Code
                   "typ/math/op-02.typ"
                   ( line 3 , column 16 )
-                  (FieldAccess (Ident (Identifier "r")) (Ident (Identifier "arrow")))
+                  (Literal (String "\8594"))
               , Code
                   "typ/math/op-02.typ"
                   ( line 3 , column 18 )
@@ -51,7 +51,7 @@
               , Code
                   "typ/math/op-02.typ"
                   ( line 4 , column 9 )
-                  (FieldAccess (Ident (Identifier "r")) (Ident (Identifier "arrow")))
+                  (Literal (String "\8594"))
               , Code
                   "typ/math/op-02.typ"
                   ( line 4 , column 11 )
diff --git a/test/typ/math/op-03.out b/test/typ/math/op-03.out
--- a/test/typ/math/op-03.out
+++ b/test/typ/math/op-03.out
@@ -12,8 +12,7 @@
               , Code
                   "typ/math/op-03.typ"
                   ( line 2 , column 32 )
-                  (FieldAccess
-                     (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+                  (Literal (String "\8788"))
               , Text "1"
               ]))
         Nothing
@@ -36,8 +35,7 @@
               , Code
                   "typ/math/op-03.typ"
                   ( line 3 , column 31 )
-                  (FieldAccess
-                     (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+                  (Literal (String "\8788"))
               , Text "1"
               ]))
         Nothing
diff --git a/test/typ/math/root-03.out b/test/typ/math/root-03.out
--- a/test/typ/math/root-03.out
+++ b/test/typ/math/root-03.out
@@ -12,10 +12,7 @@
                [ Code
                    "typ/math/root-03.typ"
                    ( line 2 , column 8 )
-                   (FieldAccess
-                      (Ident (Identifier "l"))
-                      (FieldAccess
-                         (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+                   (Literal (String "\10214"))
                , Text "x"
                , MAttach
                    Nothing
@@ -23,18 +20,12 @@
                    (Code
                       "typ/math/root-03.typ"
                       ( line 2 , column 11 )
-                      (FieldAccess
-                         (Ident (Identifier "r"))
-                         (FieldAccess
-                            (Ident (Identifier "stroked")) (Ident (Identifier "bracket")))))
+                      (Literal (String "\10215")))
                , Text "+"
                , Code
                    "typ/math/root-03.typ"
                    ( line 2 , column 18 )
-                   (FieldAccess
-                      (Ident (Identifier "l"))
-                      (FieldAccess
-                         (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+                   (Literal (String "\10214"))
                , Text "y"
                , MAttach
                    Nothing
@@ -42,28 +33,19 @@
                    (Code
                       "typ/math/root-03.typ"
                       ( line 2 , column 21 )
-                      (FieldAccess
-                         (Ident (Identifier "r"))
-                         (FieldAccess
-                            (Ident (Identifier "stroked")) (Ident (Identifier "bracket")))))
+                      (Literal (String "\10215")))
                ]
            ])
     , Text "<"
     , Code
         "typ/math/root-03.typ"
         ( line 2 , column 29 )
-        (FieldAccess
-           (Ident (Identifier "l"))
-           (FieldAccess
-              (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+        (Literal (String "\10214"))
     , Text "z"
     , Code
         "typ/math/root-03.typ"
         ( line 2 , column 32 )
-        (FieldAccess
-           (Ident (Identifier "r"))
-           (FieldAccess
-              (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+        (Literal (String "\10215"))
     ]
 , SoftBreak
 , Equation
diff --git a/test/typ/math/spacing-00.out b/test/typ/math/spacing-00.out
--- a/test/typ/math/spacing-00.out
+++ b/test/typ/math/spacing-00.out
@@ -40,7 +40,7 @@
     , Code
         "typ/math/spacing-00.typ"
         ( line 4 , column 8 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Text "|"
     , Text ","
     , MGroup (Just "[") Nothing [ Text "=" ]
@@ -65,7 +65,7 @@
     [ Code
         "typ/math/spacing-00.typ"
         ( line 6 , column 2 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Text "a"
     , Text ","
     , Text "+"
@@ -94,7 +94,7 @@
     , Code
         "typ/math/spacing-00.typ"
         ( line 8 , column 8 )
-        (FieldAccess (Ident (Identifier "op")) (Ident (Identifier "ast")))
+        (Literal (String "\8727"))
     , Text "b"
     ]
 , Space
diff --git a/test/typ/math/spacing-02.out b/test/typ/math/spacing-02.out
--- a/test/typ/math/spacing-02.out
+++ b/test/typ/math/spacing-02.out
@@ -51,7 +51,7 @@
     , Code
         "typ/math/spacing-02.typ"
         ( line 4 , column 4 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Text "b"
     , Code
         "typ/math/spacing-02.typ"
diff --git a/test/typ/math/spacing-04.out b/test/typ/math/spacing-04.out
--- a/test/typ/math/spacing-04.out
+++ b/test/typ/math/spacing-04.out
@@ -21,15 +21,12 @@
     , Code
         "typ/math/spacing-04.typ"
         ( line 3 , column 16 )
-        (Ident (Identifier "minus"))
+        (Literal (String "\8722"))
     , Text "d"
     , Code
         "typ/math/spacing-04.typ"
         ( line 3 , column 20 )
-        (FieldAccess
-           (Ident (Identifier "r"))
-           (FieldAccess
-              (Ident (Identifier "double")) (Ident (Identifier "arrow"))))
+        (Literal (String "\8658"))
     , Text "e"
     , Code
         "typ/math/spacing-04.typ"
@@ -75,7 +72,7 @@
                [ Code
                    "typ/math/spacing-04.typ"
                    ( line 4 , column 40 )
-                   (Ident (Identifier "minus"))
+                   (Literal (String "\8722"))
                ]
            ])
     , Text "d"
@@ -88,10 +85,7 @@
                [ Code
                    "typ/math/spacing-04.typ"
                    ( line 4 , column 49 )
-                   (FieldAccess
-                      (Ident (Identifier "r"))
-                      (FieldAccess
-                         (Ident (Identifier "double")) (Ident (Identifier "arrow"))))
+                   (Literal (String "\8658"))
                ]
            ])
     , Text "e"
@@ -155,7 +149,7 @@
                [ Code
                    "typ/math/spacing-04.typ"
                    ( line 5 , column 44 )
-                   (Ident (Identifier "minus"))
+                   (Literal (String "\8722"))
                ]
            ])
     , Text "d"
@@ -168,10 +162,7 @@
                [ Code
                    "typ/math/spacing-04.typ"
                    ( line 5 , column 62 )
-                   (FieldAccess
-                      (Ident (Identifier "r"))
-                      (FieldAccess
-                         (Ident (Identifier "double")) (Ident (Identifier "arrow"))))
+                   (Literal (String "\8658"))
                ]
            ])
     , Text "e"
@@ -247,7 +238,7 @@
                [ Code
                    "typ/math/spacing-04.typ"
                    ( line 7 , column 72 )
-                   (Ident (Identifier "minus"))
+                   (Literal (String "\8722"))
                ]
            ])
     , Text "d"
@@ -260,10 +251,7 @@
                [ Code
                    "typ/math/spacing-04.typ"
                    ( line 7 , column 83 )
-                   (FieldAccess
-                      (Ident (Identifier "r"))
-                      (FieldAccess
-                         (Ident (Identifier "double")) (Ident (Identifier "arrow"))))
+                   (Literal (String "\8658"))
                ]
            ])
     , Text "e"
diff --git a/test/typ/math/style-00.out b/test/typ/math/style-00.out
--- a/test/typ/math/style-00.out
+++ b/test/typ/math/style-00.out
@@ -28,22 +28,5 @@
     ]
 , ParBreak
 ]
---- evaluated ---
-document(body: { 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() })
+"typ/math/style-00.typ" (line 2, column 18):
+Identifier "diff" not found
diff --git a/test/typ/math/style-01.out b/test/typ/math/style-01.out
--- a/test/typ/math/style-01.out
+++ b/test/typ/math/style-01.out
@@ -74,20 +74,20 @@
                [ Code
                    "typ/math/style-01.typ"
                    ( line 4 , column 9 )
-                   (Ident (Identifier "diff"))
+                   (Ident (Identifier "partial"))
                ]
            ])
     , Text ","
     , Code
         "typ/math/style-01.typ"
-        ( line 4 , column 16 )
+        ( line 4 , column 19 )
         (FuncCall
            (Ident (Identifier "upright"))
            [ BlockArg
                [ Code
                    "typ/math/style-01.typ"
-                   ( line 4 , column 24 )
-                   (Ident (Identifier "diff"))
+                   ( line 4 , column 27 )
+                   (Ident (Identifier "partial"))
                ]
            ])
     , Text ","
diff --git a/test/typ/math/style-01.typ b/test/typ/math/style-01.typ
--- a/test/typ/math/style-01.typ
+++ b/test/typ/math/style-01.typ
@@ -1,7 +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), \
+ italic(partial), upright(partial), \
  bb("hello") + bold(cal("world")), \
  mono("SQRT")(x) wreath mono(123 + 456)$
 
diff --git a/test/typ/math/style-05.out b/test/typ/math/style-05.out
--- a/test/typ/math/style-05.out
+++ b/test/typ/math/style-05.out
@@ -18,8 +18,7 @@
     , Code
         "typ/math/style-05.typ"
         ( line 3 , column 5 )
-        (FieldAccess
-           (Ident (Identifier "eq")) (Ident (Identifier "colon")))
+        (Literal (String "\8788"))
     , Code
         "typ/math/style-05.typ"
         ( line 3 , column 8 )
@@ -31,7 +30,7 @@
                , Code
                    "typ/math/style-05.typ"
                    ( line 3 , column 21 )
-                   (Ident (Identifier "minus"))
+                   (Literal (String "\8722"))
                , Text "4"
                ]
            , BlockArg
diff --git a/test/typ/math/syntax-01.out b/test/typ/math/syntax-01.out
--- a/test/typ/math/syntax-01.out
+++ b/test/typ/math/syntax-01.out
@@ -19,7 +19,7 @@
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 2 , column 21 )
-                   (FieldAccess (Ident (Identifier "r")) (Ident (Identifier "arrow")))
+                   (Literal (String "\8594"))
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 2 , column 24 )
@@ -31,10 +31,7 @@
     , Code
         "typ/math/syntax-01.typ"
         ( line 3 , column 5 )
-        (FieldAccess
-           (Ident (Identifier "r"))
-           (FieldAccess
-              (Ident (Identifier "bar")) (Ident (Identifier "arrow"))))
+        (Literal (String "\8614"))
     , Code
         "typ/math/syntax-01.typ"
         ( line 3 , column 9 )
@@ -44,26 +41,19 @@
                [ Code
                    "typ/math/syntax-01.typ"
                    ( line 4 , column 5 )
-                   (FieldAccess
-                      (Ident (Identifier "l"))
-                      (FieldAccess
-                         (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+                   (Literal (String "\10214"))
                , Text "1"
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 4 , column 8 )
-                   (FieldAccess
-                      (Ident (Identifier "r"))
-                      (FieldAccess
-                         (Ident (Identifier "stroked")) (Ident (Identifier "bracket"))))
+                   (Literal (String "\10215"))
                , MAlignPoint
                , Text "if "
                , Text "n"
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 4 , column 19 )
-                   (FieldAccess
-                      (Ident (Identifier "triple")) (Ident (Identifier "gt")))
+                   (Literal (String "\8921"))
                , Text "10"
                ]
            , BlockArg
@@ -71,7 +61,7 @@
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 5 , column 7 )
-                   (FieldAccess (Ident (Identifier "op")) (Ident (Identifier "ast")))
+                   (Literal (String "\8727"))
                , Text "3"
                , MAlignPoint
                , Text "if "
@@ -79,7 +69,7 @@
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 5 , column 19 )
-                   (FieldAccess (Ident (Identifier "not")) (Ident (Identifier "eq")))
+                   (Literal (String "\8800"))
                , Text "5"
                ]
            , BlockArg
@@ -87,7 +77,7 @@
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 6 , column 7 )
-                   (Ident (Identifier "minus"))
+                   (Literal (String "\8722"))
                , Text "0"
                , Code
                    "typ/math/syntax-01.typ"
@@ -97,7 +87,7 @@
                , Code
                    "typ/math/syntax-01.typ"
                    ( line 6 , column 18 )
-                   (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                   (Literal (String "\8230"))
                ]
            ])
     ]
diff --git a/test/typ/math/underover-00.out b/test/typ/math/underover-00.out
--- a/test/typ/math/underover-00.out
+++ b/test/typ/math/underover-00.out
@@ -18,7 +18,7 @@
                , Code
                    "typ/math/underover-00.typ"
                    ( line 3 , column 11 )
-                   (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                   (Literal (String "\8230"))
                , Text "+"
                , Text "5"
                ]
diff --git a/test/typ/math/underover-01.out b/test/typ/math/underover-01.out
--- a/test/typ/math/underover-01.out
+++ b/test/typ/math/underover-01.out
@@ -34,7 +34,7 @@
                , Code
                    "typ/math/underover-01.typ"
                    ( line 4 , column 11 )
-                   (FieldAccess (Ident (Identifier "h")) (Ident (Identifier "dots")))
+                   (Literal (String "\8230"))
                , Text "+"
                , Text "5"
                ]
diff --git a/test/typ/regression/issue41.out b/test/typ/regression/issue41.out
--- a/test/typ/regression/issue41.out
+++ b/test/typ/regression/issue41.out
@@ -7,8 +7,7 @@
         (Code
            "typ/regression/issue41.typ"
            ( line 1 , column 2 )
-           (FieldAccess
-              (Ident (Identifier "circle")) (Ident (Identifier "plus"))))
+           (FieldAccess (Ident (Identifier "o")) (Ident (Identifier "plus"))))
     ]
 , ParBreak
 ]
diff --git a/test/typ/regression/issue41.typ b/test/typ/regression/issue41.typ
--- a/test/typ/regression/issue41.typ
+++ b/test/typ/regression/issue41.typ
@@ -1,1 +1,1 @@
-$plus.circle_2$
+$plus.o_2$
diff --git a/test/typ/regression/issue57.out b/test/typ/regression/issue57.out
--- a/test/typ/regression/issue57.out
+++ b/test/typ/regression/issue57.out
@@ -18,8 +18,7 @@
                                  (Code
                                     "typ/regression/issue57.typ"
                                     ( line 1 , column 5 )
-                                    (FieldAccess
-                                       (Ident (Identifier "op")) (Ident (Identifier "ast")))))
+                                    (Literal (String "\8727"))))
                               (Text "b")
                           ]
                       ]))))
diff --git a/test/typ/regression/show-list-fields-00.out b/test/typ/regression/show-list-fields-00.out
new file mode 100644
--- /dev/null
+++ b/test/typ/regression/show-list-fields-00.out
@@ -0,0 +1,126 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Comment
+, SoftBreak
+, Comment
+, SoftBreak
+, Code
+    "typ/regression/show-list-fields-00.typ"
+    ( line 4 , column 2 )
+    (LetFunc
+       (Identifier "checklist")
+       [ NormalParam (Identifier "body") ]
+       (Block
+          (CodeBlock
+             [ Show
+                 (Just (Ident (Identifier "list")))
+                 (FuncExpr
+                    [ NormalParam (Identifier "it") ]
+                    (Block
+                       (CodeBlock
+                          [ Let
+                              (BasicBind (Just (Identifier "default-marker")))
+                              (If
+                                 [ ( Equals
+                                       (FuncCall
+                                          (Ident (Identifier "type"))
+                                          [ NormalArg
+                                              (FieldAccess
+                                                 (Ident (Identifier "marker"))
+                                                 (Ident (Identifier "it")))
+                                          ])
+                                       (Ident (Identifier "array"))
+                                   , Block
+                                       (CodeBlock
+                                          [ FuncCall
+                                              (FieldAccess
+                                                 (Ident (Identifier "at"))
+                                                 (FieldAccess
+                                                    (Ident (Identifier "marker"))
+                                                    (Ident (Identifier "it"))))
+                                              [ NormalArg (Literal (Int 0)) ]
+                                          ])
+                                   )
+                                 , ( Literal (Boolean True)
+                                   , Block
+                                       (CodeBlock
+                                          [ FieldAccess
+                                              (Ident (Identifier "marker"))
+                                              (Ident (Identifier "it"))
+                                          ])
+                                   )
+                                 ])
+                          , Block
+                              (Content
+                                 [ Text "("
+                                 , Code
+                                     "typ/regression/show-list-fields-00.typ"
+                                     ( line 11 , column 8 )
+                                     (FieldAccess
+                                        (Ident (Identifier "tight")) (Ident (Identifier "it")))
+                                 , Text ","
+                                 , Space
+                                 , Code
+                                     "typ/regression/show-list-fields-00.typ"
+                                     ( line 11 , column 19 )
+                                     (FieldAccess
+                                        (Ident (Identifier "indent")) (Ident (Identifier "it")))
+                                 , Text ","
+                                 , Space
+                                 , Code
+                                     "typ/regression/show-list-fields-00.typ"
+                                     ( line 11 , column 31 )
+                                     (FieldAccess
+                                        (Ident (Identifier "body-indent"))
+                                        (Ident (Identifier "it")))
+                                 , Text ","
+                                 , Space
+                                 , Code
+                                     "typ/regression/show-list-fields-00.typ"
+                                     ( line 11 , column 48 )
+                                     (FieldAccess
+                                        (Ident (Identifier "spacing")) (Ident (Identifier "it")))
+                                 , Text ","
+                                 , Space
+                                 , Code
+                                     "typ/regression/show-list-fields-00.typ"
+                                     ( line 11 , column 61 )
+                                     (Ident (Identifier "default-marker"))
+                                 , Text ")"
+                                 ])
+                          ])))
+             , Ident (Identifier "body")
+             ])))
+, SoftBreak
+, Code
+    "typ/regression/show-list-fields-00.typ"
+    ( line 15 , column 2 )
+    (Show Nothing (Ident (Identifier "checklist")))
+, SoftBreak
+, BulletListItem
+    [ Text "[" , Space , Text "]" , Space , Text "meow" ]
+, ParBreak
+]
+--- evaluated ---
+document(body: { text(body: [
+]), 
+                 text(body: [
+]), 
+                 text(body: [
+]), 
+                 text(body: [
+]), 
+                 text(body: [
+]), 
+                 text(body: [(]), 
+                 text(body: [true]), 
+                 text(body: [, ]), 
+                 text(body: [0.0pt]), 
+                 text(body: [, ]), 
+                 text(body: [0.5em]), 
+                 text(body: [, ]), 
+                 text(body: [auto]), 
+                 text(body: [, ]), 
+                 text(body: [•]), 
+                 text(body: [)]) })
diff --git a/test/typ/regression/show-list-fields-00.typ b/test/typ/regression/show-list-fields-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/regression/show-list-fields-00.typ
@@ -0,0 +1,16 @@
+// https://github.com/jgm/typst-hs/issues/100
+// Settable fields like marker should be accessible in a show rule
+// even when not explicitly set on the element.
+#let checklist(body) = {
+  show list: it => {
+    let default-marker = if type(it.marker) == array {
+      it.marker.at(0)
+    } else {
+      it.marker
+    }
+    [(#it.tight, #it.indent, #it.body-indent, #it.spacing, #default-marker)]
+  }
+  body
+}
+#show: checklist
+- [ ] meow
diff --git a/test/typ/visualize/curve-00.out b/test/typ/visualize/curve-00.out
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/curve-00.out
@@ -0,0 +1,309 @@
+--- parse tree ---
+[ Code
+    "typ/visualize/curve-00.typ"
+    ( line 1 , column 2 )
+    (Set
+       (Ident (Identifier "page"))
+       [ KeyValArg (Identifier "height") (Literal (Numeric 200.0 Pt))
+       , KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt))
+       ])
+, SoftBreak
+, Code
+    "typ/visualize/curve-00.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "table"))
+       [ KeyValArg
+           (Identifier "columns")
+           (Array
+              [ Reg (Literal (Numeric 1.0 Fr))
+              , Reg (Literal (Numeric 1.0 Fr))
+              ])
+       , KeyValArg
+           (Identifier "rows")
+           (Array
+              [ Reg (Literal (Numeric 1.0 Fr))
+              , Reg (Literal (Numeric 1.0 Fr))
+              ])
+       , KeyValArg
+           (Identifier "align")
+           (Plus (Ident (Identifier "center")) (Ident (Identifier "horizon")))
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "curve"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "move")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 0.0 Percent))
+                            , Reg (Literal (Numeric 0.0 Percent))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "cubic")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 4.0 Percent))
+                            , Reg (Negated (Literal (Numeric 4.0 Percent)))
+                            ])
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 46.0 Percent))
+                            , Reg (Literal (Numeric 46.0 Percent))
+                            ])
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 50.0 Percent))
+                            , Reg (Literal (Numeric 50.0 Percent))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "cubic")) (Ident (Identifier "curve")))
+                     [ NormalArg (Literal Auto)
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 4.0 Percent))
+                            , Reg (Literal (Numeric 54.0 Percent))
+                            ])
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 0.0 Percent))
+                            , Reg (Literal (Numeric 50.0 Percent))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "cubic")) (Ident (Identifier "curve")))
+                     [ NormalArg (Literal Auto)
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 46.0 Percent))
+                            , Reg (Negated (Literal (Numeric 4.0 Percent)))
+                            ])
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 50.0 Percent))
+                            , Reg (Literal (Numeric 0.0 Percent))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "close")) (Ident (Identifier "curve")))
+                     [])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "curve"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "purple"))
+              , KeyValArg (Identifier "stroke") (Literal (Numeric 1.0 Pt))
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "move")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 0.0 Pt))
+                            , Reg (Literal (Numeric 0.0 Pt))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 30.0 Pt))
+                            , Reg (Literal (Numeric 30.0 Pt))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 0.0 Pt))
+                            , Reg (Literal (Numeric 30.0 Pt))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 30.0 Pt))
+                            , Reg (Literal (Numeric 0.0 Pt))
+                            ])
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "curve"))
+              [ KeyValArg (Identifier "fill") (Ident (Identifier "blue"))
+              , KeyValArg (Identifier "stroke") (Literal (Numeric 1.0 Pt))
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "move")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 30.0 Percent))
+                            , Reg (Literal (Numeric 0.0 Percent))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "cubic")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 65.0 Percent))
+                            , Reg (Literal (Numeric 30.0 Percent))
+                            ])
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 10.0 Percent))
+                            , Reg (Literal (Numeric 60.0 Percent))
+                            ])
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 30.0 Percent))
+                            , Reg (Literal (Numeric 60.0 Percent))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "cubic")) (Ident (Identifier "curve")))
+                     [ NormalArg (Literal Auto)
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 110.0 Percent))
+                            , Reg (Literal (Numeric 0.0 Percent))
+                            ])
+                     , NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 50.0 Percent))
+                            , Reg (Literal (Numeric 30.0 Percent))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "close")) (Ident (Identifier "curve")))
+                     [])
+              ])
+       , NormalArg
+           (FuncCall
+              (Ident (Identifier "curve"))
+              [ KeyValArg (Identifier "stroke") (Literal (Numeric 5.0 Pt))
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "move")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 0.0 Pt))
+                            , Reg (Literal (Numeric 30.0 Pt))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 30.0 Pt))
+                            , Reg (Literal (Numeric 30.0 Pt))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "line")) (Ident (Identifier "curve")))
+                     [ NormalArg
+                         (Array
+                            [ Reg (Literal (Numeric 15.0 Pt))
+                            , Reg (Literal (Numeric 0.0 Pt))
+                            ])
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (FieldAccess
+                        (Ident (Identifier "close")) (Ident (Identifier "curve")))
+                     [])
+              ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(body: { text(body: [
+]), 
+                 table(align: Axes(center, horizon), 
+                       children: (curve(components: (curve.move(start: (0%, 
+                                                                        0%)), 
+                                                     curve.cubic(control-end: (46%, 
+                                                                               46%), 
+                                                                 control-start: (4%, 
+                                                                                 -4%), 
+                                                                 end: (50%, 
+                                                                       50%)), 
+                                                     curve.cubic(control-end: (4%, 
+                                                                               54%), 
+                                                                 control-start: auto, 
+                                                                 end: (0%, 
+                                                                       50%)), 
+                                                     curve.cubic(control-end: (46%, 
+                                                                               -4%), 
+                                                                 control-start: auto, 
+                                                                 end: (50%, 
+                                                                       0%)), 
+                                                     curve.close()), 
+                                        fill: rgb(100%,25%,21%,100%)), 
+                                  curve(components: (curve.move(start: (0.0pt, 
+                                                                        0.0pt)), 
+                                                     curve.line(end: (30.0pt, 
+                                                                      30.0pt)), 
+                                                     curve.line(end: (0.0pt, 
+                                                                      30.0pt)), 
+                                                     curve.line(end: (30.0pt, 
+                                                                      0.0pt))), 
+                                        fill: rgb(69%,5%,78%,100%), 
+                                        stroke: 1.0pt), 
+                                  curve(components: (curve.move(start: (30%, 
+                                                                        0%)), 
+                                                     curve.cubic(control-end: (10%, 
+                                                                               60%), 
+                                                                 control-start: (65%, 
+                                                                                 30%), 
+                                                                 end: (30%, 
+                                                                       60%)), 
+                                                     curve.cubic(control-end: (110%, 
+                                                                               0%), 
+                                                                 control-start: auto, 
+                                                                 end: (50%, 
+                                                                       30%)), 
+                                                     curve.close()), 
+                                        fill: rgb(0%,45%,85%,100%), 
+                                        stroke: 1.0pt), 
+                                  curve(components: (curve.move(start: (0.0pt, 
+                                                                        30.0pt)), 
+                                                     curve.line(end: (30.0pt, 
+                                                                      30.0pt)), 
+                                                     curve.line(end: (15.0pt, 
+                                                                      0.0pt)), 
+                                                     curve.close()), 
+                                        stroke: 5.0pt)), 
+                       columns: (1.0fr, 1.0fr), 
+                       rows: (1.0fr, 1.0fr)), 
+                 parbreak() })
diff --git a/test/typ/visualize/curve-00.typ b/test/typ/visualize/curve-00.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/curve-00.typ
@@ -0,0 +1,37 @@
+#set page(height: 200pt, width: 200pt)
+#table(
+  columns: (1fr, 1fr),
+  rows: (1fr, 1fr),
+  align: center + horizon,
+  curve(
+    fill: red,
+    curve.move((0%, 0%)),
+    curve.cubic((4%, -4%), (46%, 46%), (50%, 50%)),
+    curve.cubic(auto, (4%, 54%), (0%, 50%)),
+    curve.cubic(auto, (46%, -4%), (50%, 0%)),
+    curve.close(),
+  ),
+  curve(
+    fill: purple,
+    stroke: 1pt,
+    curve.move((0pt, 0pt)),
+    curve.line((30pt, 30pt)),
+    curve.line((0pt, 30pt)),
+    curve.line((30pt, 0pt)),
+  ),
+  curve(
+    fill: blue,
+    stroke: 1pt,
+    curve.move((30%, 0%)),
+    curve.cubic((65%, 30%), (10%, 60%), (30%, 60%)),
+    curve.cubic(auto, (110%, 0%), (50%, 30%)),
+    curve.close(),
+  ),
+  curve(
+    stroke: 5pt,
+    curve.move((0pt, 30pt)),
+    curve.line((30pt, 30pt)),
+    curve.line((15pt, 0pt)),
+    curve.close(),
+  ),
+)
diff --git a/test/typ/visualize/curve-01.out b/test/typ/visualize/curve-01.out
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/curve-01.out
@@ -0,0 +1,96 @@
+--- parse tree ---
+[ Comment
+, SoftBreak
+, Code
+    "typ/visualize/curve-01.typ"
+    ( line 2 , column 2 )
+    (FuncCall
+       (Ident (Identifier "curve"))
+       [ KeyValArg
+           (Identifier "stroke")
+           (Plus (Literal (Numeric 2.0 Pt)) (Ident (Identifier "red")))
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "move")) (Ident (Identifier "curve")))
+              [ NormalArg
+                  (Array
+                     [ Reg (Literal (Numeric 0.0 Pt))
+                     , Reg (Literal (Numeric 0.0 Pt))
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "quad")) (Ident (Identifier "curve")))
+              [ NormalArg
+                  (Array
+                     [ Reg (Literal (Numeric 20.0 Pt))
+                     , Reg (Literal (Numeric 40.0 Pt))
+                     ])
+              , NormalArg
+                  (Array
+                     [ Reg (Literal (Numeric 40.0 Pt))
+                     , Reg (Literal (Numeric 0.0 Pt))
+                     ])
+              , KeyValArg (Identifier "relative") (Literal (Boolean True))
+              ])
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "quad")) (Ident (Identifier "curve")))
+              [ NormalArg (Literal Auto)
+              , NormalArg
+                  (Array
+                     [ Reg (Literal (Numeric 40.0 Pt))
+                     , Reg (Literal (Numeric 0.0 Pt))
+                     ])
+              , KeyValArg (Identifier "relative") (Literal (Boolean True))
+              ])
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "cubic")) (Ident (Identifier "curve")))
+              [ NormalArg (Literal None)
+              , NormalArg
+                  (Array
+                     [ Reg (Literal (Numeric 90.0 Pt))
+                     , Reg (Literal (Numeric 0.0 Pt))
+                     ])
+              , NormalArg
+                  (Array
+                     [ Reg (Literal (Numeric 50.0 Pt))
+                     , Reg (Literal (Numeric 0.0 Pt))
+                     ])
+              ])
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "close")) (Ident (Identifier "curve")))
+              [ KeyValArg (Identifier "mode") (Literal (String "straight")) ])
+       ])
+, ParBreak
+]
+--- evaluated ---
+document(body: { text(body: [
+]), 
+                 curve(components: (curve.move(start: (0.0pt, 
+                                                       0.0pt)), 
+                                    curve.quad(control: (20.0pt, 
+                                                         40.0pt), 
+                                               end: (40.0pt, 
+                                                     0.0pt), 
+                                               relative: true), 
+                                    curve.quad(control: auto, 
+                                               end: (40.0pt, 
+                                                     0.0pt), 
+                                               relative: true), 
+                                    curve.cubic(control-end: (90.0pt, 
+                                                              0.0pt), 
+                                                control-start: none, 
+                                                end: (50.0pt, 
+                                                      0.0pt)), 
+                                    curve.close(mode: "straight")), 
+                       stroke: (thickness: 2.0pt,
+                                color: rgb(100%,25%,21%,100%))), 
+                 parbreak() })
diff --git a/test/typ/visualize/curve-01.typ b/test/typ/visualize/curve-01.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/visualize/curve-01.typ
@@ -0,0 +1,9 @@
+// Test the curve components.
+#curve(
+  stroke: 2pt + red,
+  curve.move((0pt, 0pt)),
+  curve.quad((20pt, 40pt), (40pt, 0pt), relative: true),
+  curve.quad(auto, (40pt, 0pt), relative: true),
+  curve.cubic(none, (90pt, 0pt), (50pt, 0pt)),
+  curve.close(mode: "straight"),
+)
diff --git a/test/typ/visualize/path-00.out b/test/typ/visualize/path-00.out
deleted file mode 100644
--- a/test/typ/visualize/path-00.out
+++ /dev/null
@@ -1,263 +0,0 @@
---- parse tree ---
-[ Code
-    "typ/visualize/path-00.typ"
-    ( line 1 , column 2 )
-    (Set
-       (Ident (Identifier "page"))
-       [ KeyValArg (Identifier "height") (Literal (Numeric 200.0 Pt))
-       , KeyValArg (Identifier "width") (Literal (Numeric 200.0 Pt))
-       ])
-, SoftBreak
-, Code
-    "typ/visualize/path-00.typ"
-    ( line 2 , column 2 )
-    (FuncCall
-       (Ident (Identifier "table"))
-       [ KeyValArg
-           (Identifier "columns")
-           (Array
-              [ Reg (Literal (Numeric 1.0 Fr))
-              , Reg (Literal (Numeric 1.0 Fr))
-              ])
-       , KeyValArg
-           (Identifier "rows")
-           (Array
-              [ Reg (Literal (Numeric 1.0 Fr))
-              , Reg (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
-                     [ Reg
-                         (Array
-                            [ Reg (Literal (Numeric 0.0 Percent))
-                            , Reg (Literal (Numeric 0.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 4.0 Percent))
-                            , Reg (Negated (Literal (Numeric 4.0 Percent)))
-                            ])
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg
-                         (Array
-                            [ Reg (Literal (Numeric 50.0 Percent))
-                            , Reg (Literal (Numeric 50.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 4.0 Percent))
-                            , Reg (Negated (Literal (Numeric 4.0 Percent)))
-                            ])
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg
-                         (Array
-                            [ Reg (Literal (Numeric 0.0 Percent))
-                            , Reg (Literal (Numeric 50.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 4.0 Percent))
-                            , Reg (Literal (Numeric 4.0 Percent))
-                            ])
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg
-                         (Array
-                            [ Reg (Literal (Numeric 50.0 Percent))
-                            , Reg (Literal (Numeric 0.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 4.0 Percent))
-                            , Reg (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
-                     [ Reg (Literal (Numeric 0.0 Pt))
-                     , Reg (Literal (Numeric 0.0 Pt))
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 30.0 Pt))
-                     , Reg (Literal (Numeric 30.0 Pt))
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 0.0 Pt))
-                     , Reg (Literal (Numeric 30.0 Pt))
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 30.0 Pt))
-                     , Reg (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
-                     [ Reg
-                         (Array
-                            [ Reg (Literal (Numeric 30.0 Percent))
-                            , Reg (Literal (Numeric 0.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 35.0 Percent))
-                            , Reg (Literal (Numeric 30.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Negated (Literal (Numeric 20.0 Percent)))
-                            , Reg (Literal (Numeric 0.0 Percent))
-                            ])
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg
-                         (Array
-                            [ Reg (Literal (Numeric 30.0 Percent))
-                            , Reg (Literal (Numeric 60.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Negated (Literal (Numeric 20.0 Percent)))
-                            , Reg (Literal (Numeric 0.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 0.0 Percent))
-                            , Reg (Literal (Numeric 0.0 Percent))
-                            ])
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg
-                         (Array
-                            [ Reg (Literal (Numeric 50.0 Percent))
-                            , Reg (Literal (Numeric 30.0 Percent))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 60.0 Percent))
-                            , Reg (Negated (Literal (Numeric 30.0 Percent)))
-                            ])
-                     , Reg
-                         (Array
-                            [ Reg (Literal (Numeric 60.0 Percent))
-                            , Reg (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
-                     [ Reg (Literal (Numeric 0.0 Pt))
-                     , Reg (Literal (Numeric 30.0 Pt))
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 30.0 Pt))
-                     , Reg (Literal (Numeric 30.0 Pt))
-                     ])
-              , NormalArg
-                  (Array
-                     [ Reg (Literal (Numeric 15.0 Pt))
-                     , Reg (Literal (Numeric 0.0 Pt))
-                     ])
-              ])
-       ])
-, ParBreak
-]
---- evaluated ---
-document(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/typ/visualize/path-00.typ b/test/typ/visualize/path-00.typ
deleted file mode 100644
--- a/test/typ/visualize/path-00.typ
+++ /dev/null
@@ -1,38 +0,0 @@
-#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.out b/test/typ/visualize/path-01.out
deleted file mode 100644
--- a/test/typ/visualize/path-01.out
+++ /dev/null
@@ -1,2 +0,0 @@
---- skipped ---
-
diff --git a/test/typ/visualize/path-01.typ b/test/typ/visualize/path-01.typ
deleted file mode 100644
--- a/test/typ/visualize/path-01.typ
+++ /dev/null
@@ -1,3 +0,0 @@
-// Error: 7-9 path vertex must have 1, 2, or 3 points
-#path(())
-
diff --git a/test/typ/visualize/path-02.out b/test/typ/visualize/path-02.out
deleted file mode 100644
--- a/test/typ/visualize/path-02.out
+++ /dev/null
@@ -1,2 +0,0 @@
---- skipped ---
-
diff --git a/test/typ/visualize/path-02.typ b/test/typ/visualize/path-02.typ
deleted file mode 100644
--- a/test/typ/visualize/path-02.typ
+++ /dev/null
@@ -1,3 +0,0 @@
-// 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.out b/test/typ/visualize/path-03.out
deleted file mode 100644
--- a/test/typ/visualize/path-03.out
+++ /dev/null
@@ -1,2 +0,0 @@
---- skipped ---
-
diff --git a/test/typ/visualize/path-03.typ b/test/typ/visualize/path-03.typ
deleted file mode 100644
--- a/test/typ/visualize/path-03.typ
+++ /dev/null
@@ -1,2 +0,0 @@
-// Error: 7-31 point array must contain exactly two entries
-#path(((0%, 0%), (0%, 0%, 0%)))
diff --git a/test/typ/visualize/stroke-07.out b/test/typ/visualize/stroke-07.out
--- a/test/typ/visualize/stroke-07.out
+++ b/test/typ/visualize/stroke-07.out
@@ -99,124 +99,108 @@
     "typ/visualize/stroke-07.typ"
     ( line 14 , column 2 )
     (FuncCall
-       (Ident (Identifier "path"))
+       (Ident (Identifier "curve"))
        [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
        , KeyValArg (Identifier "stroke") (Literal None)
-       , KeyValArg (Identifier "closed") (Literal (Boolean True))
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "move")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 0.0 Percent))
                      , Reg (Literal (Numeric 0.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Negated (Literal (Numeric 4.0 Percent)))
-                     ])
               ])
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "line")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 50.0 Percent))
                      , Reg (Literal (Numeric 50.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Negated (Literal (Numeric 4.0 Percent)))
-                     ])
               ])
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "line")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 0.0 Percent))
                      , Reg (Literal (Numeric 50.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Literal (Numeric 4.0 Percent))
-                     ])
               ])
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "line")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 50.0 Percent))
                      , Reg (Literal (Numeric 0.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Literal (Numeric 4.0 Percent))
-                     ])
               ])
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "close")) (Ident (Identifier "curve")))
+              [])
        ])
 , ParBreak
 , Code
     "typ/visualize/stroke-07.typ"
     ( line 24 , column 2 )
     (FuncCall
-       (Ident (Identifier "path"))
+       (Ident (Identifier "curve"))
        [ KeyValArg (Identifier "fill") (Ident (Identifier "red"))
        , KeyValArg (Identifier "stroke") (Literal (Numeric 0.0 Pt))
-       , KeyValArg (Identifier "closed") (Literal (Boolean True))
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "move")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 0.0 Percent))
                      , Reg (Literal (Numeric 0.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Negated (Literal (Numeric 4.0 Percent)))
-                     ])
               ])
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "line")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 50.0 Percent))
                      , Reg (Literal (Numeric 50.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Negated (Literal (Numeric 4.0 Percent)))
-                     ])
               ])
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "line")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 0.0 Percent))
                      , Reg (Literal (Numeric 50.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Literal (Numeric 4.0 Percent))
-                     ])
               ])
        , NormalArg
-           (Array
-              [ Reg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "line")) (Ident (Identifier "curve")))
+              [ NormalArg
                   (Array
                      [ Reg (Literal (Numeric 50.0 Percent))
                      , Reg (Literal (Numeric 0.0 Percent))
                      ])
-              , Reg
-                  (Array
-                     [ Reg (Literal (Numeric 4.0 Percent))
-                     , Reg (Literal (Numeric 4.0 Percent))
-                     ])
               ])
+       , NormalArg
+           (FuncCall
+              (FieldAccess
+                 (Ident (Identifier "close")) (Ident (Identifier "curve")))
+              [])
        ])
 , ParBreak
 ]
@@ -264,21 +248,27 @@
                        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%)))), 
+                 curve(components: (curve.move(start: (0%, 
+                                                       0%)), 
+                                    curve.line(end: (50%, 
+                                                     50%)), 
+                                    curve.line(end: (0%, 
+                                                     50%)), 
+                                    curve.line(end: (50%, 
+                                                     0%)), 
+                                    curve.close()), 
+                       fill: rgb(100%,25%,21%,100%), 
+                       stroke: none), 
                  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%)))), 
+                 curve(components: (curve.move(start: (0%, 
+                                                       0%)), 
+                                    curve.line(end: (50%, 
+                                                     50%)), 
+                                    curve.line(end: (0%, 
+                                                     50%)), 
+                                    curve.line(end: (50%, 
+                                                     0%)), 
+                                    curve.close()), 
+                       fill: rgb(100%,25%,21%,100%), 
+                       stroke: 0.0pt), 
                  parbreak() })
diff --git a/test/typ/visualize/stroke-07.typ b/test/typ/visualize/stroke-07.typ
--- a/test/typ/visualize/stroke-07.typ
+++ b/test/typ/visualize/stroke-07.typ
@@ -11,22 +11,22 @@
 #table(columns: 2, stroke: none)[A][B]
 #table(columns: 2, stroke: 0pt)[A][B]
 
-#path(
+#curve(
   fill: red,
   stroke: none,
-  closed: true,
-  ((0%, 0%), (4%, -4%)),
-  ((50%, 50%), (4%, -4%)),
-  ((0%, 50%), (4%, 4%)),
-  ((50%, 0%), (4%, 4%)),
+  curve.move((0%, 0%)),
+  curve.line((50%, 50%)),
+  curve.line((0%, 50%)),
+  curve.line((50%, 0%)),
+  curve.close(),
 )
 
-#path(
+#curve(
   fill: red,
   stroke: 0pt,
-  closed: true,
-  ((0%, 0%), (4%, -4%)),
-  ((50%, 50%), (4%, -4%)),
-  ((0%, 50%), (4%, 4%)),
-  ((50%, 0%), (4%, 4%)),
+  curve.move((0%, 0%)),
+  curve.line((50%, 50%)),
+  curve.line((0%, 50%)),
+  curve.line((50%, 0%)),
+  curve.close(),
 )
diff --git a/typst.cabal b/typst.cabal
--- a/typst.cabal
+++ b/typst.cabal
@@ -1,10 +1,10 @@
 cabal-version:      2.4
 name:               typst
-version:            0.10
+version:            0.11
 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.13
+                    formatting language. This library targets typst 0.15
                     and currently offers only partial support.
 license:            BSD-3-Clause
 license-file:       LICENSE
@@ -62,7 +62,7 @@
 
     -- other-extensions:
     build-depends:    base >= 4.14 && < 5,
-                      typst-symbols >= 0.2 && < 0.3,
+                      typst-symbols >= 0.3 && < 0.4,
                       mtl,
                       vector,
                       parsec,
@@ -81,7 +81,8 @@
                       regex-tdfa,
                       array,
                       time,
-                      pretty
+                      pretty,
+                      erf
     hs-source-dirs:   src
     if os(darwin)
       cpp-options: -D__MACOS__
