macro librarywork/xetal-ml/libs/Flow/src/Flow.xtlm
Flow: ML data flow written left to right, |> between stages -- each stage becomes one line of X_eTaL
Import it with an alias of your choice: "flow:" u_se< "Flow" (flow:p_ipe<). Put libs/Flow/src on XETAL_PATH ("just path"); the reference is libs/Flow/docs. Names with m: are macros; those under h: are private to this file.
A macro is a function from the source text written left and right of its call to the source that replaces the call, before the program is compiled (X_eTaL MC10); xetal expand FILE shows the result. The pipeline was decided in X_eTaL (D155, its docs/spatial.md, "Pipelines") and is built here (docs/pipeline-macro.md). Its reader uses all of its text or refuses it: a stage the grammar does not know is a compile-time error naming the text, never a wrong answer.
The macros
ᵐp̲ipe< : Unit -> Char -> Char
The value of a pipeline: the data, then each stage in turn, |> between them. A stage is a function (act:r_elu, [f_ g_], '{ x -> ... }), applied to the previous value, or an expression naming the previous value it (W nn:d_ense it; the order is written, never guessed). "$name" at a stage's end names its value for the later stages, the $ touching the name ("$(Q, K, V)" takes a tuple apart, as X_eTaL's S14 label is written and drawn); " [N O]" after the name is the shape the value must have, checked when the program runs (error[shape], naming the stage, its shape and the one expected). The left side is @; the right is a code string c"...", drawn as X_eTaL (|> and $ as triangles), and may put one stage per line; a plain or raw string reads the same.
"flow:" u̲se< "Flow"
x ← f̲loat 1 2 3 4
@ ᶠˡᵒʷp̲ipe< c"x ▹s ▷ 2 × it ▷ it + s" 3.0 6.0 9.0 12.0
ᵐp̲ipe< ← { @ text → ʰw̲rite ʰr̲ead text }
ᵐt̲ext< : Unit -> Char -> Char
The pipeline written back from its reading, a string: the stages trimmed, " |> " between them, each name and shape as written. What the macro read is what was written, or the call was refused.
"flow:" u̲se< "Flow"
@ ᶠˡᵒʷt̲ext< c"x ▹s ▷ 2 × it ▷ it + s" x $s |> 2 * it |> it + s
ᵐt̲ext< ← { @ text → "\"" c̲at (ʰe̲scape ʰs̲how ʰr̲ead text) c̲at "\"" }
ᵐm̲ath< : Unit -> Char -> Char
The pipeline drawn as math, a LaTeX string: an aligned display of a row per stage, the data first, each later stage after an arrow, each label after its stage as X_eTaL draws $ (a triangle, the name, its shape); an equation stage ("H[i,k] | n d" e:e_q< "...") as Equations draws it (its e:t_ex<, the same strings), any other stage as code. The call is read as flow:p_ipe< reads it, or refused; KaTeX or LaTeX draws the result.
"flow:" u̲se< "Flow"
@ ᶠˡᵒʷm̲ath< c"x ▹s ▷ 2 × it ▷ it + s" \begin{aligned} & x \qquad \triangleright \, s \\ \longrightarrow \; & \texttt{2 * it} \\ \longrightarrow \; & \texttt{it + s} \end{aligned}
ᵐm̲ath< ← { @ text → ʰd̲raw ʰr̲ead text }
ᵐs̲tages< : Unit -> Char -> Char
Every stage's value, as one line of text: a record per value, " | " between them, each its stage's number, its label ("" for none), its shape, its smallest and largest item and its first 64 items, ";" between the fields; a tuple's parts a record each. For pages that show what each stage gives; the values are those flow:p_ipe< gives.
"flow:" u̲se< "Flow"
x ← f̲loat 1 2 3
@ ᶠˡᵒʷs̲tages< c"x ▷ 2 × it ▹y" 1;;3;1.0;3.0;1.0 2.0 3.0 | 2;y;3;2.0;6.0;2.0 4.0 6.0
ᵐs̲tages< ← { @ text → ʰt̲race ʰr̲ead text }
Reading the call
ʰr̲ead : Char -> (Box Char, Box Char, Box Char)
The stages of text as (expressions, names, shapes), each a boxed text per stage ("" for no name or no shape), every rule checked.
ʰr̲ead ← { text → t ← ᵗt̲rim text _ ← (0 < t̲ally t) ʰr̲equire "an empty pipeline: write the data, then |> and each stage" parts ← '{ p → ᵗt̲rim d̲isclose p } m̲ap "|>" ʰs̲plit t _ ← '{ p → ʰt̲ouches? d̲isclose p } m̲ap parts _ ← ('∧ r̲/ '{ p → 0 < t̲ally d̲isclose p } e̲ach parts) ʰr̲equire "an empty stage (nothing between two |>, or after the last): " c̲at t es ← '{ p → ʰe̲xpr d̲isclose p } m̲ap parts bs ← '{ p → ʰb̲inder d̲isclose p } m̲ap parts ss ← '{ p → ʰs̲hapeOf d̲isclose p } m̲ap parts _ ← '{ i → (ʰf̲latten (i − 1) t̲ake bs) ʰs̲tage? d̲isclose i s̲elect es } m̲ap 1 d̲rop r̲ange t̲ally es _ ← (n̲ot ʰi̲t? d̲isclose f̲irst es) ʰr̲equire "the first stage is the data; nothing precedes it: " c̲at d̲isclose f̲irst es _ ← '{ b → ʰb̲inder? d̲isclose b } m̲ap bs _ ← (ss, bs) ʰs̲hapes? r̲ange t̲ally ss all ← ʰf̲latten bs twice ← (1 < '+ r̲/₂ 0 + all 'm̲atch t̲able all) r̲eplicate all _ ← (0 = t̲ally twice) ʰr̲equire "a name is bound once in a pipeline: " c̲at ʰf̲irstText twice (es, bs, ss) }
ʰe̲xpr : Char -> Char
A stage's expression: its text before its label's $, trimmed.
ʰe̲xpr ← { s → c ← ʰl̲abel s 0 = c ? ᵗt̲rim s ᵗt̲rim (c − 1) t̲ake s }
ʰa̲fter : Char -> Char
What follows a stage's $, trimmed ("" for no label).
ʰa̲fter ← { s → c ← ʰl̲abel s 0 = c ? "" ᵗt̲rim c d̲rop s }
ʰb̲inder : Char -> Char
A stage's name (or tuple of names): the text after $ up to its shape's [, trimmed; "" for none.
ʰb̲inder ← { s → a ← ʰa̲fter s k ← "[" ʰf̲irstOf a 0 = k ? a ᵗt̲rim (k − 1) t̲ake a }
ʰs̲hapeOf : Char -> Char
A stage's shape as written, "[N O]", from its first [ on; "" for none.
ʰs̲hapeOf ← { s → a ← ʰa̲fter s k ← "[" ʰf̲irstOf a 0 = k ? "" ᵗt̲rim (k − 1) d̲rop a }
ʰl̲abel : Char -> Int
Where the first $ outside brackets and strings is in s, or 0.
ʰl̲abel ← { s → ʰf̲irst "$" ʰo̲utside s }
ʰt̲ouches? : Char -> Char
A stage's $ touches the name or tuple it gives ($m, $(Q, K)), as X_eTaL's own label does: $ m, or a $ with nothing after it, is refused ("" when the stage has no label or its $ touches).
ʰt̲ouches? ← { s → c ← ʰl̲abel s 0 = c ? "" msg ← "$ labels a stage and touches the name or tuple it gives ($m, $(Q, K)): " c̲at s c = t̲ally s ? (0 = 1) ʰr̲equire msg (((c + 1) s̲elect s) m̲ember? letters c̲at "(") ʰr̲equire msg }
ʰs̲tage? : Box Char -> Char -> Char
A stage after the first is a function, or an expression naming the previous value it or a name bound before it (earlier, boxed); a stage that calls a macro (an equation, "Y[i] | n" e:e_q< "2 * it[i]") names them in its strings too. Else the call is refused with the text ("" when it is one of these).
ʰs̲tage? ← { earlier e → named ← '∨ r̲/ (0 = 1) c̲at '{ w → (d̲isclose w) ʰu̲ses? e } e̲ach earlier ((ʰi̲t? e) ∨ (ʰf̲unction? e) ∨ named) ʰr̲equire "a stage is a function (act:r_elu, [f_ g_], '{ x -> ... }) or an expression naming the previous value it (or a name bound before it), in an equation's strings or out: " c̲at e }
ʰi̲t? : Truthy a => Char -> a
Whether e names the previous value: the word it, outside strings, or in the strings of a macro call.
ʰi̲t? ← { e → "it" ʰu̲ses? e }
ʰu̲ses? : Truthy a => Char -> Char -> a
Whether e uses the name w: outside strings; in a macro call's strings too (the names an equation reads, x[i,j]).
ʰu̲ses? ← { w e → (w, ʰm̲acro? e) ʰw̲ord? e }
ʰm̲acro? : Truthy a => Char -> a
Whether e calls a macro: a word ending in < outside strings (e:e_q<).
ʰm̲acro? ← { e → ps ← "<" ʰo̲utside e '∨ r̲/ (0 = 1) c̲at '{ p → p = 1 ? 0 = 1◆ ((p − 1) s̲elect e) m̲ember? nameChars } e̲ach ps }
ʰw̲ord? : (Truthy a, Truthy b) => (Char, a) -> Char -> b
Whether the word w (a name) occurs whole in e: outside strings, or anywhere when inStrings holds.
ʰw̲ord? ← { (w, inStrings) e → ps ← w ᵗf̲ind e 0 = t̲ally ps ? 0 = 1 q ← ʰq̲uoted e n ← t̲ally w before ← '{ p → p = 1 ? 0 = 1◆ ((p − 1) s̲elect e) m̲ember? nameChars } e̲ach ps after ← '{ p → (p + n) > t̲ally e ? 0 = 1◆ ((p + n) s̲elect e) m̲ember? nameChars } e̲ach ps '∨ r̲/ (n̲ot before) ∧ (n̲ot after) ∧ inStrings ∨ 0 = ps s̲elect q }
ʰf̲unction? : Truthy a => Char -> a
Whether e is written as a function: a quoted function or lambda ('n_eg, '+ r_/, '{ x -> ... }), a train ([f_ g_]), or one function name (act:r_elu, t_ally: no blanks, an underline).
ʰf̲unction? ← { e → ("'" m̲atch 1 t̲ake e) ∨ "[" m̲atch 1 t̲ake e ? 0 = 0 (0 = t̲ally w̲here e m̲ember? " ") ∧ (0 < t̲ally w̲here e m̲ember? "_") ∧ '∧ r̲/ e m̲ember? nameChars }
ʰb̲inder? : Char -> Char
A name after $ is a plain name (letters and digits, a letter first) or a tuple of two or more, (Q, K, V); never it; else refused ("" when it is).
ʰb̲inder? ← { b → 0 = t̲ally b ? "" _ ← (n̲ot "it" m̲atch b) ʰr̲equire "it is the previous value, not a name to bind: " c̲at b ps ← ʰp̲arts b allNames ← '∧ r̲/ '{ p → ʰn̲ame? d̲isclose p } e̲ach ps tuple ← ("(" m̲atch 1 t̲ake b) ∧ (")" m̲atch -1 t̲ake b) ∧ 2 ≤ t̲ally ps (allNames ∧ (tuple ∨ n̲ot "(" m̲atch 1 t̲ake b)) ʰr̲equire "after $ comes a plain name, or a tuple of names (Q, K, V): " c̲at b }
ʰp̲arts : Char -> Box Char
The names a binder binds, boxed: the name itself, or a tuple's parts.
ʰp̲arts ← { b → n̲ot "(" m̲atch 1 t̲ake b ? 1 r̲eshape e̲nclose b '{ p → ᵗt̲rim d̲isclose p } m̲ap "," ᵗs̲plit 1 d̲rop -1 d̲rop b }
ʰf̲latten : Box Char -> Box Char
Every name the stages bind, boxed, in order.
ʰf̲latten ← { bs → 0 = t̲ally bs ? 0 r̲eshape e̲nclose "" 0 = t̲ally d̲isclose f̲irst bs ? ʰf̲latten 1 d̲rop bs (ʰp̲arts d̲isclose f̲irst bs) c̲at ʰf̲latten 1 d̲rop bs }
ʰn̲ame? : Truthy a => Char -> a
Whether b is a plain name: a letter, then letters or digits.
ʰn̲ame? ← { b → 0 = t̲ally b ? 0 = 1 ((f̲irst b) m̲ember? letters) ∧ '∧ r̲/ b m̲ember? plainChars }
ʰs̲hapes? : (Box Char, Box Char) -> Int -> Box Char
The shapes against their names, each stage: a shape needs a single name before it, is [extents] whole (names or numbers, blanks between) and nothing follows it; else refused with the text ("" each).
ʰs̲hapes? ← { (ss, bs) is → '{ i → sh ← d̲isclose i s̲elect ss b ← d̲isclose i s̲elect bs 0 = t̲ally sh ? "" _ ← ((0 < t̲ally b) ∧ n̲ot "(" m̲atch 1 t̲ake b) ʰr̲equire "a shape [N O] goes after the stage's name: " c̲at sh _ ← (("]" m̲atch -1 t̲ake sh) ∧ (1 = t̲ally w̲here sh m̲ember? "]") ∧ 1 = t̲ally w̲here sh m̲ember? "[") ʰr̲equire "a shape is [extents] at the stage's end, nothing after it: " c̲at sh items ← ᵗw̲ords 1 d̲rop -1 d̲rop sh ((0 < t̲ally items) ∧ '∧ r̲/ '{ w → '∧ r̲/ (d̲isclose w) m̲ember? plainChars } e̲ach items) ʰr̲equire "a shape's extents are names or numbers, blanks between: " c̲at sh } m̲ap is }
Writing the code
ʰw̲rite : (Box Char, Box Char, Box Char) -> Char
The expansion: a block binding each stage's value, one line per stage (a fresh name from []G_ENSYM, or the name given), the shape checks after their stages, and the last value as the result.
ʰw̲rite ← { (es, bs, ss) → n ← t̲ally es names ← '{ i → b ← d̲isclose i s̲elect bs◆ 0 = t̲ally b ? ⎕G̲ENSYM "stage"◆ b } m̲ap r̲ange n lines ← '{ i → (es, ss, names) ʰl̲ine i } m̲ap r̲ange n "{ @ ->\n" c̲at ("" ᵗj̲oin lines) c̲at " " c̲at (d̲isclose n s̲elect names) c̲at "\n} @" }
ʰl̲ine : (Box Char, Box Char, Box Char) -> Int -> Char
Stage i's line: the data as written; an expression naming it in a block of its own (it := the previous value); a function applied to the previous value; an expression of earlier names as written; then its shape check, if any.
ʰl̲ine ← { (es, ss, names) i → e ← d̲isclose i s̲elect es name ← d̲isclose i s̲elect names check ← (i, name) ʰc̲heckOf d̲isclose i s̲elect ss i = 1 ? " " c̲at name c̲at " := " c̲at e c̲at "\n" c̲at check prev ← d̲isclose (i − 1) s̲elect names ʰi̲t? e ? " " c̲at name c̲at " := { @ ->\n it := " c̲at prev c̲at "\n " c̲at e c̲at "\n } @\n" c̲at check ʰf̲unction? e ? " " c̲at name c̲at " := " c̲at (ʰa̲pplied e) c̲at " " c̲at prev c̲at "\n" c̲at check " " c̲at name c̲at " := " c̲at e c̲at "\n" c̲at check }
ʰa̲pplied : Char -> Char
A function stage as applied to a value: a quoted lambda or quoted name loses its quote ('{ x -> ... } and 'n_eg are the function passed, { x -> ... } v and n_eg v the call); a derived function ('+ r_/), a train and a name stay as written.
ʰa̲pplied ← { e → n̲ot "'" m̲atch 1 t̲ake e ? e ("'{" m̲atch 2 t̲ake e) ∨ 0 = t̲ally w̲here e m̲ember? " " ? 1 d̲rop e e }
ʰc̲heckOf : (Int, Char) -> Char -> Char
The check of stage i's shape sh, "" when it has none.
ʰc̲heckOf ← { (i, name) sh → 0 = t̲ally sh ? "" (i, name) ʰc̲heck sh }
ʰc̲heck : (Int, Char) -> Char -> Char
The run-time check of a stage's shape: nothing when it matches, else error[shape] naming the stage, its shape and the one expected (the extents are the caller's values when the program runs).
ʰc̲heck ← { (i, name) sh → expected ← "r_avel " c̲at " c_at " ᵗj̲oin ᵗw̲ords 1 d̲rop -1 d̲rop sh " _ := { @ ->\n ((s_hape " c̲at name c̲at ") m_atch " c̲at expected c̲at ") ? @\n \"shape\" []S_IGNAL \"stage " c̲at (f̲ormat i) c̲at " (" c̲at name c̲at "): shape \" c_at (f_ormat s_hape " c̲at name c̲at ") c_at \", expected \" c_at f_ormat " c̲at expected c̲at "\n } @\n" }
Drawing the call
ʰd̲raw : (Box Char, Box Char, Box Char) -> Char
The display: the rows joined, inside \begin{aligned} ... \end{aligned}, as an expression of strings (an equation's row is its library's t_ex< call, expanded in turn).
ʰd̲raw ← { (es, bs, ss) → n ← t̲ally es rows ← '{ i → (es, bs, ss) ʰr̲ow i } m̲ap r̲ange n pieces ← (e̲nclose ʰr̲aw "\\begin{aligned} ") c̲at rows c̲at e̲nclose ʰr̲aw " \\end{aligned}" "(" c̲at (" c_at " ᵗj̲oin pieces) c̲at ")" }
ʰr̲ow : (Box Char, Box Char, Box Char) -> Int -> Char
Row i: an arrow before every stage but the data, the stage drawn, its label after it as X_eTaL draws $ (a small triangle, the name and its shape), a line break after every row but the last.
ʰr̲ow ← { (es, bs, ss) i → e ← (es, bs) ʰs̲hown i into ← ʰi̲nto i label ← ʰn̲amed (d̲isclose i s̲elect bs, d̲isclose i s̲elect ss) (ʰr̲aw into) c̲at " c_at " c̲at (ʰd̲rawn e) c̲at " c_at " c̲at ʰr̲aw label c̲at i ʰb̲reak t̲ally es }
ʰi̲nto : Int -> Char
What comes before row i: the column for the data, an arrow then the column for each later stage.
ʰi̲nto ← { i → i = 1 ? "& " "\\longrightarrow \\; & " }
ʰb̲reak : Int -> Int -> Char
What ends row i of n: a line break, but for the last.
ʰb̲reak ← { i n → i = n ? "" " \\\\ " }
ʰn̲amed : (Char, Char) -> Char
A stage's label drawn after it: the triangle, the name, the extents of its shape (n \\times 16); "" when it has no name.
ʰn̲amed ← { (b, sh) → 0 = t̲ally b ? "" dims ← " \\times " ᵗj̲oin ᵗw̲ords 1 d̲rop -1 d̲rop sh " \\qquad \\triangleright \\, " c̲at b c̲at (": " ʰo̲pt dims) }
ʰs̲hown : (Box Char, Box Char) -> Int -> Char
Stage i as drawn: in an equation, it, the previous value, under the name it came with when it has one (the previous stage's label, or the data when the data is a name), so it reads X[i,j], not it[i,j]; code as written.
ʰs̲hown ← { (es, bs) i → e ← d̲isclose i s̲elect es (i = 1) ∨ 0 = t̲ally "e_q<" ʰo̲utside e ? e ((es, bs) ʰi̲ncoming i − 1) ʰa̲s e }
ʰi̲ncoming : (Box Char, Box Char) -> Int -> Char
The name stage i's value goes by: its label, or the data itself when it is a plain name; "" for none (a tuple label is no one name).
ʰi̲ncoming ← { (es, bs) i → b ← d̲isclose i s̲elect bs ʰn̲ame? b ? b (i = 1) ∧ ʰn̲ame? d̲isclose 1 s̲elect es ? d̲isclose 1 s̲elect es "" }
ʰc̲hr : Char -> Int -> Char
The i-th character of s, a blank before its start and past its end.
ʰc̲hr ← { s i → (i < 1) ∨ i > t̲ally s ? 1 s̲elect " "◆ i s̲elect s }
ʰa̲s : Char -> Char -> Char
e with each whole word it written as name (e as it is for "").
ʰa̲s ← { name e → 0 = t̲ally name ? e ps ← "it" ᵗf̲ind e whole ← '{ p → n̲ot ((e ʰc̲hr p − 1) m̲ember? nameChars) ∨ (e ʰc̲hr p + 2) m̲ember? nameChars } e̲ach ps 0 = '+ r̲/ 0 + whole ? e p ← f̲irst whole r̲eplicate ps ((p − 1) t̲ake e) c̲at name c̲at name ʰa̲s (p + 1) d̲rop e }
ʰd̲rawn : Char -> Char
A stage drawn, as an expression of a string: an equation by its library's t_ex< on the same strings (e:e_q< becomes e:t_ex<); a plain name as itself; anything else as code.
ʰd̲rawn ← { e → ps ← "e_q<" ʰo̲utside e 0 < t̲ally ps ? "(" c̲at ((-1 + f̲irst ps) t̲ake e) c̲at "t_ex<" c̲at ((3 + f̲irst ps) d̲rop e) c̲at ")" ʰn̲ame? e ? ʰr̲aw e ʰr̲aw ʰt̲t e }
ʰt̲t : Char -> Char
Code as LaTeX's typewriter text, its special characters escaped.
ʰt̲t ← { s → "\\texttt{" c̲at ("" ᵗj̲oin '{ ch → ʰl̲atexChar ch } m̲ap s) c̲at "}" }
ʰl̲atexChar : Char -> Char
One character of code as LaTeX text.
ʰl̲atexChar ← { ch → ch m̲ember? "\\" ? "\\textbackslash{}" ch m̲ember? "^" ? "\\textasciicircum{}" ch m̲ember? "~" ? "\\textasciitilde{}" ch m̲ember? "{}_$&%#" ? "\\" c̲at ch ch }
ʰr̲aw : Char -> Char
s as a raw string literal, r#"s"#: a backslash stays a backslash.
ʰr̲aw ← { s → "r#\"" c̲at s c̲at "\"#" }
Tracing the stages
ʰt̲race : (Box Char, Box Char, Box Char) -> Char
The expansion as flow:p_ipe< writes it, the last line the records of every stage's value instead of the last value.
ʰt̲race ← { (es, bs, ss) → n ← t̲ally es names ← '{ i → b ← d̲isclose i s̲elect bs◆ 0 = t̲ally b ? ⎕G̲ENSYM "stage"◆ b } m̲ap r̲ange n lines ← '{ i → (es, ss, names) ʰl̲ine i } m̲ap r̲ange n records ← '{ i → ʰr̲ecords (i, d̲isclose i s̲elect bs, d̲isclose i s̲elect names) } m̲ap r̲ange n "{ @ ->\n" c̲at ("" ᵗj̲oin lines) c̲at " " c̲at (" c_at \" | \" c_at " ᵗj̲oin records) c̲at "\n} @" }
ʰr̲ecords : (Int, Char, Char) -> Char
The records of stage i's value (the name it is bound to): one, or one per part of a tuple label, as code giving text.
ʰr̲ecords ← { (i, b, name) → "(" m̲atch 1 t̲ake b c̲at " " ? " c_at \" | \" c_at " ᵗj̲oin '{ p → (i, d̲isclose p) ʰr̲ecord d̲isclose p } m̲ap ʰp̲arts b (i, b) ʰr̲ecord name }
ʰr̲ecord : (Int, Char) -> Char -> Char
One value's record, as code giving text.
ʰr̲ecord ← { (i, label) v → "(\"" c̲at (f̲ormat i) c̲at ";" c̲at label c̲at ";\" c_at (f_ormat s_hape " c̲at v c̲at ") c_at \";\" c_at (f_ormat 'm_in r_/ r_avel " c̲at v c̲at ") c_at \";\" c_at (f_ormat 'm_ax r_/ r_avel " c̲at v c̲at ") c_at \";\" c_at f_ormat (64 m_in t_ally r_avel " c̲at v c̲at ") t_ake r_avel " c̲at v c̲at ")" }
Writing the call back
ʰs̲how : (Box Char, Box Char, Box Char) -> Char
The pipeline as read, one line: the stages with " |> " between, " $name" and " [shape]" where given.
ʰs̲how ← { (es, bs, ss) → one ← '{ i → (d̲isclose i s̲elect es) c̲at (" $" ʰo̲pt d̲isclose i s̲elect bs) c̲at " " ʰo̲pt d̲isclose i s̲elect ss } m̲ap r̲ange t̲ally es " |> " ᵗj̲oin one }
ʰo̲pt : Char -> Char -> Char
pre and x, or "" when x is empty.
ʰo̲pt ← { pre x → 0 = t̲ally x ? "" pre c̲at x }
ʰe̲scape : Char -> Char
s as the inside of a string literal: a quote becomes \".
ʰe̲scape ← { s → "" ᵗj̲oin '{ ch → (ch m̲ember? "\"") ? "\\\""◆ ch } m̲ap s }
Text helpers
ʰr̲equire : Truthy a => a -> Char -> Char
Nothing when ok holds; else the call is refused with message, at its text (the right side).
ʰr̲equire ← { ok message → ok ? "" "bad-pipeline right" ⎕R̲EJECT message }
nameChars : Char
Characters of names: of values (Q, m1), of functions (act:r_elu, n_ame?, p_rint!), and digits.
nameChars ← "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_:?!"
plainChars : Char
Characters of plain names and numbers.
plainChars ← "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
letters : Char
letters ← "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
ʰq̲uoted : Char -> Int
1 at each character of s inside a string literal (its quotes included).
ʰq̲uoted ← { s → ('+ s̲\ 0 + s m̲ember? "\"") m̲od 2 }
ʰo̲utside : Char -> Char -> Int
The positions in s where sep starts outside brackets, braces, parentheses and strings.
ʰo̲utside ← { sep s → q ← ʰq̲uoted s d ← '+ s̲\ ((0 + s m̲ember? "([{") − 0 + s m̲ember? ")]}") × 1 − q ps ← sep ᵗf̲ind s (((ps s̲elect d) = 0) ∧ 0 = ps s̲elect q) r̲eplicate ps }
ʰs̲plit : Char -> Char -> Box Char
s cut where sep starts outside brackets and strings: the pieces between, boxed (one piece when it never does).
ʰs̲plit ← { sep s → ps ← sep ʰo̲utside s m ← t̲ally sep starts ← 1 c̲at ps + m ends ← ps c̲at 1 + t̲ally s '{ i → ((i s̲elect ends) − i s̲elect starts) t̲ake ((i s̲elect starts) − 1) d̲rop s } m̲ap r̲ange t̲ally starts }
ʰf̲irstText : Box Char -> Char
The first of the boxed texts b ("" for none).
ʰf̲irstText ← { b → 0 = t̲ally b ? "" d̲isclose f̲irst b }