-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Bricks is a lazy functional language based on Nix. -- -- Bricks is a lazy functional language based on Nix. This package -- provides parsing, rendering, and evaluation for the Bricks language. @package bricks @version 0.0.0.4 -- | Bricks is a lazy functional language that resembles Nix. -- -- This module serves as fairly exhaustive overview of the entire -- package, and should usually serve as your go-to place to start when -- reading the Bricks documentation if you want an in-depth -- understanding of how everything works. It is a fairly large -- module, and probably ought to be used via a qualified import. -- --
--   import qualified Bricks
--   
-- -- If you just want to use Bricks for common cases, look at the simple -- API in Bricks.Prelude instead. That module is much smaller and -- is designed to be imported unqualified. -- --
--   import Bricks.Prelude
--   
module Bricks data Expression :: * -- | A variable, such as x Expr'Var :: Var -> Expression -- | A string, quoted in the traditional form using a single double-quote -- (" ... ") Expr'Str :: Str'Dynamic -> Expression -- | A string in "indented string" form, using two single-quotes -- ('' ... '') Expr'Str'Indented :: InStr -> Expression -- | A list is an ordered collection of expressions. Expr'List :: List -> Expression -- | A dict is an unordered enumerated mapping from strings. Expr'Dict :: Dict -> Expression -- | A dot expression (named after the . character it contains) -- looks up the value at a particular key in a dict. Expr'Dot :: Dot -> Expression -- | A lambda expression x: y where x is the parameter. Expr'Lambda :: Lambda -> Expression -- | The application of a function to a single argument. Expr'Apply :: Apply -> Expression -- | A let-in expression consists of a list of variable -- bindings followed by an expression. Expr'Let :: Let -> Expression expression'source :: Expression -> Maybe SourceRange expression'discardSource :: Expression -> Expression -- | Render an expression. -- --

Examples

-- --
--   >>> :{
--   
--   >>> render'expression renderContext'terse
--   
--   >>> (lambda
--   
--   >>> (param "a" <> pattern
--   
--   >>> [ dict'param "f"
--   
--   >>> , dict'param "b" & def (apply (var "g") (var "x"))
--   
--   >>> ] <> ellipsis)
--   
--   >>> (apply (var "f") (var "b")))
--   
--   >>> :}
--   "a@{ f, b ? g x, ... }: f b"
--   
render'expression :: Render Expression -- | Render an expression in a list context. render'expression'listContext :: Render Expression -- | Render an expression in the context of the left-hand side of a -- Dot. render'expression'dotLeftContext :: Render Expression -- | Render an expression in the context of the left-hand side of an -- Apply. render'expression'applyLeftContext :: Render Expression -- | Render an expression in the context of the right-hand side of an -- Apply. render'expression'applyRightContext :: Render Expression render'expression'inParens :: Render Expression render'expression'dictKey :: Render Expression -- | The primary, top-level expression parser. This is what you use to -- parse a .nix file. -- --

Examples

-- --
--   >>> parseTest parse'expression ""
--   parse error at (line 1, column 1):
--   unexpected end of input
--   expecting expression
--   
parse'expression :: Parser Expression -- | Parser for a parenthesized expression, from opening parenthesis to -- closing parenthesis. parse'expression'paren :: Parser Expression parse'expression'antiquote :: Parser Expression -- | Parser for an expression in a context that is expecting a dict key. -- -- One of: -- -- parse'expression'dictKey :: Parser Expression -- | Parser for a list of expressions in a list literal ([ x y z -- ]) or in a chain of function arguments (f x y z). -- --

Examples

-- --
--   >>> parseTest parse'expressionList ""
--   []
--   
-- --
--   >>> parseTest (length <$> parse'expressionList) "x \"one two\" (a: b) (c d)"
--   4
--   
-- --
--   >>> parseTest (length <$> parse'expressionList) "(x \"one two\" (a: b) (c d))"
--   1
--   
parse'expressionList :: Parser [Expression] -- | Parser for a single item within an expression list -- (expressionListP). This expression is not a lambda, a -- function application, a let-in expression, or a -- with expression. -- --

Examples

-- --
--   >>> parseTest parse'expressionList'1 "ab.xy"
--   {- 1:1-1:6 -} dot ({- 1:1-1:3 -} var "ab") ({- 1:4-1:6 -} str [{- 1:4-1:6 -} "xy"])
--   
-- --
--   >>> :{
--   
--   >>> parseTest (expression'discardSource <$> parse'expressionList'1)
--   
--   >>> "(x: f x x) y z"
--   
--   >>> :}
--   lambda (param "x") (apply (apply (var "f") (var "x")) (var "x"))
--   
-- --
--   >>> :{
--   
--   >>> parseTest (expression'discardSource <$> parse'expressionList'1)
--   
--   >>> "{ a = b; }.a y"
--   
--   >>> :}
--   dot (dict [dict'eq (str ["a"]) (var "b")]) (str ["a"])
--   
parse'expressionList'1 :: Parser Expression -- | Like parse'expressionList'1, but with the further restriction -- that the expression may not be a Dot. -- --

Examples

-- --
--   >>> parseTest parse'expressionList'1'noDot "ab.xy"
--   {- 1:1-1:3 -} var "ab"
--   
-- --
--   >>> :{
--   
--   >>> parseTest (expression'discardSource <$> parse'expressionList'1'noDot)
--   
--   >>> "(x: f x x) y z"
--   
--   >>> :}
--   lambda (param "x") (apply (apply (var "f") (var "x")) (var "x"))
--   
-- --
--   >>> :{
--   
--   >>> parseTest (expression'discardSource <$> parse'expressionList'1'noDot)
--   
--   >>> "{ a = b; }.a y"
--   
--   >>> :}
--   dict [dict'eq (str ["a"]) (var "b")]
--   
parse'expressionList'1'noDot :: Parser Expression -- | A variable x, as in the lambda calculus sense, is in -- one of two positions: -- --
    --
  1. A binding, which may take a number of forms: - x: ... -- (Param'Name) - let x = ... ; in ... -- (LetBinding'Eq) - let inherit ( ... ) x; in -- ... (LetBinding'Inhherit)
  2. --
  3. A contextual reference to a lambda head or let binding in -- which x is bound: - The expression x by itself - An -- inherit binding in a dict expression -- (DictBinding'Inherit'Var)
  4. --
-- --

Syntax

-- -- Variables are always written without quotes. -- -- Unquoted strings are used for variables (Expr'Var) and places -- that bind variables (Lambda and Let). data Var :: * Var :: UnquotedString -> Maybe SourceRange -> Var [var'str] :: Var -> UnquotedString [var'source] :: Var -> Maybe SourceRange var'text :: Var -> Text -- | Render an unquoted string in unquoted form. render'var :: Render Var parse'var :: Parser Var var'to'str'static :: Var -> Str'Static var'to'str'dynamic :: Var -> Str'Dynamic var'discardSource :: Var -> Var -- | Insert escape sequences for rendering normal double-quoted -- (") strings. str'escape :: Text -> Text -- | Parser for at least one normal character, within a normally-quoted -- string context, up to but not including the end of the string or the -- start of an antiquotation. parse'str'within'normalQ :: Parser Str'Static parse'str'escape'normalQ :: Parser Text -- | A fixed string value. We use the description "static" to mean the -- string may not contain antiquotation, in contrast with -- Str'Dynamic which can. data Str'Static :: * Str'Static :: Text -> Maybe SourceRange -> Str'Static [str'static'text] :: Str'Static -> Text [str'static'source] :: Str'Static -> Maybe SourceRange str'static'append :: Str'Static -> Str'Static -> Str'Static str'static'discardSource :: Str'Static -> Str'Static str'static'to'dynamic :: Str'Static -> Str'Dynamic -- | Render a static string, in unquoted form if possible. render'strStatic'unquotedIfPossible :: Render Str'Static -- | Render a static string, in quoted form. render'strStatic'quoted :: Render Str'Static -- | Parser for a static string which may be either quoted or unquoted. -- --

Examples

-- --
--   >>> parseTest parse'strStatic "\"hello\""
--   {- 1:1-1:8 -} "hello"
--   
-- --
--   >>> parseTest parse'strStatic "hello"
--   {- 1:1-1:6 -} "hello"
--   
-- --
--   >>> parseTest parse'strStatic "\"a b\""
--   {- 1:1-1:6 -} "a b"
--   
-- --
--   >>> parseTest parse'strStatic "a b"
--   {- 1:1-1:2 -} "a"
--   
-- -- By "static," we mean that the string may not contain -- antiquotation: -- --
--   >>> parseTest parse'strStatic "\"a${x}b\" xyz"
--   parse error at (line 1, column 5):
--   antiquotation is not allowed in this context
--   
parse'strStatic :: Parser Str'Static -- | Parser for a static string that is quoted. parse'strStatic'quoted :: Parser Str'Static -- | Parser for an unquoted static string. parse'strStatic'unquoted :: Parser Str'Static -- | A dynamic string is a quoted string expression, which may be a -- simple string like "hello" or a more complex string -- containing antiquotation like "Hello, my name is ${name}!". -- See Expr'Str. -- -- We use the description "dynamic" to mean the string may contain -- antiquotation, in contrast with Str'Static which cannot. -- -- This is the type of string expressions (Expr'Str). -- --

String syntax

-- -- A string may be quoted either in the traditional form using a -- single double-quote (" ... "): -- --
--   "one\ntwo"
--   
-- -- or in the "indented string" form using two single-quotes ('' -- ... ''): -- --
--   ''
--     one
--     two
--   ''
--   
-- -- Both of these examples reduce to the same value, because leading -- whitespace is stripped from indented strings. -- -- Either may contain "antiquotation" (also known as "string -- interpolation") to conveniently concatenate string-valued variables -- into the string. -- --
--   "Hello, my name is ${name}!"
--   
-- -- Normal strings may contain the following escape sequences: -- -- -- -- The indented string form does not interpret any escape sequences. data Str'Dynamic :: * Str'Dynamic :: Seq Str'1 -> Maybe SourceRange -> Str'Dynamic [strDynamic'toSeq] :: Str'Dynamic -> Seq Str'1 [strDynamic'source] :: Str'Dynamic -> Maybe SourceRange -- | One part of a Str'Dynamic. data Str'1 :: * Str'1'Literal :: Str'Static -> Str'1 Str'1'Antiquote :: Expression -> Str'1 str'1'discardSource :: Str'1 -> Str'1 str'dynamic'append :: Str'Dynamic -> Str'Dynamic -> Str'Dynamic -- | Simplify a dynamic string by combining consecutive pieces of static -- text. -- --

Examples

-- --
--   >>> :{
--   
--   >>> str :: Text -> Str'1
--   
--   >>> str x = Str'1'Literal $ Str'Static x Nothing
--   
--   >>> 
--   
--   >>> var :: Text -> Str'1
--   
--   >>> var x = Str'1'Antiquote . Expr'Var $
--   
--   >>> Var (unquotedString'orThrow x) Nothing
--   
--   >>> :}
--   
-- --
--   >>> :{
--   
--   >>> str'dynamic'normalize $ Str'Dynamic (Seq.fromList
--   
--   >>> [str "a", str "b", var "x", var "y", str "c", str "d"]) Nothing
--   
--   >>> :}
--   str ["ab", antiquote (var "x"), antiquote (var "y"), "cd"]
--   
str'dynamic'normalize :: Str'Dynamic -> Str'Dynamic str'dynamic'discardSource :: Str'Dynamic -> Str'Dynamic -- |

Examples

-- --
--   >>> str'dynamic'to'static $ Str'Dynamic (Seq.fromList []) Nothing
--   Just ""
--   
-- --
--   >>> a = Str'1'Literal (Str'Static "hi" Nothing)
--   
-- --
--   >>> b = Str'1'Antiquote $ Expr'Var $ Var (unquotedString'orThrow "x") Nothing
--   
-- --
--   >>> str'dynamic'to'static $ Str'Dynamic (Seq.fromList [ a ]) Nothing
--   Just "hi"
--   
-- --
--   >>> str'dynamic'to'static $ Str'Dynamic (Seq.fromList [ a, b ]) Nothing
--   Nothing
--   
str'dynamic'to'static :: Str'Dynamic -> Maybe Str'Static -- | Render a dynamic string, in unquoted form if possible. render'strDynamic'unquotedIfPossible :: Render Str'Dynamic -- | Render a dynamic string, in quoted form. render'strDynamic'quoted :: Render Str'Dynamic render'str'1 :: Render Str'1 -- | Parser for a dynamic string enclosed in quotes (" ... -- "). parse'str'dynamic :: Parser Str'Dynamic -- | A string that can be rendered unquoted. Unquoted strings are -- restricted to a conservative set of characters; see -- text'canBeUnquoted for the full rules. -- -- This type does not represent a particular part of Bricks syntax, but -- it is a wrapper for Text that enforces the limitations of -- strings at various places in the Bricks syntax. -- --

Construction

-- -- -- --

Deconstruction

-- -- -- --

See also

-- -- data UnquotedString :: * -- |

Properties

-- -- unquotedString'try :: Text -> Maybe UnquotedString -- | Throws an exception if the string cannot render unquoted. unquotedString'orThrow :: Text -> UnquotedString unquotedString'text :: UnquotedString -> Text -- | Whether a string having this name can be rendered without quoting it. -- --

Requirements for unquoted strings

-- -- We allow a string to render unquoted if all these conditions are met: -- -- -- --

Properties

-- -- -- --

Examples

-- --
--   >>> text'canBeUnquoted "-ab_c"
--   True
--   
-- --
--   >>> text'canBeUnquoted ""
--   False
--   
-- --
--   >>> text'canBeUnquoted "a\"b"
--   False
--   
-- --
--   >>> text'canBeUnquoted "let"
--   False
--   
text'canBeUnquoted :: Text -> Bool -- | Whether the character is allowed to be included in an -- UnquotedString. Such characters are letters, +, -- -, *, /, and _. -- -- This is used in the implementation of text'canBeUnquoted. char'canBeUnquoted :: Char -> Bool -- | Parser for an unquoted string. Unquoted strings are restricted to a -- conservative set of characters, and they may not be any of the -- keywords. See text'canBeUnquoted for a complete description of -- the unquoted string rules. -- --

Examples

-- --
--   >>> parseTest parse'strUnquoted "abc"
--   ("abc",1:1-1:4)
--   
-- -- Here the parser consumes letters up to but not including {, -- because that character does not satisfy char'canBeUnquoted: -- --
--   >>> parseTest parse'strUnquoted "ab{c"
--   ("ab",1:1-1:3)
--   
-- -- "let" does not parse as an unquoted string because let is a -- keyword: -- --
--   >>> parseTest parse'strUnquoted "let"
--   parse error at (line 1, column 4):
--   unexpected end of input
--   
-- -- This parser does not parse quoted strings: -- --
--   >>> parseTest parse'strUnquoted "\"abc\""
--   parse error at (line 1, column 1):
--   unexpected "\""
--   
parse'strUnquoted :: Parser (UnquotedString, SourceRange) -- | An "indented string literal," delimited by two single-quotes -- ''. -- -- This type of literal is called "indented" because the parser -- automatically removes leading whitespace from the string -- (inStr'dedent), which makes it convenient to use these literals -- for multi-line strings within an indented expression without the -- whitespace from indentation ending up as part of the string. data InStr :: * InStr :: Seq InStr'1 -> Maybe SourceRange -> InStr [inStr'toSeq] :: InStr -> Seq InStr'1 [inStr'source] :: InStr -> Maybe SourceRange -- | One line of an InStr. data InStr'1 :: * InStr'1 :: Natural -> Maybe SourceRange -> Seq Str'1 -> Maybe Str'Static -> InStr'1 -- | The number of leading space characters. We store this separately for -- easier implementation of inStr'dedent. [inStr'1'level] :: InStr'1 -> Natural -- | The source position of the leading space characters [inStr'1'indentSource] :: InStr'1 -> Maybe SourceRange -- | The meat of the line, after any leading spaces and before the line -- break. [inStr'1'str] :: InStr'1 -> Seq Str'1 -- | The line break at the end, if any; all lines but the last one should -- have a line break [inStr'1'lineBreak] :: InStr'1 -> Maybe Str'Static inStr'1'toStrParts :: InStr'1 -> Seq Str'1 inStr'toList :: InStr -> [InStr'1] inStr'to'strDynamic :: InStr -> Str'Dynamic -- | Determine how many characters of whitespace to strip from an indented -- string. inStr'level :: InStr -> Natural -- | Determine the minimum indentation of any nonempty line, and remove -- that many space characters from the front of every line. inStr'dedent :: InStr -> InStr -- | Remove any empty lines from the beginning or end of an indented -- string, and remove the newline from the final nonempty line. inStr'trim :: InStr -> InStr inStr'discardSource :: InStr -> InStr inStr'1'discardSource :: InStr'1 -> InStr'1 render'str'indented :: Render InStr render'str'indented'1 :: Render InStr'1 -- | Parser for a dynamic string enclosed in "indented string" format, -- delimited by two single-quotes '' ... ''. -- -- This form of string does not have any escape sequences. Therefore the -- only way to express '' or ${ within an indented -- string is to antiquote them. -- --

Examples

-- --
--   >>> x = "''${\"''\"} and ${\"\\${\"}''"
--   
-- --
--   >>> putStrLn x
--   ''${"''"} and ${"\${"}''
--   
-- --
--   >>> parseTest (inStr'discardSource <$> parse'inStr) x
--   str'indented [indent 0 [antiquote (str ["''"]), " and ", antiquote (str ["${"])] Nothing]
--   
-- --
--   >>> parseTest parse'inStr x
--   {- 1:1-1:25 -} str'indented [indent {- 1:3-1:3 -} 0 [antiquote ({- 1:5-1:9 -} str [{- 1:6-1:8 -} "''"]), {- 1:10-1:15 -} " and ", antiquote ({- 1:17-1:22 -} str [{- 1:18-1:21 -} "${"])] Nothing]
--   
parse'inStr :: Parser InStr -- | Parser for a single line of an InStr. parse'inStr'1 :: Parser InStr'1 -- | A list is an ordered collection. -- --

Syntax

-- -- A list expression (Expr'List) starts with [, ends with -- ], and contains any number of expressions in between. -- -- The empty list: -- --
--   [ ]
--   
-- -- A list containing three variables: -- --
--   [ a b c ]
--   
-- -- Lambdas, function applications, let-in expressions, -- and with expressions must be parenthesized when in a list. -- --
--   [
--     (x: f x y)
--     (g y)
--     (let a = y; in f a a)
--     (with d; f x a)
--   ]
--   
data List :: * List :: Seq Expression -> Maybe SourceRange -> List [list'expressions] :: List -> Seq Expression [list'source] :: List -> Maybe SourceRange list'discardSource :: List -> List -- | Render a list literal ([ ... ]). render'list :: Render List -- | Parser for a list expression ([ ... ]). -- --

Examples

-- --
--   >>> parseTest parse'list "[]"
--   {- 1:1-1:3 -} list []
--   
-- --
--   >>> :{
--   
--   >>> parseTest (list'discardSource <$> parse'list)
--   
--   >>> "[x \"one\" (a: b) (c d)]"
--   
--   >>> :}
--   list [var "x", str ["one"], lambda (param "a") (var "b"), apply (var "c") (var "d")]
--   
parse'list :: Parser List -- | A dict is an unordered enumerated mapping from strings. -- --

Syntax

-- -- A dict expression (Expr'Dict) starts with { or rec -- {, ends with }, and contains any number of -- DictBindings in between. -- -- The empty dict (with no bindings): -- --
--   { }
--   
-- -- A dict with two bindings: -- --
--   {
--     a = "one";
--     b = "one two";
--   }
--   
-- -- By default, dict bindings cannot refer to each other. For that, you -- need the rec keyword to create a recursive dict. -- --
--   rec {
--     a = "one";
--     b = "${a} two";
--   }
--   
-- -- In either case, the order of the bindings does not matter. -- -- The left-hand side of a dict binding may be a quoted string (in the -- traditional " ... " style, not the indented-string -- '' style), which make it possible for them to be strings that -- otherwise couldn't be expressed unquoted, such as strings containing -- spaces: -- --
--   { "a b" = "c"; }
--   
-- -- The left-hand side of a dict may even be an arbitrary expression, -- using the ${ ... } form: -- --
--   let x = "a b"; in { ${x} = "c"; }
--   
-- -- Dicts also support the inherit keyword: -- --
--   { inherit a; inherit (x) c d; }
--   
-- -- The previous expression is equivalent to: -- --
--   { a = a; c = x.c; d = x.d; }
--   
data Dict :: * Dict :: Bool -> Seq DictBinding -> Maybe SourceRange -> Dict -- | Whether the dict is recursive (denoted by the rec keyword) [dict'rec] :: Dict -> Bool -- | The bindings (everything between { and }) [dict'bindings] :: Dict -> Seq DictBinding [dict'source] :: Dict -> Maybe SourceRange keyword'rec :: Keyword dict'discardSource :: Dict -> Dict -- | Render a dict literal ({ ... }). render'dict :: Render Dict -- | Parser for a dict expression, either recursive (rec keyword) -- or not. -- --

Examples

-- --
--   >>> parseTest parse'dict "{}"
--   {- 1:1-1:3 -} dict []
--   
-- --
--   >>> parseTest parse'dict "rec { }"
--   {- 1:1-1:8 -} rec'dict []
--   
-- --
--   >>> :{
--   
--   >>> parseTest (dict'discardSource <$> parse'dict)
--   
--   >>> "{ a = b; inherit (x) y z \"s t\"; }"
--   
--   >>> :}
--   dict [dict'eq (str ["a"]) (var "b"), dict'inherit'from (var "x") ["y", "z", "s t"]]
--   
parse'dict :: Parser Dict -- | Parser for a recursive (rec keyword) dict. -- --

Examples

-- --
--   >>> parseTest parse'dict'rec "rec { }"
--   {- 1:1-1:8 -} rec'dict []
--   
-- --
--   >>> :{
--   
--   >>> parseTest (dict'discardSource <$> parse'dict'rec)
--   
--   >>> "rec { a = \"1\"; b = \"${a}2\"; }"
--   
--   >>> :}
--   rec'dict [dict'eq (str ["a"]) (str ["1"]), dict'eq (str ["b"]) (str [antiquote (var "a"), "2"])]
--   
parse'dict'rec :: Parser Dict -- | Parser for a non-recursive (no rec keyword) dict. -- --

Examples

-- --
--   >>> parseTest parse'dict'noRec "{ }"
--   {- 1:1-1:4 -} dict []
--   
-- --
--   >>> :{
--   
--   >>> parseTest (dict'discardSource <$> parse'dict'noRec)
--   
--   >>> "{ a = \"1\"; b = \"${a}2\"; }"
--   
--   >>> :}
--   dict [dict'eq (str ["a"]) (str ["1"]), dict'eq (str ["b"]) (str [antiquote (var "a"), "2"])]
--   
parse'dict'noRec :: Parser Dict -- | A binding within a Dict. data DictBinding :: * -- | A binding of the form x = y; DictBinding'Eq :: Expression -> Expression -> DictBinding DictBinding'Inherit'Dict :: Expression -> Seq Str'Static -> DictBinding DictBinding'Inherit'Var :: Seq Var -> DictBinding dictBinding'discardSource :: DictBinding -> DictBinding -- | Render a binding within a Dict, including the trailing -- semicolon. render'dictBinding :: Render DictBinding parse'dictBinding :: Parser DictBinding parse'dictBinding'inherit :: Parser DictBinding parse'dictBinding'eq :: Parser DictBinding -- | The dot function looks up a value (or a list of values) from a -- dict. -- --

Syntax

-- -- A dot expression is named after the . character it contains. -- a.b looks up value at key b in the dict a. -- -- The examples in this section all reduce to "Z". -- --
--   { a = "Z"; }.a
--   
-- --
--   let x = { a = "Z"; }; in x.a
--   
-- --
--   { x = { a = "Z"; }; }.x.a
--   
-- -- The right-hand side of a dot may be a quoted string (in the -- traditional " ... " style, not the indented-string -- '' style): -- --
--   { a = "Z"; }."a"
--   
-- -- The right-hand side of a dot may even be an arbitrary expression, -- using the ${ ... } form: -- --
--   { a = "Z"; }.${ let b = "a"; in b }
--   
data Dot :: * Dot :: Expression -> Expression -> Maybe SourceRange -> Dot [dot'dict] :: Dot -> Expression [dot'key] :: Dot -> Expression [dot'source] :: Dot -> Maybe SourceRange dot'discardSource :: Dot -> Dot expression'applyDots :: Expression -> [Expression] -> Expression -- | Render a dot expression (a.b). render'dot :: Render Dot -- | Parser for a chain of dict lookups (like .a.b.c) on the -- right-hand side of a Dot expression. -- --

Examples

-- --
--   >>> parseTest parse'dot'rhs'chain ""
--   []
--   
-- --
--   >>> parseTest parse'dot'rhs'chain ".abc"
--   [{- 1:2-1:5 -} str [{- 1:2-1:5 -} "abc"]]
--   
-- --
--   >>> :{
--   
--   >>> parseTest (fmap expression'discardSource <$> parse'dot'rhs'chain)
--   
--   >>> ".a.${b}.\"c\".\"d${e}\""
--   
--   >>> :}
--   [str ["a"],var "b",str ["c"],str ["d", antiquote (var "e")]]
--   
parse'dot'rhs'chain :: Parser [Expression] -- | A function expressed as a lambda abstraction. -- --

Syntax

-- -- A lambda expression (Expr'Lambda) has the form x: y -- where x is the function parameter to bind in the function -- body y. -- -- This is a function that turns a name into a greeting: -- --
--   name: "Hello, ${name}!"
--   
-- -- The function parameter can also be a dict pattern, which looks -- like this: -- --
--   { a, b, c ? "another" }: "Hello, ${a}, ${b}, and ${c}!"
--   
-- -- That function accepts a dict and looks up the keys a, -- b, and c from it, applying the default value -- "another" to c if it is not present in the dict. -- Dict patterns therefore give us something that resembles functions -- with named parameters and default arguments. -- -- By default, a lambda defined with a dict pattern fails to evaluate if -- the dict argument contains keys that are not listed in the pattern. To -- prevent it from failing, you can end the pattern with ... : -- --
--   ({ a, ... }: x) { a = "1"; b = "2"; }
--   
-- -- Every function has a single parameter. If you need multiple -- parameters, you have to curry: -- --
--   a: b: [ a b ]
--   
data Lambda :: * Lambda :: Param -> Expression -> Maybe SourceRange -> Lambda -- | Declaration of the function's parameter [lambda'head] :: Lambda -> Param -- | Body of the function; what it evaluates to [lambda'body] :: Lambda -> Expression [lambda'source] :: Lambda -> Maybe SourceRange lambda'discardSource :: Lambda -> Lambda -- | Render a lambda expression (x: y). render'lambda :: Render Lambda -- | Parser for a lambda expression (x: y). -- --

Examples

-- --
--   >>> test = parseTest (lambda'discardSource <$> parse'lambda)
--   
-- --
--   >>> test "x: [x x \"a\"]"
--   lambda (param "x") (list [var "x", var "x", str ["a"]])
--   
-- --
--   >>> test "{a,b}:a"
--   lambda (pattern [dict'param "a", dict'param "b"]) (var "a")
--   
-- --
--   >>> test "{ ... }: \"x\""
--   lambda (pattern [] <> ellipsis) (str ["x"])
--   
-- --
--   >>> test "a@{ f, b ? g x, ... }: f b"
--   lambda (param "a" <> pattern [dict'param "f", dict'param "b" & def (apply (var "g") (var "x"))] <> ellipsis) (apply (var "f") (var "b"))
--   
-- --
--   >>> test "a: b: \"x\""
--   lambda (param "a") (lambda (param "b") (str ["x"]))
--   
parse'lambda :: Parser Lambda -- | A parameter to a Lambda. All functions have a single parameter, -- but it's more complicated than that because it may also include dict -- destructuring. data Param :: * -- | A simple single-parameter function Param'Name :: Var -> Param -- | Dict destructuring, which gives you something resembling multiple -- named parameters with default values Param'DictPattern :: DictPattern -> Param -- | Both a param name and a dict pattern, separated by the -- @ keyword Param'Both :: Var -> DictPattern -> Param param'discardSource :: Param -> Param -- | Render a lambda parameter: everything from the beginning of a lambda, -- up to but not including the : that separates the head from -- the body of the lambda. render'param :: Render Param -- | Parser for a function parameter (the beginning of a Lambda), -- including the colon. This forms part of parse'expression, so it -- backtracks in places where it has overlap with other types of -- expressions. parse'param :: Parser Param -- | Parser for a parameter that starts with a variable. This could be a -- simple param that consists only of only the variable, or the -- variable may be followed by a dict pattern. parse'param'var :: Parser Param -- | Parser for a param that has no variable, only a a dict pattern. This -- parser backtracks because the beginning of a dict pattern looks like -- the beginning of a dict expression. parse'param'noVar :: Parser Param -- | A type of function parameter (Param) that does dict -- destructuring. data DictPattern :: * DictPattern :: Seq DictPattern'1 -> Bool -> DictPattern -- | The list of keys to pull out of the dict, along with any default value -- each may have [dictPattern'items] :: DictPattern -> Seq DictPattern'1 -- | Whether to allow additional keys beyond what is listed in the items, -- corresponding to the ... keyword [dictPattern'ellipsis] :: DictPattern -> Bool dictPattern'discardSource :: DictPattern -> DictPattern -- | One item within a DictPattern. data DictPattern'1 :: * DictPattern'1 :: Var -> Maybe Expression -> DictPattern'1 -- | The name of the key to pull out of the dict [dictPattern'1'name] :: DictPattern'1 -> Var -- | The default value to be used if the key is not present in the dict [dictPattern'1'default] :: DictPattern'1 -> Maybe Expression dictPattern'1'discardSource :: DictPattern'1 -> DictPattern'1 -- | Render a dict pattern ({ a, b ? c, ... }). render'dictPattern :: Render DictPattern -- | Render a single item in a DictPattern. render'dictPattern'1 :: Render DictPattern'1 -- | Parser for a dict pattern (the type of lambda parameter that does dict -- destructuring. This parser does not backtrack. parse'dictPattern :: Parser DictPattern -- | This is used in a lookahead by parse'param to determine whether -- we're about to start parsing a DictPattern. parse'dictPattern'start :: Parser () -- | The application of a function to a single argument. -- --

Syntax

-- -- An function application expression (Expr'Apply) looks like -- this: -- --
--   f x
--   
-- -- If a function has multiple (curried) parameters, you can chain them -- together like so: -- --
--   f x y z
--   
data Apply :: * Apply :: Expression -> Expression -> Maybe SourceRange -> Apply -- | The function being called [apply'func] :: Apply -> Expression -- | The argument to the function [apply'arg] :: Apply -> Expression [apply'source] :: Apply -> Maybe SourceRange apply'discardSource :: Apply -> Apply expression'applyArgs :: Expression -> [Expression] -> Expression -- | Render a function application expression (f x). render'apply :: Render Apply -- |

Syntax

-- -- A let-in expression (Expr'Let) looks like this: -- --
--   let
--     greet = x: "Hello, ${x}!";
--     name = "Chris";
--   in
--     greet name
--   
-- -- Let bindings, like dict bindings, may also use the -- inherit keyword. -- --
--   let
--     d = { greet = x: "Hello, ${x}!"; name = "Chris"; }
--     inherit (d) greet name;
--   in
--     greet name
--   
-- -- The previous example also demonstrates how the bindings in a -- let expression may refer to each other (much like a dict with -- the rec keyword). As with dicts, the order of the bindings -- does not matter. data Let :: * Let :: Seq LetBinding -> Expression -> Maybe SourceRange -> Let -- | The bindings (everything between the let and in -- keywords) [let'bindings] :: Let -> Seq LetBinding -- | The value (everything after the in keyword) [let'value] :: Let -> Expression [let'source] :: Let -> Maybe SourceRange let'discardSource :: Let -> Let keyword'let :: Keyword keyword'in :: Keyword -- | Render a let-in expression. render'let :: Render Let parse'let :: Parser Let -- | A semicolon-terminated binding within the binding list of a Let -- expression. data LetBinding :: * -- | A binding with an equals sign, of the form x = y; LetBinding'Eq :: Var -> Expression -> LetBinding -- | A binding using the inherit keyword, of the form inherit -- (x) a b; LetBinding'Inherit :: Expression -> Seq Var -> LetBinding letBinding'discardSource :: LetBinding -> LetBinding -- | Render a binding within a Let, including the trailing -- semicolon. render'letBinding :: Render LetBinding parse'letBinding :: Parser LetBinding parse'letBinding'eq :: Parser LetBinding parse'letBinding'inherit :: Parser LetBinding keyword'inherit :: Keyword data Keyword :: * -- | All of the keywords. This list is used when parsing and rendering -- because an unquoted string cannot have a name that is exactly the same -- as a keyword. keywords :: [Keyword] keywordString :: Keyword -> String keywordText :: Keyword -> Text -- | Backtracking parser for a particular keyword. parse'keyword :: Keyword -> Parser () keyword'inlineComment :: Keyword parse'spaces :: Parser () parse'comment :: Parser () parse'comment'inline :: Parser () parse'comment'block :: Parser () type Render a = RenderContext -> a -> Text data RenderContext :: * RenderContext :: Natural -> Natural -> Bool -> RenderContext [renderContext'indentStart] :: RenderContext -> Natural [renderContext'indentStep] :: RenderContext -> Natural [renderContext'lineBreaks] :: RenderContext -> Bool renderContext'default :: RenderContext renderContext'terse :: RenderContext module Bricks.Internal.Monad -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: * -> *) -- | Lift a computation from the IO monad. liftIO :: MonadIO m => IO a -> m a -- | The strategy of combining computations that can throw exceptions by -- bypassing bound functions from the point an exception is thrown to the -- point that it is handled. -- -- Is parameterized over the type of error information and the monad type -- constructor. It is common to use Either String as the -- monad type constructor for an error monad in which error descriptions -- take the form of strings. In that case and many other common cases the -- resulting monad is already defined as an instance of the -- MonadError class. You can also define your own error type -- and/or use a monad type constructor other than Either -- String or Either IOError. In -- these cases you will have to explicitly define instances of the -- Error and/or MonadError classes. class Monad m => MonadError e (m :: * -> *) | m -> e -- | Is used within a monadic computation to begin exception processing. throwError :: MonadError e m => e -> m a -- | A handler function to handle previous errors and return to normal -- execution. A common idiom is: -- --
--   do { action1; action2; action3 } `catchError` handler
--   
-- -- where the action functions can call throwError. Note -- that handler and the do-block must have the same return type. catchError :: MonadError e m => m a -> (e -> m a) -> m a -- | A monad transformer that adds exceptions to other monads. -- -- ExceptT constructs a monad parameterized over two things: -- -- -- -- The return function yields a computation that produces the -- given value, while >>= sequences two subcomputations, -- exiting on the first exception. newtype ExceptT e (m :: * -> *) a :: * -> (* -> *) -> * -> * ExceptT :: m Either e a -> ExceptT e a -- | The inverse of ExceptT. runExceptT :: () => ExceptT e m a -> m Either e a -- | The reader monad transformer, which adds a read-only environment to -- the given monad. -- -- The return function ignores the environment, while -- >>= passes the inherited environment to both -- subcomputations. newtype ReaderT k r (m :: k -> *) (a :: k) :: forall k. () => * -> (k -> *) -> k -> * ReaderT :: (r -> m a) -> ReaderT k r [runReaderT] :: ReaderT k r -> r -> m a module Bricks.Term data Bottom Bottom :: Text -> Bottom displayBottom :: Bottom -> Text class (Monad m, MonadIO m, MonadError Bottom m) => MonadEval m reduce'term :: MonadEval m => Term -> m Term reduce'dict'keys :: MonadEval m => Term -> m (Map Text Term) type Function = forall m. MonadEval m => Term -> m Term data Term -- | The name of the data type, and a value of that type. Term'Data :: Text -> Dynamic -> Term Term'Function :: Function -> Term -- | The head and body of a lambda expression. Term'Lambda :: TermPattern -> Term -> Term Term'LetRec :: (Map Text Term) -> Term -> Term Term'List :: (Seq Term) -> Term Term'Dict :: (Seq (Term, Term)) -> Term Term'Dict'ReducedKeys :: (Map Text Term) -> Term Term'Var :: Text -> Term Term'Apply :: Term -> Term -> Term Term'Pointer :: TermPtr -> Term -- | Alias for Term'Apply. The name is an allusion to the AST -- depictions in The Implementation of Functional Programming -- Languages, where "f applied to x" is drawn as: -- --
--     @
--    ╱ ╲
--   f   x
--   
-- -- For a function of two parameters, see the corresponding /@@\ -- operator. (/@\) :: Term -> Term -> Term infixl 9 /@\ -- | Like /@\, but for a function applied to two arguments. Depicted -- as an abstract syntax tree, f /@@\ (x, y) looks like this: -- --
--       @
--      ╱ ╲
--     @   y
--    ╱ ╲
--   f   x
--   
(/@@\) :: Term -> (Term, Term) -> Term infixl 9 /@@\ -- | Alias for Term'Lambda. (|->) :: TermPattern -> Term -> Term infixl 9 |-> data TermPattern TermPattern'Simple :: Text -> TermPattern TermPattern'Dict :: (Set Text) -> TermPattern type TermPtr = IORef Term create'pointer :: MonadIO m => Term -> m Term dereference :: MonadIO m => Term -> m Term newTermPtr :: MonadIO m => Term -> m Term readTermPtr :: MonadIO m => TermPtr -> m Term writeTermPtr :: MonadIO m => TermPtr -> Term -> m () bottom :: MonadError Bottom m => Bottom -> m a module Bricks.Type data Type a Type :: Text -> Type a [type'name] :: Type a -> Text type'boolean :: Type Bool type'string :: Type Text type'integer :: Type Integer termTypeName :: MonadIO m => Term -> m Text module Bricks.BuiltinFunctions term'data :: forall a. Typeable a => Type a -> a -> Term fn'pure'parametric'arity1 :: (Term -> Term) -> Term fn'pure'parametric'arity2 :: (Term -> Term -> Term) -> Term fn'pure'parametric'arity3 :: (Term -> Term -> Term -> Term) -> Term fn'id :: Term fn'const :: Term -- | Function composition, in the traditional "backwards" order. -- -- Read f fn'comp g as "f after g." fn'comp :: Term fn'flip :: Term fn'dict'lookup :: Term fn'or :: Term fn'and :: Term fn'string'append :: Term fn'dict'disallowExtraKeys :: Set Text -> Term fn'dict'merge'preferLeft :: Term fn'dict'merge'preferRight :: Term cast'data :: (MonadEval m, Typeable a) => Type a -> Term -> m a -- | Like fn'id, but fails if the argument is not of the given type. assert'type :: Typeable a => Type a -> Term req :: forall a b m. (MonadEval m, Typeable a) => ((a, Term) -> b) -> Type a -> Term -> m b fn'int'add :: Term fn'int'constructor :: Term standard'library :: Term -- | Conversion from Expression (the AST produced by the parser) to -- Term (an augmented form of the lambda calculus used for -- evaluation). module Bricks.ExpressionToTerm expression'to'term :: Expression -> IO Term var'to'term :: Var -> IO Term apply'to'term :: Apply -> IO Term str'to'term :: Str'Dynamic -> IO Term str'1'to'term :: Str'1 -> IO Term list'to'term :: List -> IO Term dict'to'term :: Dict -> IO Term dot'to'term :: Dot -> IO Term let'to'term :: Let -> IO Term letBinding'to'term :: LetBinding -> IO [(Text, Term)] lambda'to'term :: Lambda -> IO Term lambda'to'term'simple :: Var -> Term -> IO Term lambda'to'term'dictPattern :: DictPattern -> Term -> IO Term lambda'to'term'both :: Var -> DictPattern -> Term -> IO Term dictPattern'names :: DictPattern -> Set Text dictPattern'defaults :: DictPattern -> IO (Map Text Term) -- | This module lets you evaluate Bricks expressions. First -- expression'to'terms converts the abstract syntax tree -- (Expression) into an enriched version of the lambda calculus -- (Term). Then we perform graph reduction, repeatedly -- applying simplifications until we arrive at an irreducible term. -- -- When we substitute an argument into a lambda body to perform -- beta-conversion, we do so by substituting a Pointer of the -- argument rather than the term itself. This gives rise to -- sharing, thus turning the tree into a general graph, and helps -- avoid reducing the same expression more than once. -- --

The Implementation of Functional Programming Languages

-- -- The design of Bricks evaluation is in large part based on Simon Peyton -- Jones's 1987 book The Implementation of Functional Programming -- Languages. In attempt to keep the Bricks API documentation mostly -- self-contained, we avoid making frequent references to this work -- throughout. Instead, here we give a list of some important connections -- to the book: -- -- module Bricks.Evaluation newtype Eval a Eval :: ExceptT Bottom IO a -> Eval a [unEval] :: Eval a -> ExceptT Bottom IO a does'termPattern'bind :: Text -> TermPattern -> Bool -- | instantiate var value body produces a copy of the term -- body, substituting value for free occurrences of -- var. instantiate'one :: forall m. MonadEval m => Text -> Term -> Term -> m Term instantiate'many :: forall m. MonadEval m => Map Text Term -> Term -> m Term reduce'to'type :: Typeable a => Type a -> Term -> IO (Either Bottom a) reduce'to'type'or'throw :: (HasCallStack, Typeable a) => Type a -> Term -> IO a instance Control.Monad.IO.Class.MonadIO Bricks.Evaluation.Eval instance Control.Monad.Error.Class.MonadError Bricks.Term.Bottom Bricks.Evaluation.Eval instance GHC.Base.Monad Bricks.Evaluation.Eval instance GHC.Base.Applicative Bricks.Evaluation.Eval instance GHC.Base.Functor Bricks.Evaluation.Eval instance Bricks.Term.MonadEval Bricks.Evaluation.Eval module Bricks.Prelude bricks'eval :: (HasCallStack, Typeable a) => Type a -> Text -> IO a bricks'eval'stdlib :: (HasCallStack, Typeable a) => Type a -> Text -> IO a