From ec1f6caacb47ca6d06f829a95a9b692d004b48a2 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Mon, 20 Aug 2018 21:51:07 -0400 Subject: Trying to minimize the amount of clips+concats that happen. --- stdlib/source/lux/compiler/default/syntax.lux | 27 ++-- stdlib/source/lux/data/text/lexer.lux | 207 ++++++++++++++++++-------- 2 files changed, 162 insertions(+), 72 deletions(-) (limited to 'stdlib') diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux index 5f2d6d93b..322035fd8 100644 --- a/stdlib/source/lux/compiler/default/syntax.lux +++ b/stdlib/source/lux/compiler/default/syntax.lux @@ -55,20 +55,19 @@ ## It operates recursively in order to produce the longest continuous ## chunk of white-space. (def: (space^ where) - (-> Cursor (Lexer [Cursor Text])) + (-> Cursor (Lexer [Cursor Any])) (p.either (do p.Monad - [content (l.many (l.one-of white-space))] - (wrap [(update@ #.column (n/+ (text.size content)) where) - content])) + [content (l.many! (l.one-of! white-space))] + (wrap [(update@ #.column (n/+ (get@ #l.distance content)) where) + []])) ## New-lines must be handled as a separate case to ensure line ## information is handled properly. (do p.Monad - [content (l.many (l.one-of new-line))] + [content (l.many! (l.one-of! new-line))] (wrap [(|> where - (update@ #.line (n/+ (text.size content))) + (update@ #.line (n/+ (get@ #l.distance content))) (set@ #.column 0)) - content])) - )) + []])))) ## Single-line comments can start anywhere, but only go up to the ## next new-line. @@ -76,7 +75,7 @@ (-> Cursor (Lexer [Cursor Text])) (do p.Monad [_ (l.this "##") - comment (l.some (l.none-of new-line)) + comment (l.slice (l.some! (l.none-of! new-line))) _ (l.this new-line)] (wrap [(|> where (update@ #.line inc) @@ -157,7 +156,7 @@ [[where comment] (comment^ where)] (left-padding^ where)) (do p.Monad - [[where white-space] (space^ where)] + [[where _] (space^ where)] (left-padding^ where)) (:: p.Monad wrap where))) @@ -365,7 +364,7 @@ ## the text's body's column, ## to ensure they are aligned. (do @ - [offset (l.many (l.one-of " ")) + [offset (l.slice (l.many! (l.one-of! " "))) #let [offset-size (text.size offset)]] (if (n/>= offset-column offset-size) ## Any extra offset @@ -385,7 +384,7 @@ ($_ p.either ## Normal text characters. (do @ - [normal (l.many (l.none-of "\\\"\n"))] + [normal (l.slice (l.many! (l.none-of! "\\\"\n")))] (recur (format text-read normal) (|> where (update@ #.column (n/+ (text.size normal)))) @@ -512,8 +511,8 @@ [#let [digits "0123456789" delimiters (format "()[]{}#\"" name-separator) space (format white-space new-line) - head-lexer (l.none-of (format digits delimiters space)) - tail-lexer (l.some (l.none-of (format delimiters space)))] + head-lexer (l.slice (l.none-of! (format digits delimiters space))) + tail-lexer (l.slice (l.some! (l.none-of! (format delimiters space))))] head head-lexer tail tail-lexer] (wrap (format head tail)))) diff --git a/stdlib/source/lux/data/text/lexer.lux b/stdlib/source/lux/data/text/lexer.lux index 481d17b0a..3b4b63a26 100644 --- a/stdlib/source/lux/data/text/lexer.lux +++ b/stdlib/source/lux/data/text/lexer.lux @@ -9,7 +9,7 @@ ["." maybe] ["e" error] [collection - ["." list]]] + ["." list ("list/." Fold)]]] [macro ["." code]]]) @@ -20,6 +20,10 @@ (type: #export Lexer (p.Parser [Offset Text])) +(type: #export Slice + {#basis Offset + #distance Offset}) + (def: (remaining offset tape) (-> Offset Text Text) (|> tape (text.split offset) maybe.assume product.right)) @@ -42,6 +46,23 @@ (#e.Error (unconsumed-input-error end-offset input))) )) +(def: #export offset + (Lexer Offset) + (function (_ (^@ input [offset tape])) + (#e.Success [input offset]))) + +(def: (with-slices lexer) + (-> (Lexer (List Slice)) (Lexer Slice)) + (do p.Monad + [offset ..offset + slices lexer] + (wrap (list/fold (function (_ [slice::basis slice::distance] + [total::basis total::distance]) + [total::basis (n/+ slice::distance total::distance)]) + {#basis offset + #distance 0} + slices)))) + (def: #export any {#.doc "Just returns the next character without applying any logic."} (Lexer Text) @@ -51,19 +72,31 @@ (#e.Success [[(inc offset) tape] (text.from-code output)]) _ - (#e.Error cannot-lex-error)) - )) + (#e.Error cannot-lex-error)))) -(def: #export (not p) - {#.doc "Produce a character if the lexer fails."} - (All [a] (-> (Lexer a) (Lexer Text))) - (function (_ input) - (case (p input) - (#e.Error msg) - (any input) - - _ - (#e.Error "Expected to fail; yet succeeded.")))) +(def: #export any! + {#.doc "Just returns the next character without applying any logic."} + (Lexer Slice) + (function (_ [offset tape]) + (#e.Success [[(inc offset) tape] + {#basis offset + #distance 1}]))) + +(do-template [ ] + [(def: #export ( p) + {#.doc "Produce a character if the lexer fails."} + (All [a] (-> (Lexer a) (Lexer ))) + (function (_ input) + (case (p input) + (#e.Error msg) + ( input) + + _ + (#e.Error "Expected to fail; yet succeeded."))))] + + [not Text ..any] + [not! Slice ..any!] + ) (def: #export (this reference) {#.doc "Lex a text if it matches the given sample."} @@ -112,8 +145,7 @@ (#e.Success [input (text.from-code output)]) _ - (#e.Error cannot-lex-error)) - )) + (#e.Error cannot-lex-error)))) (def: #export get-input {#.doc "Get all of the remaining input (without consuming it)."} @@ -162,33 +194,49 @@ (range (char "a") (char "f")) (range (char "A") (char "F")))) -(def: #export (one-of options) - {#.doc "Only lex characters that are part of a piece of text."} - (-> Text (Lexer Text)) - (function (_ [offset tape]) - (case (text.nth offset tape) - (#.Some output) - (let [output (text.from-code output)] - (if (text.contains? output options) - (#e.Success [[(inc offset) tape] output]) - (#e.Error ($_ text/compose "Character (" output ") is not one of: " options)))) - - _ - (#e.Error cannot-lex-error)))) - -(def: #export (none-of options) - {#.doc "Only lex characters that are not part of a piece of text."} - (-> Text (Lexer Text)) - (function (_ [offset tape]) - (case (text.nth offset tape) - (#.Some output) - (let [output (text.from-code output)] - (if (.not (text.contains? output options)) - (#e.Success [[(inc offset) tape] output]) - (#e.Error ($_ text/compose "Character (" output ") is one of: " options)))) +(do-template [ ] + [(def: #export ( options) + {#.doc (code.text ($_ text/compose "Only lex characters that are" " part of a piece of text."))} + (-> Text (Lexer Text)) + (function (_ [offset tape]) + (case (text.nth offset tape) + (#.Some output) + (let [output (text.from-code output)] + (if ( (text.contains? output options)) + (#e.Success [[(inc offset) tape] output]) + (#e.Error ($_ text/compose "Character (" output + ") is should " + "be one of: " options)))) + + _ + (#e.Error cannot-lex-error))))] + + [one-of "" |>] + [none-of " not" .not] + ) - _ - (#e.Error cannot-lex-error)))) +(do-template [ ] + [(def: #export ( options) + {#.doc (code.text ($_ text/compose "Only lex characters that are" " part of a piece of text."))} + (-> Text (Lexer Slice)) + (function (_ [offset tape]) + (case (text.nth offset tape) + (#.Some output) + (let [output (text.from-code output)] + (if ( (text.contains? output options)) + (#e.Success [[(inc offset) tape] + {#basis offset + #distance 1}]) + (#e.Error ($_ text/compose "Character (" output + ") is should " + "be one of: " options)))) + + _ + (#e.Error cannot-lex-error))))] + + [one-of! "" |>] + [none-of! " not" .not] + ) (def: #export (satisfies p) {#.doc "Only lex characters that satisfy a predicate."} @@ -215,33 +263,64 @@ =right right] (wrap ($_ text/compose =left =right)))) -(do-template [ ] - [(def: #export ( p) - {#.doc } +(def: #export (and! left right) + (-> (Lexer Slice) (Lexer Slice) (Lexer Slice)) + (do p.Monad + [[left::basis left::distance] left + [right::basis right::distance] right] + (wrap [left::basis (n/+ right::distance right::distance)]))) + +(do-template [ ] + [(def: #export ( lexer) + {#.doc (code.text ($_ text/compose "Lex " " characters as a single continuous text."))} (-> (Lexer Text) (Lexer Text)) - (|> p (:: p.Monad map text.concat)))] + (|> lexer (:: p.Monad map text.concat)))] - [some p.some "Lex some characters as a single continuous text."] - [many p.many "Lex many characters as a single continuous text."] + [some p.some "some"] + [many p.many "many"] ) -(do-template [ ] - [(def: #export ( n p) - {#.doc } +(do-template [ ] + [(def: #export ( lexer) + {#.doc (code.text ($_ text/compose "Lex " " characters as a single continuous text."))} + (-> (Lexer Slice) (Lexer Slice)) + (with-slices ( lexer)))] + + [some! p.some "some"] + [many! p.many "many"] + ) + +(do-template [ ] + [(def: #export ( amount lexer) + {#.doc (code.text ($_ text/compose "Lex " " N characters."))} (-> Nat (Lexer Text) (Lexer Text)) - (do p.Monad - [] - (|> p ( n) (:: @ map text.concat))))] + (|> lexer ( amount) (:: p.Monad map text.concat)))] + + [exactly p.exactly "exactly"] + [at-most p.at-most "at most"] + [at-least p.at-least "at least"] + ) - [exactly p.exactly "Lex exactly N characters."] - [at-most p.at-most "Lex at most N characters."] - [at-least p.at-least "Lex at least N characters."] +(do-template [ ] + [(def: #export ( amount lexer) + {#.doc (code.text ($_ text/compose "Lex " " N characters."))} + (-> Nat (Lexer Slice) (Lexer Slice)) + (with-slices ( amount lexer)))] + + [exactly! p.exactly "exactly"] + [at-most! p.at-most "at most"] + [at-least! p.at-least "at least"] ) -(def: #export (between from to p) +(def: #export (between from to lexer) {#.doc "Lex between N and M characters."} (-> Nat Nat (Lexer Text) (Lexer Text)) - (|> p (p.between from to) (:: p.Monad map text.concat))) + (|> lexer (p.between from to) (:: p.Monad map text.concat))) + +(def: #export (between! from to lexer) + {#.doc "Lex between N and M characters."} + (-> Nat Nat (Lexer Slice) (Lexer Slice)) + (with-slices (p.between from to lexer))) (def: #export (enclosed [start end] lexer) (All [a] (-> [Text Text] (Lexer a) (Lexer a))) @@ -259,3 +338,15 @@ (#e.Success value) (#e.Success [real-input value])))) + +(def: #export (slice lexer) + (-> (Lexer Slice) (Lexer Text)) + (do p.Monad + [[basis distance] lexer] + (function (_ (^@ input [offset tape])) + (case (text.clip basis (n/+ basis distance) tape) + (#.Some output) + (#e.Success [input output]) + + #.None + (#e.Error "Cannot slice."))))) -- cgit v1.2.3 From 726dbf02da1ae0da3965ec0a72e99fec1730f882 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Mon, 20 Aug 2018 22:43:17 -0400 Subject: Small optimizations. --- stdlib/source/lux/compiler/default/syntax.lux | 188 ++++++++++---------------- stdlib/source/lux/data/text/lexer.lux | 2 +- 2 files changed, 71 insertions(+), 119 deletions(-) (limited to 'stdlib') diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux index 322035fd8..ca715e8dd 100644 --- a/stdlib/source/lux/compiler/default/syntax.lux +++ b/stdlib/source/lux/compiler/default/syntax.lux @@ -46,8 +46,14 @@ (type: #export Aliases (Dictionary Text Text)) (def: #export no-aliases Aliases (dictionary.new text.Hash)) +(def: digits "0123456789") +(def: digits+ (format "_" ..digits)) + (def: white-space Text "\t\v \r\f") (def: new-line Text "\n") +(def: new-line^ (l.this new-line)) + +(def: text-delimiter^ (l.this "\"")) ## This is the parser for white-space. ## Whenever a new-line is encountered, the column gets reset to 0, and @@ -55,41 +61,41 @@ ## It operates recursively in order to produce the longest continuous ## chunk of white-space. (def: (space^ where) - (-> Cursor (Lexer [Cursor Any])) + (-> Cursor (Lexer Cursor)) (p.either (do p.Monad [content (l.many! (l.one-of! white-space))] - (wrap [(update@ #.column (n/+ (get@ #l.distance content)) where) - []])) + (wrap (update@ #.column (n/+ (get@ #l.distance content)) where))) ## New-lines must be handled as a separate case to ensure line ## information is handled properly. (do p.Monad [content (l.many! (l.one-of! new-line))] - (wrap [(|> where - (update@ #.line (n/+ (get@ #l.distance content))) - (set@ #.column 0)) - []])))) + (wrap (|> where + (update@ #.line (n/+ (get@ #l.distance content))) + (set@ #.column 0)))))) ## Single-line comments can start anywhere, but only go up to the ## next new-line. (def: (single-line-comment^ where) - (-> Cursor (Lexer [Cursor Text])) + (-> Cursor (Lexer Cursor)) (do p.Monad [_ (l.this "##") - comment (l.slice (l.some! (l.none-of! new-line))) - _ (l.this new-line)] - (wrap [(|> where - (update@ #.line inc) - (set@ #.column 0)) - comment]))) + _ (l.some! (l.none-of! new-line)) + _ ..new-line^] + (wrap (|> where + (update@ #.line inc) + (set@ #.column 0))))) ## This is just a helper parser to find text which doesn't run into ## any special character sequences for multi-line comments. -(def: comment-bound^ +(def: multi-line-comment-start^ (l.this "#(")) +(def: multi-line-comment-end^ (l.this ")#")) + +(def: multi-line-comment-bound^ (Lexer Any) ($_ p.either - (l.this new-line) - (l.this ")#") - (l.this "#("))) + ..new-line^ + ..multi-line-comment-start^ + ..multi-line-comment-end^)) ## Multi-line comments are bounded by #( these delimiters, #(and, they may ## also be nested)# )#. @@ -97,24 +103,21 @@ ## That is, any nested comment must have matched delimiters. ## Unbalanced comments ought to be rejected as invalid code. (def: (multi-line-comment^ where) - (-> Cursor (Lexer [Cursor Text])) + (-> Cursor (Lexer Cursor)) (do p.Monad - [_ (l.this "#(")] - (loop [comment "" - where (update@ #.column (n/+ 2) where)] + [_ ..multi-line-comment-start^] + (loop [where (update@ #.column (n/+ 2) where)] ($_ p.either ## These are normal chunks of commented text. (do @ - [chunk (l.many (l.not comment-bound^))] - (recur (format comment chunk) - (|> where - (update@ #.column (n/+ (text.size chunk)))))) + [chunk (l.many! (l.not! multi-line-comment-bound^))] + (recur (|> where + (update@ #.column (n/+ (get@ #l.distance chunk)))))) ## This is a special rule to handle new-lines within ## comments properly. (do @ - [_ (l.this new-line)] - (recur (format comment new-line) - (|> where + [_ ..new-line^] + (recur (|> where (update@ #.line inc) (set@ #.column 0)))) ## This is the rule for handling nested sub-comments. @@ -124,14 +127,12 @@ ## That is why the sub-comment is covered in delimiters ## and then appended to the rest of the comment text. (do @ - [[sub-where sub-comment] (multi-line-comment^ where)] - (recur (format comment "#(" sub-comment ")#") - sub-where)) + [sub-where (multi-line-comment^ where)] + (recur sub-where)) ## Finally, this is the rule for closing the comment. (do @ - [_ (l.this ")#")] - (wrap [(update@ #.column (n/+ 2) where) - comment])) + [_ ..multi-line-comment-end^] + (wrap (update@ #.column (n/+ 2) where))) )))) ## This is the only parser that should be used directly by other @@ -141,11 +142,11 @@ ## from being used in any situation (alternatively, forcing one type ## of comment to be the only usable one). (def: (comment^ where) - (-> Cursor (Lexer [Cursor Text])) + (-> Cursor (Lexer Cursor)) (p.either (single-line-comment^ where) (multi-line-comment^ where))) -## To simplify parsing, I remove any left-padding that an Code token +## To simplify parsing, I remove any left-padding that a Code token ## may have prior to parsing the token itself. ## Left-padding is assumed to be either white-space or a comment. ## The cursor gets updated, but the padding gets ignored. @@ -153,10 +154,10 @@ (-> Cursor (Lexer Cursor)) ($_ p.either (do p.Monad - [[where comment] (comment^ where)] + [where (comment^ where)] (left-padding^ where)) (do p.Monad - [[where _] (space^ where)] + [where (space^ where)] (left-padding^ where)) (:: p.Monad wrap where))) @@ -187,7 +188,7 @@ [code (l.between 1 4 l.hexadecimal)] (wrap (case (:: number.Hex@Codec decode code) (#.Right value) - [(n/+ 2 (text.size code)) (text.from-code value)] + [("lux i64 +" 2 (text.size code)) (text.from-code value)] _ (undefined)))) @@ -233,32 +234,7 @@ number.Codec] ) -(def: (nat-char where) - (-> Cursor (Lexer [Cursor Code])) - (do p.Monad - [_ (l.this "#\"") - [where' char] (: (Lexer [Cursor Text]) - ($_ p.either - ## Normal text characters. - (do @ - [normal (l.none-of "\\\"\n")] - (wrap [(|> where - (update@ #.column inc)) - normal])) - ## Must handle escaped - ## chars separately. - (do @ - [[chars-consumed char] escaped-char^] - (wrap [(|> where - (update@ #.column (n/+ chars-consumed))) - char])))) - _ (l.this "\"") - #let [char (maybe.assume (text.nth 0 char))]] - (wrap [(|> where' - (update@ #.column inc)) - [where (#.Nat char)]]))) - -(def: (normal-nat where) +(def: #export (nat where) (-> Cursor (Lexer [Cursor Code])) (do p.Monad [chunk rich-digits^] @@ -270,11 +246,6 @@ (wrap [(update@ #.column (n/+ (text.size chunk)) where) [where (#.Nat value)]])))) -(def: #export (nat where) - (-> Cursor (Lexer [Cursor Code])) - (p.either (normal-nat where) - (nat-char where))) - (def: (normal-frac where) (-> Cursor (Lexer [Cursor Code])) (do p.Monad @@ -299,8 +270,8 @@ (def: frac-ratio-fragment (Lexer Frac) (<| (p.codec number.Codec) - (:: p.Monad map (function (_ digits) - (format digits ".0"))) + (parser/map (function (_ digits) + (format digits ".0"))) rich-digits^)) (def: (ratio-frac where) @@ -337,7 +308,7 @@ (do p.Monad [## Lux text "is delimited by double-quotes", as usual in most ## programming languages. - _ (l.this "\"") + _ ..text-delimiter^ ## I must know what column the text body starts at (which is ## always 1 column after the left-delimiting quote). ## This is important because, when procesing subsequent lines, @@ -364,43 +335,28 @@ ## the text's body's column, ## to ensure they are aligned. (do @ - [offset (l.slice (l.many! (l.one-of! " "))) - #let [offset-size (text.size offset)]] - (if (n/>= offset-column offset-size) - ## Any extra offset - ## becomes part of the - ## text's body. - (recur (|> offset - (text.split offset-column) - (maybe.default (undefined)) - product.right - (format text-read)) - (|> where - (update@ #.column (n/+ offset-size))) - #0) - (p.fail (format "Each line of a multi-line text must have an appropriate offset!\n" - "Expected: " (%i (.int offset-column)) " columns.\n" - " Actual: " (%i (.int offset-size)) " columns.\n")))) + [_ (l.exactly! offset-column (l.one-of! " "))] + (recur text-read + (update@ #.column (n/+ offset-column) where) + #0)) ($_ p.either ## Normal text characters. (do @ [normal (l.slice (l.many! (l.none-of! "\\\"\n")))] (recur (format text-read normal) - (|> where - (update@ #.column (n/+ (text.size normal)))) + (update@ #.column (n/+ (text.size normal)) where) #0)) ## Must handle escaped ## chars separately. (do @ [[chars-consumed char] escaped-char^] (recur (format text-read char) - (|> where - (update@ #.column (n/+ chars-consumed))) + (update@ #.column (n/+ chars-consumed) where) #0)) ## The text ends when it ## reaches the right-delimiter. (do @ - [_ (l.this "\"")] + [_ ..text-delimiter^] (wrap [(update@ #.column inc where) text-read])))) ## If a new-line is @@ -409,7 +365,7 @@ ## the loop is alerted that the ## next line must have an offset. (do @ - [_ (l.this new-line)] + [_ ..new-line^] (recur (format text-read new-line) (|> where (update@ #.line inc) @@ -507,15 +463,11 @@ ## a digit, to avoid confusion with regards to numbers. (def: name-part^ (Lexer Text) - (do p.Monad - [#let [digits "0123456789" - delimiters (format "()[]{}#\"" name-separator) - space (format white-space new-line) - head-lexer (l.slice (l.none-of! (format digits delimiters space))) - tail-lexer (l.slice (l.some! (l.none-of! (format delimiters space))))] - head head-lexer - tail tail-lexer] - (wrap (format head tail)))) + (let [delimiters (format "()[]{}#\"" name-separator) + space (format white-space new-line) + head (l.none-of! (format ..digits delimiters space)) + tail (l.some! (l.none-of! (format delimiters space)))] + (l.slice (l.and! head tail)))) (def: current-module-mark Text (format name-separator name-separator)) @@ -530,7 +482,7 @@ [_ (l.this current-module-mark) def-name name-part^] (wrap [[current-module def-name] - (n/+ 2 (text.size def-name))])) + ("lux i64 +" 2 (text.size def-name))])) ## If the name is prefixed by the mark, but no module ## part, the module is assumed to be "lux" (otherwise known as ## the 'prelude'). @@ -558,7 +510,7 @@ second-part name-part^] (wrap [[(|> aliases (dictionary.get first-part) (maybe.default first-part)) second-part] - ($_ n/+ + ($_ "lux i64 +" (text.size first-part) 1 (text.size second-part))])) @@ -571,17 +523,17 @@ (do p.Monad [[value length] (<|
                            (name^ current-module aliases))]
-       (wrap [(update@ #.column (|>> (n/+ )) where)
+       (wrap [(update@ #.column (n/+ ) where)
               [where ( value)]])))]
 
-  [tag        (p.after (l.this "#")) #.Tag        (n/+ 1 length)]
+  [tag        (p.after (l.this "#")) #.Tag        ("lux i64 +" 1 length)]
   [identifier (|>)                   #.Identifier length]
   )
 
 (do-template [ ]
   [(def: 
      (Lexer Bit)
-     (:: p.Monad map (function.constant ) (l.this (%b ))))]
+     (parser/map (function.constant ) (l.this (%b ))))]
 
   [false #0]
   [true  #1]
@@ -591,7 +543,7 @@
   (-> Cursor (Lexer [Cursor Code]))
   (do p.Monad
     [value (p.either ..false ..true)]
-    (wrap [(update@ #.column (|>> (n/+ 2)) where)
+    (wrap [(update@ #.column (n/+ 2) where)
            [where (#.Bit value)]])))
 
 (exception: #export (end-of-file {module Text})
@@ -608,17 +560,17 @@
     (do p.Monad
       [where (left-padding^ where)]
       ($_ p.either
-          (..form where ast')
-          (..tuple where ast')
-          (..record where ast')
-          (..text where)
+          (..bit where)
           (..nat where)
           (..frac where)
-          (..int where)
           (..rev where)
-          (..bit where)
+          (..int where)
+          (..text where)
           (..identifier current-module aliases where)
           (..tag current-module aliases where)
+          (..form where ast')
+          (..tuple where ast')
+          (..record where ast')
           (do @
             [end? l.end?]
             (if end?
diff --git a/stdlib/source/lux/data/text/lexer.lux b/stdlib/source/lux/data/text/lexer.lux
index 3b4b63a26..80e2cea0f 100644
--- a/stdlib/source/lux/data/text/lexer.lux
+++ b/stdlib/source/lux/data/text/lexer.lux
@@ -268,7 +268,7 @@
   (do p.Monad
     [[left::basis left::distance] left
      [right::basis right::distance] right]
-    (wrap [left::basis (n/+ right::distance right::distance)])))
+    (wrap [left::basis (n/+ left::distance right::distance)])))
 
 (do-template [  ]
   [(def: #export ( lexer)
-- 
cgit v1.2.3


From a1944a9d561e76b02717673647b87704118c03a6 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Mon, 20 Aug 2018 23:21:01 -0400
Subject: - More minor optimizations. - Removed ratio syntax for Frac.

---
 stdlib/source/lux/compiler/default/syntax.lux    | 81 ++++++++----------------
 stdlib/source/lux/data/text/lexer.lux            | 64 +++++++++----------
 stdlib/test/test/lux/compiler/default/syntax.lux | 36 -----------
 3 files changed, 59 insertions(+), 122 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index ca715e8dd..50c02c11d 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -50,10 +50,17 @@
 (def: digits+ (format "_" ..digits))
 
 (def: white-space Text "\t\v \r\f")
-(def: new-line Text "\n")
+(def: new-line "\n")
 (def: new-line^ (l.this new-line))
 
-(def: text-delimiter^ (l.this "\""))
+(def: text-delimiter "\"")
+(def: text-delimiter^ (l.this text-delimiter))
+
+(def: escape "\\")
+
+(def: sigil "#")
+
+(def: single-line-comment-marker (format ..sigil ..sigil))
 
 ## This is the parser for white-space.
 ## Whenever a new-line is encountered, the column gets reset to 0, and
@@ -78,7 +85,7 @@
 (def: (single-line-comment^ where)
   (-> Cursor (Lexer Cursor))
   (do p.Monad
-    [_ (l.this "##")
+    [_ (l.this ..single-line-comment-marker)
      _ (l.some! (l.none-of! new-line))
      _ ..new-line^]
     (wrap (|> where
@@ -87,8 +94,8 @@
 
 ## This is just a helper parser to find text which doesn't run into
 ## any special character sequences for multi-line comments.
-(def: multi-line-comment-start^ (l.this "#("))
-(def: multi-line-comment-end^ (l.this ")#"))
+(def: multi-line-comment-start^ (l.this (format ..sigil "(")))
+(def: multi-line-comment-end^ (l.this (format ")" ..sigil)))
 
 (def: multi-line-comment-bound^
   (Lexer Any)
@@ -168,19 +175,19 @@
 ## Escaped characters may show up in Char and Text literals.
 (def: escaped-char^
   (Lexer [Nat Text])
-  (p.after (l.this "\\")
+  (p.after (l.this ..escape)
            (do p.Monad
              [code l.any]
              (case code
                ## Handle special cases.
-               "t"  (wrap [2 "\t"])
-               "v"  (wrap [2 "\v"])
-               "b"  (wrap [2 "\b"])
-               "n"  (wrap [2 "\n"])
-               "r"  (wrap [2 "\r"])
-               "f"  (wrap [2 "\f"])
-               "\"" (wrap [2 "\""])
-               "\\" (wrap [2 "\\"])
+               "t" (wrap [2 "\t"])
+               "v" (wrap [2 "\v"])
+               "b" (wrap [2 "\b"])
+               "n" (wrap [2 ..new-line])
+               "r" (wrap [2 "\r"])
+               "f" (wrap [2 "\f"])
+               (^ (static ..text-delimiter)) (wrap [2 ..text-delimiter])
+               (^ (static ..escape)) (wrap [2 ..escape])
 
                ## Handle unicode escapes.
                "u"
@@ -246,7 +253,7 @@
       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
              [where (#.Nat value)]]))))
 
-(def: (normal-frac where)
+(def: #export (frac where)
   (-> Cursor (Lexer [Cursor Code]))
   (do p.Monad
     [chunk ($_ l.and
@@ -267,40 +274,6 @@
       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
              [where (#.Frac value)]]))))
 
-(def: frac-ratio-fragment
-  (Lexer Frac)
-  (<| (p.codec number.Codec)
-      (parser/map (function (_ digits)
-                    (format digits ".0")))
-      rich-digits^))
-
-(def: (ratio-frac where)
-  (-> Cursor (Lexer [Cursor Code]))
-  (do p.Monad
-    [chunk ($_ l.and
-               (p.default "" (l.one-of "-"))
-               rich-digits^
-               (l.one-of "/")
-               rich-digits^)
-     value (l.local chunk
-                    (do @
-                      [signed? (l.this? "-")
-                       numerator frac-ratio-fragment
-                       _ (l.this? "/")
-                       denominator frac-ratio-fragment
-                       _ (p.assert "Denominator cannot be 0."
-                                   (not (f/= +0.0 denominator)))]
-                      (wrap (|> numerator
-                                (f/* (if signed? -1.0 +1.0))
-                                (f// denominator)))))]
-    (wrap [(update@ #.column (n/+ (text.size chunk)) where)
-           [where (#.Frac value)]])))
-
-(def: #export (frac where)
-  (-> Cursor (Lexer [Cursor Code]))
-  (p.either (normal-frac where)
-            (ratio-frac where)))
-
 ## This parser looks so complex because text in Lux can be multi-line
 ## and there are rules regarding how this is handled.
 (def: #export (text where)
@@ -342,7 +315,7 @@
                                          ($_ p.either
                                              ## Normal text characters.
                                              (do @
-                                               [normal (l.slice (l.many! (l.none-of! "\\\"\n")))]
+                                               [normal (l.slice (l.many! (l.none-of! (format ..escape ..text-delimiter ..new-line))))]
                                                (recur (format text-read normal)
                                                       (update@ #.column (n/+ (text.size normal)) where)
                                                       #0))
@@ -463,13 +436,13 @@
 ## a digit, to avoid confusion with regards to numbers.
 (def: name-part^
   (Lexer Text)
-  (let [delimiters (format "()[]{}#\"" name-separator)
+  (let [delimiters (format "()[]{}" ..sigil ..text-delimiter ..name-separator)
         space (format white-space new-line)
         head (l.none-of! (format ..digits delimiters space))
         tail (l.some! (l.none-of! (format delimiters space)))]
     (l.slice (l.and! head tail))))
 
-(def: current-module-mark Text (format name-separator name-separator))
+(def: current-module-mark Text (format ..name-separator ..name-separator))
 
 (def: (name^ current-module aliases)
   (-> Text Aliases (Lexer [Name Nat]))
@@ -526,8 +499,8 @@
        (wrap [(update@ #.column (n/+ ) where)
               [where ( value)]])))]
 
-  [tag        (p.after (l.this "#")) #.Tag        ("lux i64 +" 1 length)]
-  [identifier (|>)                   #.Identifier length]
+  [tag        (p.after (l.this ..sigil)) #.Tag        ("lux i64 +" 1 length)]
+  [identifier (|>)                       #.Identifier length]
   )
 
 (do-template [ ]
diff --git a/stdlib/source/lux/data/text/lexer.lux b/stdlib/source/lux/data/text/lexer.lux
index 80e2cea0f..677810eb8 100644
--- a/stdlib/source/lux/data/text/lexer.lux
+++ b/stdlib/source/lux/data/text/lexer.lux
@@ -4,14 +4,14 @@
     [monad (#+ do Monad)]
     ["p" parser]]
    [data
-    ["." text ("text/." Monoid)]
     ["." product]
     ["." maybe]
     ["e" error]
     [collection
      ["." list ("list/." Fold)]]]
    [macro
-    ["." code]]])
+    ["." code]]]
+  ["." // ("text/." Monoid)])
 
 (type: Offset Nat)
 
@@ -26,7 +26,7 @@
 
 (def: (remaining offset tape)
   (-> Offset Text Text)
-  (|> tape (text.split offset) maybe.assume product.right))
+  (|> tape (//.split offset) maybe.assume product.right))
 
 (def: cannot-lex-error Text "Cannot lex from empty text.")
 
@@ -41,7 +41,7 @@
     (#e.Error msg)
     
     (#e.Success [[end-offset _] output])
-    (if (n/= end-offset (text.size input))
+    (if (n/= end-offset (//.size input))
       (#e.Success output)
       (#e.Error (unconsumed-input-error end-offset input)))
     ))
@@ -67,9 +67,9 @@
   {#.doc "Just returns the next character without applying any logic."}
   (Lexer Text)
   (function (_ [offset tape])
-    (case (text.nth offset tape)
+    (case (//.nth offset tape)
       (#.Some output)
-      (#e.Success [[(inc offset) tape] (text.from-code output)])
+      (#e.Success [[(inc offset) tape] (//.from-code output)])
 
       _
       (#e.Error cannot-lex-error))))
@@ -102,22 +102,22 @@
   {#.doc "Lex a text if it matches the given sample."}
   (-> Text (Lexer Any))
   (function (_ [offset tape])
-    (case (text.index-of' reference offset tape)
+    (case (//.index-of' reference offset tape)
       (#.Some where)
       (if (n/= offset where)
-        (#e.Success [[(n/+ (text.size reference) offset) tape] []])
-        (#e.Error ($_ text/compose "Could not match: " (text.encode reference) " @ " (maybe.assume (text.clip' offset tape)))))
+        (#e.Success [[(n/+ (//.size reference) offset) tape] []])
+        (#e.Error ($_ text/compose "Could not match: " (//.encode reference) " @ " (maybe.assume (//.clip' offset tape)))))
 
       _
-      (#e.Error ($_ text/compose "Could not match: " (text.encode reference))))))
+      (#e.Error ($_ text/compose "Could not match: " (//.encode reference))))))
 
 (def: #export (this? reference)
   {#.doc "Lex a text if it matches the given sample."}
   (-> Text (Lexer Bit))
   (function (_ (^@ input [offset tape]))
-    (case (text.index-of' reference offset tape)
+    (case (//.index-of' reference offset tape)
       (^multi (#.Some where) (n/= offset where))
-      (#e.Success [[(n/+ (text.size reference) offset) tape] #1])
+      (#e.Success [[(n/+ (//.size reference) offset) tape] #1])
 
       _
       (#e.Success [input #0]))))
@@ -126,7 +126,7 @@
   {#.doc "Ensure the lexer's input is empty."}
   (Lexer Any)
   (function (_ (^@ input [offset tape]))
-    (if (n/= offset (text.size tape))
+    (if (n/= offset (//.size tape))
       (#e.Success [input []])
       (#e.Error (unconsumed-input-error offset tape)))))
 
@@ -134,15 +134,15 @@
   {#.doc "Ask if the lexer's input is empty."}
   (Lexer Bit)
   (function (_ (^@ input [offset tape]))
-    (#e.Success [input (n/= offset (text.size tape))])))
+    (#e.Success [input (n/= offset (//.size tape))])))
 
 (def: #export peek
   {#.doc "Lex the next character (without consuming it from the input)."}
   (Lexer Text)
   (function (_ (^@ input [offset tape]))
-    (case (text.nth offset tape)
+    (case (//.nth offset tape)
       (#.Some output)
-      (#e.Success [input (text.from-code output)])
+      (#e.Success [input (//.from-code output)])
 
       _
       (#e.Error cannot-lex-error))))
@@ -158,8 +158,8 @@
   (-> Nat Nat (Lexer Text))
   (do p.Monad
     [char any
-     #let [char' (maybe.assume (text.nth 0 char))]
-     _ (p.assert ($_ text/compose "Character is not within range: " (text.from-code bottom) "-" (text.from-code top))
+     #let [char' (maybe.assume (//.nth 0 char))]
+     _ (p.assert ($_ text/compose "Character is not within range: " (//.from-code bottom) "-" (//.from-code top))
                  (.and (n/>= bottom char')
                        (n/<= top char')))]
     (wrap char)))
@@ -199,10 +199,10 @@
      {#.doc (code.text ($_ text/compose "Only lex characters that are"  " part of a piece of text."))}
      (-> Text (Lexer Text))
      (function (_ [offset tape])
-       (case (text.nth offset tape)
+       (case (//.nth offset tape)
          (#.Some output)
-         (let [output (text.from-code output)]
-           (if ( (text.contains? output options))
+         (let [output (//.from-code output)]
+           (if ( (//.contains? output options))
              (#e.Success [[(inc offset) tape] output])
              (#e.Error ($_ text/compose "Character (" output
                            ") is should " 
@@ -220,10 +220,10 @@
      {#.doc (code.text ($_ text/compose "Only lex characters that are"  " part of a piece of text."))}
      (-> Text (Lexer Slice))
      (function (_ [offset tape])
-       (case (text.nth offset tape)
+       (case (//.nth offset tape)
          (#.Some output)
-         (let [output (text.from-code output)]
-           (if ( (text.contains? output options))
+         (let [output (//.from-code output)]
+           (if ( (//.contains? output options))
              (#e.Success [[(inc offset) tape]
                           {#basis offset
                            #distance 1}])
@@ -242,11 +242,11 @@
   {#.doc "Only lex characters that satisfy a predicate."}
   (-> (-> Nat Bit) (Lexer Text))
   (function (_ [offset tape])
-    (case (text.nth offset tape)
+    (case (//.nth offset tape)
       (#.Some output)
       (if (p output)
-        (#e.Success [[(inc offset) tape] (text.from-code output)])
-        (#e.Error ($_ text/compose "Character does not satisfy predicate: " (text.from-code output))))
+        (#e.Success [[(inc offset) tape] (//.from-code output)])
+        (#e.Error ($_ text/compose "Character does not satisfy predicate: " (//.from-code output))))
 
       _
       (#e.Error cannot-lex-error))))
@@ -254,7 +254,7 @@
 (def: #export space
   {#.doc "Only lex white-space."}
   (Lexer Text)
-  (satisfies text.space?))
+  (satisfies //.space?))
 
 (def: #export (and left right)
   (-> (Lexer Text) (Lexer Text) (Lexer Text))
@@ -274,7 +274,7 @@
   [(def: #export ( lexer)
      {#.doc (code.text ($_ text/compose "Lex "  " characters as a single continuous text."))}
      (-> (Lexer Text) (Lexer Text))
-     (|> lexer  (:: p.Monad map text.concat)))]
+     (|> lexer  (:: p.Monad map //.concat)))]
 
   [some p.some "some"]
   [many p.many "many"]
@@ -294,7 +294,7 @@
   [(def: #export ( amount lexer)
      {#.doc (code.text ($_ text/compose "Lex "  " N characters."))}
      (-> Nat (Lexer Text) (Lexer Text))
-     (|> lexer ( amount) (:: p.Monad map text.concat)))]
+     (|> lexer ( amount) (:: p.Monad map //.concat)))]
 
   [exactly  p.exactly  "exactly"]
   [at-most  p.at-most  "at most"]
@@ -315,7 +315,7 @@
 (def: #export (between from to lexer)
   {#.doc "Lex between N and M characters."}
   (-> Nat Nat (Lexer Text) (Lexer Text))
-  (|> lexer (p.between from to) (:: p.Monad map text.concat)))
+  (|> lexer (p.between from to) (:: p.Monad map //.concat)))
 
 (def: #export (between! from to lexer)
   {#.doc "Lex between N and M characters."}
@@ -344,7 +344,7 @@
   (do p.Monad
     [[basis distance] lexer]
     (function (_ (^@ input [offset tape]))
-      (case (text.clip basis (n/+ basis distance) tape)
+      (case (//.clip basis (n/+ basis distance) tape)
         (#.Some output)
         (#e.Success [input output])
 
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index 2b4a8f5b6..a9baa546c 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -112,42 +112,6 @@
                            (:: code.Equivalence = other =other)))))
             ))))
 
-(context: "Frac special syntax."
-  (<| (times 100)
-      (do @
-        [numerator (|> r.nat (:: @ map (|>> (n/% 100) .int int-to-frac)))
-         denominator (|> r.nat (:: @ map (|>> (n/% 100) (n/max 1) .int int-to-frac)))
-         signed? r.bit
-         #let [expected (|> numerator (f// denominator) (f/* (if signed? -1.0 +1.0)))]]
-        (test "Can parse frac ratio syntax."
-              (case (&.read "" (dict.new text.Hash)
-                            [default-cursor 0
-                             (format (if signed? "-" "+")
-                                     (%i (frac-to-int numerator))
-                                     "/"
-                                     (%i (frac-to-int denominator)))])
-                (#e.Success [_ [_ (#.Frac actual)]])
-                (f/= expected actual)
-
-                _
-                #0)
-              ))))
-
-(context: "Nat special syntax."
-  (<| (times 100)
-      (do @
-        [expected (|> r.nat (:: @ map (n/% 1_000)))]
-        (test "Can parse nat char syntax."
-              (case (&.read "" (dict.new text.Hash)
-                            [default-cursor 0
-                             (format "#" (%t (text.from-code expected)) "")])
-                (#e.Success [_ [_ (#.Nat actual)]])
-                (n/= expected actual)
-
-                _
-                #0)
-              ))))
-
 (def: comment-text^
   (r.Random Text)
   (let [char-gen (|> r.nat (r.filter (function (_ value)
-- 
cgit v1.2.3


From 9ccc8ea44ebe4f9a3d40c8e94b55f77c0d815099 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Mon, 20 Aug 2018 23:23:02 -0400
Subject: Some refactoring.

---
 stdlib/source/lux.lux | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index bf92eb4db..d64b83bd3 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -19,7 +19,7 @@
          (1 [[dummy-cursor (7 ["lux" "export?"])]
              [dummy-cursor (0 #1)]]
             (1 [[dummy-cursor (7 ["lux" "doc"])]
-                [dummy-cursor (5 "The type of things whose type does not matter.
+                [dummy-cursor (5 "The type of things whose type is irrelevant.
 
                                   It can be used to write functions or data-structures that can take, or return, anything.")]]
                (0)))))])
@@ -35,7 +35,7 @@
          (1 [[dummy-cursor (7 ["lux" "export?"])]
              [dummy-cursor (0 #1)]]
             (1 [[dummy-cursor (7 ["lux" "doc"])]
-                [dummy-cursor (5 "The type of things whose type is unknown or undefined.
+                [dummy-cursor (5 "The type of things whose type is undefined.
 
                                   Useful for expressions that cause errors or other \"extraordinary\" conditions.")]]
                (0)))))])
-- 
cgit v1.2.3


From 81a04b5935cd755efb4096d5e3f347cd0bb6cdef Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Tue, 21 Aug 2018 00:35:28 -0400
Subject: Minor optimizations + timing.

---
 stdlib/source/lux/compiler/default/syntax.lux | 205 +++++++++++++++-----------
 stdlib/source/lux/data/text/lexer.lux         |  22 +--
 2 files changed, 135 insertions(+), 92 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 50c02c11d..21b142ec0 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -39,9 +39,30 @@
      ["l" lexer (#+ Lexer)]
      format]
     [collection
-     ["." row (#+ Row)]
      ["." dictionary (#+ Dictionary)]]]
-   ["." function]])
+   ["." function]
+   ["." io]
+   [time
+    ["." instant]
+    ["." duration]]])
+
+(type: #export Syntax
+  (-> Cursor (Lexer [Cursor Code])))
+
+(def: #export (timed description lexer)
+  (All [a]
+    (-> Text (Lexer [Cursor Code]) (Lexer [Cursor Code])))
+  (do p.Monad
+    [_ (wrap [])
+     #let [pre (io.run instant.now)]
+     [where output] lexer
+     #let [_ (log! (|> instant.now
+                       io.run
+                       instant.relative
+                       (duration.difference (instant.relative pre))
+                       %duration
+                       (format (%code output) " [" description "]: ")))]]
+    (wrap [where output])))
 
 (type: #export Aliases (Dictionary Text Text))
 (def: #export no-aliases Aliases (dictionary.new text.Hash))
@@ -56,6 +77,15 @@
 (def: text-delimiter "\"")
 (def: text-delimiter^ (l.this text-delimiter))
 
+(def: open-form "(")
+(def: close-form ")")
+
+(def: open-tuple "[")
+(def: close-tuple "]")
+
+(def: open-record "{")
+(def: close-record "}")
+
 (def: escape "\\")
 
 (def: sigil "#")
@@ -94,8 +124,8 @@
 
 ## This is just a helper parser to find text which doesn't run into
 ## any special character sequences for multi-line comments.
-(def: multi-line-comment-start^ (l.this (format ..sigil "(")))
-(def: multi-line-comment-end^ (l.this (format ")" ..sigil)))
+(def: multi-line-comment-start^ (l.this (format ..sigil open-form)))
+(def: multi-line-comment-end^ (l.this (format close-form ..sigil)))
 
 (def: multi-line-comment-bound^
   (Lexer Any)
@@ -220,7 +250,7 @@
 
 (do-template [   ]
   [(def: #export ( where)
-     (-> Cursor (Lexer [Cursor Code]))
+     Syntax
      (do p.Monad
        [chunk ]
        (case (::  decode chunk)
@@ -242,7 +272,7 @@
   )
 
 (def: #export (nat where)
-  (-> Cursor (Lexer [Cursor Code]))
+  Syntax
   (do p.Monad
     [chunk rich-digits^]
     (case (:: number.Codec decode chunk)
@@ -254,7 +284,7 @@
              [where (#.Nat value)]]))))
 
 (def: #export (frac where)
-  (-> Cursor (Lexer [Cursor Code]))
+  Syntax
   (do p.Monad
     [chunk ($_ l.and
                sign^
@@ -277,7 +307,7 @@
 ## This parser looks so complex because text in Lux can be multi-line
 ## and there are rules regarding how this is handled.
 (def: #export (text where)
-  (-> Cursor (Lexer [Cursor Code]))
+  Syntax
   (do p.Monad
     [## Lux text "is delimited by double-quotes", as usual in most
      ## programming languages.
@@ -289,7 +319,7 @@
      ## as many spaces as necessary to be column-aligned.
      ## This helps ensure that the formatting on the text in the
      ## source-code matches the formatting of the Text value.
-     #let [offset-column (inc (get@ #.column where))]
+     #let [offset (inc (get@ #.column where))]
      [where' text-read] (: (Lexer [Cursor Text])
                            ## I must keep track of how much of the
                            ## text body has been read, how far the
@@ -308,9 +338,9 @@
                                          ## the text's body's column,
                                          ## to ensure they are aligned.
                                          (do @
-                                           [_ (l.exactly! offset-column (l.one-of! " "))]
+                                           [_ (p.exactly offset (l.this " "))]
                                            (recur text-read
-                                                  (update@ #.column (n/+ offset-column) where)
+                                                  (update@ #.column (n/+ offset) where)
                                                   #0))
                                          ($_ p.either
                                              ## Normal text characters.
@@ -347,38 +377,43 @@
     (wrap [where'
            [where (#.Text text-read)]])))
 
+(def: (composite open close element)
+  (All [a]
+    (-> Text Text
+        (-> Cursor (Lexer [Cursor a]))
+        (-> Cursor (Lexer [Cursor (List a)]))))
+  (let [open^ (l.this open)
+        close^ (l.this close)]
+    (function (_ where)
+      (do p.Monad
+        [_ open^]
+        (loop [where where]
+          (p.either (do @
+                      [## Must update the cursor as I
+                       ## go along, to keep things accurate.
+                       [where' head] (element where)]
+                      (parser/map (product.both id (|>> (#.Cons head)))
+                                  (recur where')))
+                    (do @
+                      [## Must take into account any
+                       ## padding present before the
+                       ## end-delimiter.
+                       where' (left-padding^ where)
+                       _ close^]
+                      (wrap [(update@ #.column inc where')
+                             #.Nil]))))))))
+
 ## Form and tuple syntax is mostly the same, differing only in the
 ## delimiters involved.
 ## They may have an arbitrary number of arbitrary Code nodes as elements.
 (do-template [   ]
-  [(def: ( where ast)
-     (-> Cursor
-         (-> Cursor (Lexer [Cursor Code]))
-         (Lexer [Cursor Code]))
-     (do p.Monad
-       [_ (l.this )
-        [where' elems] (loop [elems (: (Row Code)
-                                       row.empty)
-                              where where]
-                         (p.either (do @
-                                     [## Must update the cursor as I
-                                      ## go along, to keep things accurate.
-                                      [where' elem] (ast where)]
-                                     (recur (row.add elem elems)
-                                            where'))
-                                   (do @
-                                     [## Must take into account any
-                                      ## padding present before the
-                                      ## end-delimiter.
-                                      where' (left-padding^ where)
-                                      _ (l.this )]
-                                     (wrap [(update@ #.column inc where')
-                                            (row.to-list elems)]))))]
-       (wrap [where'
-              [where ( elems)]])))]
-
-  [form   #.Form   "(" ")"]
-  [tuple  #.Tuple  "[" "]"]
+  [(def: ( ast where)
+     (-> Syntax Syntax)
+     (<| (parser/map (product.both id (|>>  [where])))
+         (composite   ast where)))]
+
+  [form  #.Form  ..open-form ..close-form]
+  [tuple #.Tuple ..open-tuple ..close-tuple]
   )
 
 ## Records are almost (syntactically) the same as forms and tuples,
@@ -390,27 +425,16 @@
 ## Code node, however, record Code nodes allow any Code node to occupy
 ## this position, since it may be useful when processing Code syntax in
 ## macros.
-(def: (record where ast)
-  (-> Cursor
-      (-> Cursor (Lexer [Cursor Code]))
-      (Lexer [Cursor Code]))
-  (do p.Monad
-    [_ (l.this "{")
-     [where' elems] (loop [elems (: (Row [Code Code])
-                                    row.empty)
-                           where where]
-                      (p.either (do @
-                                  [[where' key] (ast where)
-                                   [where' val] (ast where')]
-                                  (recur (row.add [key val] elems)
-                                         where'))
-                                (do @
-                                  [where' (left-padding^ where)
-                                   _ (l.this "}")]
-                                  (wrap [(update@ #.column inc where')
-                                         (row.to-list elems)]))))]
-    (wrap [where'
-           [where (#.Record elems)]])))
+(def: (record ast where)
+  (-> Syntax Syntax)
+  (<| (parser/map (product.both id (|>> #.Record [where])))
+      (composite ..open-record ..close-record
+                 (function (_ where')
+                   (do p.Monad
+                     [[where' key] (ast where')
+                      [where' val] (ast where')]
+                     (wrap [where' [key val]])))
+                 where)))
 
 ## The parts of an name are separated by a single mark.
 ## E.g. module.short.
@@ -436,8 +460,13 @@
 ## a digit, to avoid confusion with regards to numbers.
 (def: name-part^
   (Lexer Text)
-  (let [delimiters (format "()[]{}" ..sigil ..text-delimiter ..name-separator)
-        space (format white-space new-line)
+  (let [delimiters (format ..open-form ..close-form
+                           ..open-tuple ..close-tuple
+                           ..open-record ..close-record
+                           ..sigil
+                           ..text-delimiter
+                           ..name-separator)
+        space (format ..white-space ..new-line)
         head (l.none-of! (format ..digits delimiters space))
         tail (l.some! (l.none-of! (format delimiters space)))]
     (l.slice (l.and! head tail))))
@@ -491,13 +520,14 @@
                          (text.size first-part)])))))
 
 (do-template [ 
  ]
-  [(def: #export ( current-module aliases where)
-     (-> Text Aliases Cursor (Lexer [Cursor Code]))
-     (do p.Monad
-       [[value length] (<| 
-                           (name^ current-module aliases))]
-       (wrap [(update@ #.column (n/+ ) where)
-              [where ( value)]])))]
+  [(def: #export ( current-module aliases)
+     (-> Text Aliases Syntax)
+     (function (_ where)
+       (do p.Monad
+         [[value length] (<| 
+                             (name^ current-module aliases))]
+         (wrap [(update@ #.column (n/+ ) where)
+                [where ( value)]]))))]
 
   [tag        (p.after (l.this ..sigil)) #.Tag        ("lux i64 +" 1 length)]
   [identifier (|>)                       #.Identifier length]
@@ -513,7 +543,7 @@
   )
 
 (def: #export (bit where)
-  (-> Cursor (Lexer [Cursor Code]))
+  Syntax
   (do p.Monad
     [value (p.either ..false ..true)]
     (wrap [(update@ #.column (n/+ 2) where)
@@ -528,22 +558,33 @@
              ["Column" (%n column)]))
 
 (def: (ast current-module aliases)
-  (-> Text Aliases Cursor (Lexer [Cursor Code]))
+  (-> Text Aliases Syntax)
   (function (ast' where)
     (do p.Monad
       [where (left-padding^ where)]
       ($_ p.either
-          (..bit where)
-          (..nat where)
-          (..frac where)
-          (..rev where)
-          (..int where)
-          (..text where)
-          (..identifier current-module aliases where)
-          (..tag current-module aliases where)
-          (..form where ast')
-          (..tuple where ast')
-          (..record where ast')
+          (<| (..timed "bit")
+              (..bit where))
+          (<| (..timed "nat")
+              (..nat where))
+          (<| (..timed "frac")
+              (..frac where))
+          (<| (..timed "rev")
+              (..rev where))
+          (<| (..timed "int")
+              (..int where))
+          (<| (..timed "text")
+              (..text where))
+          (<| (..timed "identifier")
+              (..identifier current-module aliases where))
+          (<| (..timed "tag")
+              (..tag current-module aliases where))
+          (<| (..timed "form")
+              (..form ast' where))
+          (<| (..timed "tuple")
+              (..tuple ast' where))
+          (<| (..timed "record")
+              (..record ast' where))
           (do @
             [end? l.end?]
             (if end?
diff --git a/stdlib/source/lux/data/text/lexer.lux b/stdlib/source/lux/data/text/lexer.lux
index 677810eb8..e6186aea8 100644
--- a/stdlib/source/lux/data/text/lexer.lux
+++ b/stdlib/source/lux/data/text/lexer.lux
@@ -58,7 +58,7 @@
      slices lexer]
     (wrap (list/fold (function (_ [slice::basis slice::distance]
                                   [total::basis total::distance])
-                       [total::basis (n/+ slice::distance total::distance)])
+                       [total::basis ("lux i64 +" slice::distance total::distance)])
                      {#basis offset
                       #distance 0}
                      slices))))
@@ -69,7 +69,7 @@
   (function (_ [offset tape])
     (case (//.nth offset tape)
       (#.Some output)
-      (#e.Success [[(inc offset) tape] (//.from-code output)])
+      (#e.Success [[("lux i64 +" 1 offset) tape] (//.from-code output)])
 
       _
       (#e.Error cannot-lex-error))))
@@ -78,7 +78,7 @@
   {#.doc "Just returns the next character without applying any logic."}
   (Lexer Slice)
   (function (_ [offset tape])
-    (#e.Success [[(inc offset) tape]
+    (#e.Success [[("lux i64 +" 1 offset) tape]
                  {#basis offset
                   #distance 1}])))
 
@@ -105,7 +105,8 @@
     (case (//.index-of' reference offset tape)
       (#.Some where)
       (if (n/= offset where)
-        (#e.Success [[(n/+ (//.size reference) offset) tape] []])
+        (#e.Success [[("lux i64 +" (//.size reference) offset) tape]
+                     []])
         (#e.Error ($_ text/compose "Could not match: " (//.encode reference) " @ " (maybe.assume (//.clip' offset tape)))))
 
       _
@@ -117,7 +118,8 @@
   (function (_ (^@ input [offset tape]))
     (case (//.index-of' reference offset tape)
       (^multi (#.Some where) (n/= offset where))
-      (#e.Success [[(n/+ (//.size reference) offset) tape] #1])
+      (#e.Success [[("lux i64 +" (//.size reference) offset) tape]
+                   #1])
 
       _
       (#e.Success [input #0]))))
@@ -203,7 +205,7 @@
          (#.Some output)
          (let [output (//.from-code output)]
            (if ( (//.contains? output options))
-             (#e.Success [[(inc offset) tape] output])
+             (#e.Success [[("lux i64 +" 1 offset) tape] output])
              (#e.Error ($_ text/compose "Character (" output
                            ") is should " 
                            "be one of: " options))))
@@ -224,7 +226,7 @@
          (#.Some output)
          (let [output (//.from-code output)]
            (if ( (//.contains? output options))
-             (#e.Success [[(inc offset) tape]
+             (#e.Success [[("lux i64 +" 1 offset) tape]
                           {#basis offset
                            #distance 1}])
              (#e.Error ($_ text/compose "Character (" output
@@ -245,7 +247,7 @@
     (case (//.nth offset tape)
       (#.Some output)
       (if (p output)
-        (#e.Success [[(inc offset) tape] (//.from-code output)])
+        (#e.Success [[("lux i64 +" 1 offset) tape] (//.from-code output)])
         (#e.Error ($_ text/compose "Character does not satisfy predicate: " (//.from-code output))))
 
       _
@@ -268,7 +270,7 @@
   (do p.Monad
     [[left::basis left::distance] left
      [right::basis right::distance] right]
-    (wrap [left::basis (n/+ left::distance right::distance)])))
+    (wrap [left::basis ("lux i64 +" left::distance right::distance)])))
 
 (do-template [  ]
   [(def: #export ( lexer)
@@ -344,7 +346,7 @@
   (do p.Monad
     [[basis distance] lexer]
     (function (_ (^@ input [offset tape]))
-      (case (//.clip basis (n/+ basis distance) tape)
+      (case (//.clip basis ("lux i64 +" basis distance) tape)
         (#.Some output)
         (#e.Success [input output])
 
-- 
cgit v1.2.3


From 2d430f16e801b2589f7bfdfae943ccbd8ea90b5c Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Tue, 21 Aug 2018 01:06:35 -0400
Subject: Extra logging & optimizations.

---
 stdlib/source/lux/compiler/default/syntax.lux | 57 +++++++++++++++++----------
 1 file changed, 37 insertions(+), 20 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 21b142ec0..b7b2d06d8 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -49,9 +49,23 @@
 (type: #export Syntax
   (-> Cursor (Lexer [Cursor Code])))
 
-(def: #export (timed description lexer)
+(def: (timed' description lexer)
   (All [a]
-    (-> Text (Lexer [Cursor Code]) (Lexer [Cursor Code])))
+    (-> Text (Lexer a) (Lexer a)))
+  (do p.Monad
+    [_ (wrap [])
+     #let [pre (io.run instant.now)]
+     output lexer
+     #let [_ (log! (|> instant.now
+                       io.run
+                       instant.relative
+                       (duration.difference (instant.relative pre))
+                       %duration
+                       (format "[" description "]: ")))]]
+    (wrap output)))
+
+(def: (timed description lexer)
+  (-> Text (Lexer [Cursor Code]) (Lexer [Cursor Code]))
   (do p.Monad
     [_ (wrap [])
      #let [pre (io.run instant.now)]
@@ -319,7 +333,7 @@
      ## as many spaces as necessary to be column-aligned.
      ## This helps ensure that the formatting on the text in the
      ## source-code matches the formatting of the Text value.
-     #let [offset (inc (get@ #.column where))]
+     #let [offset ("lux i64 +" 1 (get@ #.column where))]
      [where' text-read] (: (Lexer [Cursor Text])
                            ## I must keep track of how much of the
                            ## text body has been read, how far the
@@ -387,21 +401,24 @@
     (function (_ where)
       (do p.Monad
         [_ open^]
-        (loop [where where]
-          (p.either (do @
-                      [## Must update the cursor as I
-                       ## go along, to keep things accurate.
-                       [where' head] (element where)]
-                      (parser/map (product.both id (|>> (#.Cons head)))
-                                  (recur where')))
-                    (do @
-                      [## Must take into account any
-                       ## padding present before the
-                       ## end-delimiter.
-                       where' (left-padding^ where)
-                       _ close^]
-                      (wrap [(update@ #.column inc where')
-                             #.Nil]))))))))
+        (loop [where (update@ #.column inc where)]
+          (p.either (<| (timed' "composite CONS")
+                        (do @
+                          [## Must update the cursor as I
+                           ## go along, to keep things accurate.
+                           [where' head] (<| (timed' "composite HEAD")
+                                             (element where))]
+                          (parser/map (product.both id (|>> (#.Cons head)))
+                                      (recur where'))))
+                    (<| (timed' "composite NIL")
+                        (do @
+                          [## Must take into account any
+                           ## padding present before the
+                           ## end-delimiter.
+                           where' (left-padding^ where)
+                           _ close^]
+                          (wrap [(update@ #.column inc where')
+                                 #.Nil])))))))))
 
 ## Form and tuple syntax is mostly the same, differing only in the
 ## delimiters involved.
@@ -412,7 +429,7 @@
      (<| (parser/map (product.both id (|>>  [where])))
          (composite   ast where)))]
 
-  [form  #.Form  ..open-form ..close-form]
+  [form  #.Form  ..open-form  ..close-form]
   [tuple #.Tuple ..open-tuple ..close-tuple]
   )
 
@@ -495,7 +512,7 @@
         [_ (l.this name-separator)
          def-name name-part^]
         (wrap [["lux" def-name]
-               (inc (text.size def-name))]))
+               ("lux i64 +" 1 (text.size def-name))]))
       ## Not all names must be specified with a module part.
       ## If that part is not provided, the name will be created
       ## with the empty "" text as the module.
-- 
cgit v1.2.3


From 1bcf5f7a124a1f8b3aa8c994edf2ec824799ab2f Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Tue, 21 Aug 2018 21:42:49 -0400
Subject: Low-level re-implementation of the parser.

---
 stdlib/source/lux/compiler/default/syntax.lux | 320 +++++++++++++++++++++-----
 stdlib/source/lux/data/text/lexer.lux         |   2 +-
 2 files changed, 264 insertions(+), 58 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index b7b2d06d8..4d778136f 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -31,14 +31,15 @@
     ["p" parser ("parser/." Monad)]
     ["ex" exception (#+ exception:)]]
    [data
-    ["e" error]
+    ["." error (#+ Error)]
     ["." number]
     ["." product]
     ["." maybe]
     ["." text
-     ["l" lexer (#+ Lexer)]
+     ["l" lexer (#+ Offset Lexer)]
      format]
     [collection
+     ["." list]
      ["." dictionary (#+ Dictionary)]]]
    ["." function]
    ["." io]
@@ -84,7 +85,8 @@
 (def: digits "0123456789")
 (def: digits+ (format "_" ..digits))
 
-(def: white-space Text "\t\v \r\f")
+(def: white-space " ")
+(def: carriage-return "\r")
 (def: new-line "\n")
 (def: new-line^ (l.this new-line))
 
@@ -104,6 +106,8 @@
 
 (def: sigil "#")
 
+(def: digit-separator "_")
+
 (def: single-line-comment-marker (format ..sigil ..sigil))
 
 ## This is the parser for white-space.
@@ -285,17 +289,17 @@
    number.Codec]
   )
 
-(def: #export (nat where)
-  Syntax
-  (do p.Monad
-    [chunk rich-digits^]
-    (case (:: number.Codec decode chunk)
-      (#.Left error)
-      (p.fail error)
+## (def: #export (nat where)
+##   Syntax
+##   (do p.Monad
+##     [chunk rich-digits^]
+##     (case (:: number.Codec decode chunk)
+##       (#.Left error)
+##       (p.fail error)
 
-      (#.Right value)
-      (wrap [(update@ #.column (n/+ (text.size chunk)) where)
-             [where (#.Nat value)]]))))
+##       (#.Right value)
+##       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
+##              [where (#.Nat value)]]))))
 
 (def: #export (frac where)
   Syntax
@@ -352,7 +356,7 @@
                                          ## the text's body's column,
                                          ## to ensure they are aligned.
                                          (do @
-                                           [_ (p.exactly offset (l.this " "))]
+                                           [_ (p.exactly offset (l.this ..white-space))]
                                            (recur text-read
                                                   (update@ #.column (n/+ offset) where)
                                                   #0))
@@ -420,18 +424,15 @@
                           (wrap [(update@ #.column inc where')
                                  #.Nil])))))))))
 
-## Form and tuple syntax is mostly the same, differing only in the
-## delimiters involved.
-## They may have an arbitrary number of arbitrary Code nodes as elements.
-(do-template [   ]
-  [(def: ( ast where)
-     (-> Syntax Syntax)
-     (<| (parser/map (product.both id (|>>  [where])))
-         (composite   ast where)))]
-
-  [form  #.Form  ..open-form  ..close-form]
-  [tuple #.Tuple ..open-tuple ..close-tuple]
-  )
+## (do-template [   ]
+##   [(def: ( ast where)
+##      (-> Syntax Syntax)
+##      (<| (parser/map (product.both id (|>>  [where])))
+##          (composite   ast where)))]
+
+##   [form  #.Form  ..open-form  ..close-form]
+##   [tuple #.Tuple ..open-tuple ..close-tuple]
+##   )
 
 ## Records are almost (syntactically) the same as forms and tuples,
 ## with the exception that their elements must come in pairs (as in
@@ -460,7 +461,7 @@
 ## mark], and the short [after the mark]).
 ## There are also some extra rules regarding name syntax,
 ## encoded on the parser.
-(def: name-separator Text ".")
+(def: name-separator ".")
 
 ## A Lux name is a pair of chunks of text, where the first-part
 ## refers to the module that gives context to the name, and the
@@ -550,21 +551,21 @@
   [identifier (|>)                       #.Identifier length]
   )
 
-(do-template [ ]
-  [(def: 
-     (Lexer Bit)
-     (parser/map (function.constant ) (l.this (%b ))))]
+## (do-template [ ]
+##   [(def: 
+##      (Lexer Bit)
+##      (parser/map (function.constant ) (l.this (%b ))))]
 
-  [false #0]
-  [true  #1]
-  )
+##   [false #0]
+##   [true  #1]
+##   )
 
-(def: #export (bit where)
-  Syntax
-  (do p.Monad
-    [value (p.either ..false ..true)]
-    (wrap [(update@ #.column (n/+ 2) where)
-           [where (#.Bit value)]])))
+## (def: #export (bit where)
+##   Syntax
+##   (do p.Monad
+##     [value (p.either ..false ..true)]
+##     (wrap [(update@ #.column (n/+ 2) where)
+##            [where (#.Bit value)]])))
 
 (exception: #export (end-of-file {module Text})
   (ex.report ["Module" (%t module)]))
@@ -580,10 +581,10 @@
     (do p.Monad
       [where (left-padding^ where)]
       ($_ p.either
-          (<| (..timed "bit")
-              (..bit where))
-          (<| (..timed "nat")
-              (..nat where))
+          ## (<| (..timed "bit")
+          ##     (..bit where))
+          ## (<| (..timed "nat")
+          ##     (..nat where))
           (<| (..timed "frac")
               (..frac where))
           (<| (..timed "rev")
@@ -592,14 +593,14 @@
               (..int where))
           (<| (..timed "text")
               (..text where))
-          (<| (..timed "identifier")
-              (..identifier current-module aliases where))
+          ## (<| (..timed "identifier")
+          ##     (..identifier current-module aliases where))
           (<| (..timed "tag")
               (..tag current-module aliases where))
-          (<| (..timed "form")
-              (..form ast' where))
-          (<| (..timed "tuple")
-              (..tuple ast' where))
+          ## (<| (..timed "form")
+          ##     (..form ast' where))
+          ## (<| (..timed "tuple")
+          ##     (..tuple ast' where))
           (<| (..timed "record")
               (..record ast' where))
           (do @
@@ -609,11 +610,216 @@
               (p.fail (ex.construct unrecognized-input where))))
           ))))
 
-(def: #export (read current-module aliases [where offset source-code])
-  (-> Text Aliases Source (e.Error [Source Code]))
-  (case (p.run [offset source-code] (ast current-module aliases where))
-    (#e.Error error)
-    (#e.Error error)
+(type: Simple
+  (-> Source (Error [Source Code])))
+
+(type: Reader
+  (-> Text Aliases Simple))
+
+(do-template [ ]
+  [(template: ( value)
+     ( value 1))]
+
+  [inc! "lux i64 +"]
+  [dec! "lux i64 -"]
+  )
+
+(do-template [  ]
+  [(def: ( read-code source)
+     (-> Simple Simple)
+     (loop [source source
+            stack (: (List Code) #.Nil)]
+       (case (read-code source)
+         (#error.Success [source' top])
+         (recur source' (#.Cons top stack))
+         
+         (#error.Error error)
+         (let [[where offset source-code] source]
+           (case ("lux text char" source-code offset)
+             (#.Some char)
+             (`` (case char
+                   (^ (char (~~ (static ))))
+                   (#error.Success [[(update@ #.column inc where)
+                                     (inc! offset)
+                                     source-code]
+                                    [where ( (list.reverse stack))]])
+
+                   _
+                   (ex.throw unrecognized-input where)))
+             
+             _
+             (#error.Error error))))))]
+
+  ## Form and tuple syntax is mostly the same, differing only in the
+  ## delimiters involved.
+  ## They may have an arbitrary number of arbitrary Code nodes as elements.
+  [read-form  ..close-form  #.Form]
+  [read-tuple ..close-tuple #.Tuple]
+  )
 
-    (#e.Success [[offset' remaining] [where' output]])
-    (#e.Success [[where' offset' remaining] output])))
+(template: (clip! from to text)
+  ## TODO: Optimize away "maybe.assume"
+  (maybe.assume ("lux text clip" text from to)))
+
+(def: (read-text [where offset source-code])
+  Simple
+  (case ("lux text index" source-code (static ..text-delimiter) offset)
+    (#.Some end)
+    (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end offset)) where)
+                      (inc! end)
+                      source-code]
+                     [where
+                      (#.Text (clip! offset end source-code))]])
+    
+    _
+    (ex.throw unrecognized-input where)))
+
+(def: digit-bottom Nat (dec! (char "0")))
+(def: digit-top Nat (inc! (char "9")))
+
+(template: (digit? char)
+  (and ("lux int <" (:coerce Int (static ..digit-bottom)) (:coerce Int char))
+       ("lux int <" (:coerce Int char) (:coerce Int (static ..digit-top)))))
+
+(`` (template: (digit?+ char)
+      (or (digit? char)
+          ("lux i64 =" (.char (~~ (static ..digit-separator))) char))))
+
+(`` (template: (name-char? char)
+      (not (or ("lux i64 =" (.char (~~ (static ..white-space))) char)
+               ("lux i64 =" (.char (~~ (static ..new-line))) char)
+
+               ("lux i64 =" (.char (~~ (static ..name-separator))) char)
+
+               ("lux i64 =" (.char (~~ (static ..open-form))) char)
+               ("lux i64 =" (.char (~~ (static ..close-form))) char)
+
+               ("lux i64 =" (.char (~~ (static ..open-tuple))) char)
+               ("lux i64 =" (.char (~~ (static ..close-tuple))) char)
+
+               ("lux i64 =" (.char (~~ (static ..open-record))) char)
+               ("lux i64 =" (.char (~~ (static ..close-record))) char)
+
+               ("lux i64 =" (.char (~~ (static ..text-delimiter))) char)
+               ("lux i64 =" (.char (~~ (static ..sigil))) char)))))
+
+(template: (name-char?+ char)
+  (or (name-char? char)
+      (digit? char)))
+
+(with-expansions [ (case (:: number.Codec decode (clip! start end source-code))
+                             (#error.Success output)
+                             (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end start)) where)
+                                               end
+                                               source-code]
+                                              [where (#.Nat output)]])
+
+                             (#error.Error error)
+                             (#error.Error error))]
+  (def: (read-nat start [where offset source-code])
+    (-> Offset Simple)
+    (loop [end offset]
+      (case ("lux text char" source-code end)
+        (#.Some char)
+        (if (digit?+ char)
+          (recur (inc! end))
+          )
+        
+        _
+        ))))
+
+(with-expansions [ (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end start)) where)
+                                             end
+                                             source-code]
+                                            [where (#.Identifier ["" (clip! start end source-code)])]])]
+  (def: (read-name start [where offset source-code])
+    (-> Offset Simple)
+    (loop [end offset]
+      (case ("lux text char" source-code end)
+        (#.Some char)
+        (cond (name-char?+ char)
+              (recur (inc! end))
+
+              ## else
+              )
+        
+        _
+        ))))
+
+(template: (leap-bit! value)
+  ("lux i64 +" value 2))
+
+(with-expansions [ (as-is [where (inc! offset) source-code])]
+  (def: (read-code current-module aliases source)
+    Reader
+    (let [read-code' (read-code current-module aliases)]
+      (loop [[where offset source-code] source]
+        (case ("lux text char" source-code offset)
+          (#.Some char)
+          (`` (case char
+                (^template [ ]
+                  (^ (char ))
+                  (recur [(update@  inc where)
+                          (inc! offset)
+                          source-code]))
+                ([(~~ (static ..white-space))     #.column]
+                 [(~~ (static ..carriage-return)) #.column])
+
+                (^ (char (~~ (static ..new-line))))
+                (let [[where::file where::line where::column] where]
+                  (recur [[where::file (inc! where::line) 0]
+                          (inc! offset)
+                          source-code]))
+                
+                (^ (char (~~ (static ..open-form))))
+                (read-form read-code' )
+
+                (^ (char (~~ (static ..open-tuple))))
+                (read-tuple read-code' )
+
+                (^ (char (~~ (static ..text-delimiter))))
+                (read-text )
+
+                (^ (char (~~ (static ..sigil))))
+                (case ("lux text char" source-code (inc! offset))
+                  (#.Some next)
+                  (case next
+                    (^template [ ]
+                      (^ (char ))
+                      (#error.Success [[(update@ #.column (|>> leap-bit!) where)
+                                        (leap-bit! offset)
+                                        source-code]
+                                       [where (#.Bit )]]))
+                    (["0" #0]
+                     ["1" #1])
+
+                    _
+                    (ex.throw unrecognized-input where))
+                  
+                  _
+                  (ex.throw end-of-file current-module))
+
+                _
+                (cond (digit? char)
+                      (read-nat offset )
+
+                      (name-char? char)
+                      (read-name offset )
+                      
+                      ## else
+                      (ex.throw unrecognized-input where))))
+          
+          _
+          (ex.throw end-of-file current-module))))))
+
+## [where offset source-code]
+(def: #export read Reader read-code)
+
+## (def: #export (read current-module aliases source)
+##   (-> Text Aliases Source (Error [Source Code]))
+##   (case (p.run [offset source-code] (ast current-module aliases where))
+##     (#error.Error error)
+##     (#error.Error error)
+
+##     (#error.Success [[offset' remaining] [where' output]])
+##     (#error.Success [[where' offset' remaining] output])))
diff --git a/stdlib/source/lux/data/text/lexer.lux b/stdlib/source/lux/data/text/lexer.lux
index e6186aea8..21aba8360 100644
--- a/stdlib/source/lux/data/text/lexer.lux
+++ b/stdlib/source/lux/data/text/lexer.lux
@@ -13,7 +13,7 @@
     ["." code]]]
   ["." // ("text/." Monoid)])
 
-(type: Offset Nat)
+(type: #export Offset Nat)
 
 (def: start-offset Offset 0)
 
-- 
cgit v1.2.3


From f74614ad4173cc7df1dd22944fddebf5a03bab27 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Tue, 21 Aug 2018 22:48:17 -0400
Subject: - Added single-line comment parsing. - Added tag parsing. - Added
 tracking.

---
 stdlib/source/lux.lux                              |   2 +-
 .../source/lux/compiler/default/phase/analysis.lux |  20 +-
 stdlib/source/lux/compiler/default/syntax.lux      | 393 ++++++++++++---------
 3 files changed, 236 insertions(+), 179 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index d64b83bd3..1114b069c 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -5945,7 +5945,7 @@
                        (^ (list (~+ (list/map (|>> [""] identifier$) args))))
                        (#.Right [(~ g!compiler)
                                  (list (~+ (list/map (function (_ template)
-                                                       (` (` (~ (replace-syntax rep-env template)))))
+                                                       (` (`' (~ (replace-syntax rep-env template)))))
                                                      input-templates)))])
                        
                        (~ g!_)
diff --git a/stdlib/source/lux/compiler/default/phase/analysis.lux b/stdlib/source/lux/compiler/default/phase/analysis.lux
index 8ef8324ae..e26cd3516 100644
--- a/stdlib/source/lux/compiler/default/phase/analysis.lux
+++ b/stdlib/source/lux/compiler/default/phase/analysis.lux
@@ -81,20 +81,20 @@
   [(template: #export ( content)
      ( content))]
 
-  [control/case #Case]
+  [control/case #..Case]
   )
 
 (do-template [  ]
   [(def: #export 
      (->  Analysis)
-     (|>>  #Primitive))]
-
-  [bit  Bit  #Bit]
-  [nat  Nat  #Nat]
-  [int  Int  #Int]
-  [rev  Rev  #Rev]
-  [frac Frac #Frac]
-  [text Text #Text]
+     (|>>  #..Primitive))]
+
+  [bit  Bit  #..Bit]
+  [nat  Nat  #..Nat]
+  [int  Int  #..Int]
+  [rev  Rev  #..Rev]
+  [frac Frac #..Frac]
+  [text Text #..Text]
   )
 
 (type: #export Arity Nat)
@@ -142,7 +142,7 @@
 
 (do-template [ ]
   [(template: #export ( content)
-     (.<| #Complex
+     (.<| #..Complex
           
           content))]
 
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 4d778136f..1ae6a8620 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -463,93 +463,93 @@
 ## encoded on the parser.
 (def: name-separator ".")
 
-## A Lux name is a pair of chunks of text, where the first-part
-## refers to the module that gives context to the name, and the
-## second part corresponds to the short of the name itself.
-## The module part may be absent (by being the empty text ""), but the
-## name part must always be present.
-## The rules for which characters you may use are specified in terms
-## of which characters you must avoid (to keep things as open-ended as
-## possible).
-## In particular, no white-space can be used, and neither can other
-## characters which are already used by Lux as delimiters for other
-## Code nodes (thereby reducing ambiguity while parsing).
-## Additionally, the first character in an name's part cannot be
-## a digit, to avoid confusion with regards to numbers.
-(def: name-part^
-  (Lexer Text)
-  (let [delimiters (format ..open-form ..close-form
-                           ..open-tuple ..close-tuple
-                           ..open-record ..close-record
-                           ..sigil
-                           ..text-delimiter
-                           ..name-separator)
-        space (format ..white-space ..new-line)
-        head (l.none-of! (format ..digits delimiters space))
-        tail (l.some! (l.none-of! (format delimiters space)))]
-    (l.slice (l.and! head tail))))
-
-(def: current-module-mark Text (format ..name-separator ..name-separator))
-
-(def: (name^ current-module aliases)
-  (-> Text Aliases (Lexer [Name Nat]))
-  ($_ p.either
-      ## When an name starts with 2 marks, its module is
-      ## taken to be the current-module being compiled at the moment.
-      ## This can be useful when mentioning names and tags
-      ## inside quoted/templated code in macros.
-      (do p.Monad
-        [_ (l.this current-module-mark)
-         def-name name-part^]
-        (wrap [[current-module def-name]
-               ("lux i64 +" 2 (text.size def-name))]))
-      ## If the name is prefixed by the mark, but no module
-      ## part, the module is assumed to be "lux" (otherwise known as
-      ## the 'prelude').
-      ## This makes it easy to refer to definitions in that module,
-      ## since it is the most fundamental module in the entire
-      ## standard library.
-      (do p.Monad
-        [_ (l.this name-separator)
-         def-name name-part^]
-        (wrap [["lux" def-name]
-               ("lux i64 +" 1 (text.size def-name))]))
-      ## Not all names must be specified with a module part.
-      ## If that part is not provided, the name will be created
-      ## with the empty "" text as the module.
-      ## During program analysis, such names tend to be treated
-      ## as if their context is the current-module, but this only
-      ## applies to names for tags and module definitions.
-      ## Function arguments and local-variables may not be referred-to
-      ## using names with module parts, so being able to specify
-      ## names with empty modules helps with those use-cases.
-      (do p.Monad
-        [first-part name-part^]
-        (p.either (do @
-                    [_ (l.this name-separator)
-                     second-part name-part^]
-                    (wrap [[(|> aliases (dictionary.get first-part) (maybe.default first-part))
-                            second-part]
-                           ($_ "lux i64 +"
-                               (text.size first-part)
-                               1
-                               (text.size second-part))]))
-                  (wrap [["" first-part]
-                         (text.size first-part)])))))
-
-(do-template [ 
  ]
-  [(def: #export ( current-module aliases)
-     (-> Text Aliases Syntax)
-     (function (_ where)
-       (do p.Monad
-         [[value length] (<| 
-                             (name^ current-module aliases))]
-         (wrap [(update@ #.column (n/+ ) where)
-                [where ( value)]]))))]
-
-  [tag        (p.after (l.this ..sigil)) #.Tag        ("lux i64 +" 1 length)]
-  [identifier (|>)                       #.Identifier length]
-  )
+## ## A Lux name is a pair of chunks of text, where the first-part
+## ## refers to the module that gives context to the name, and the
+## ## second part corresponds to the short of the name itself.
+## ## The module part may be absent (by being the empty text ""), but the
+## ## name part must always be present.
+## ## The rules for which characters you may use are specified in terms
+## ## of which characters you must avoid (to keep things as open-ended as
+## ## possible).
+## ## In particular, no white-space can be used, and neither can other
+## ## characters which are already used by Lux as delimiters for other
+## ## Code nodes (thereby reducing ambiguity while parsing).
+## ## Additionally, the first character in an name's part cannot be
+## ## a digit, to avoid confusion with regards to numbers.
+## (def: name-part^
+##   (Lexer Text)
+##   (let [delimiters (format ..open-form ..close-form
+##                            ..open-tuple ..close-tuple
+##                            ..open-record ..close-record
+##                            ..sigil
+##                            ..text-delimiter
+##                            ..name-separator)
+##         space (format ..white-space ..new-line)
+##         head (l.none-of! (format ..digits delimiters space))
+##         tail (l.some! (l.none-of! (format delimiters space)))]
+##     (l.slice (l.and! head tail))))
+
+## (def: current-module-mark Text (format ..name-separator ..name-separator))
+
+## (def: (name^ current-module aliases)
+##   (-> Text Aliases (Lexer [Name Nat]))
+##   ($_ p.either
+##       ## When an name starts with 2 marks, its module is
+##       ## taken to be the current-module being compiled at the moment.
+##       ## This can be useful when mentioning names and tags
+##       ## inside quoted/templated code in macros.
+##       (do p.Monad
+##         [_ (l.this current-module-mark)
+##          def-name name-part^]
+##         (wrap [[current-module def-name]
+##                ("lux i64 +" 2 (text.size def-name))]))
+##       ## If the name is prefixed by the mark, but no module
+##       ## part, the module is assumed to be "lux" (otherwise known as
+##       ## the 'prelude').
+##       ## This makes it easy to refer to definitions in that module,
+##       ## since it is the most fundamental module in the entire
+##       ## standard library.
+##       (do p.Monad
+##         [_ (l.this name-separator)
+##          def-name name-part^]
+##         (wrap [["lux" def-name]
+##                ("lux i64 +" 1 (text.size def-name))]))
+##       ## Not all names must be specified with a module part.
+##       ## If that part is not provided, the name will be created
+##       ## with the empty "" text as the module.
+##       ## During program analysis, such names tend to be treated
+##       ## as if their context is the current-module, but this only
+##       ## applies to names for tags and module definitions.
+##       ## Function arguments and local-variables may not be referred-to
+##       ## using names with module parts, so being able to specify
+##       ## names with empty modules helps with those use-cases.
+##       (do p.Monad
+##         [first-part name-part^]
+##         (p.either (do @
+##                     [_ (l.this name-separator)
+##                      second-part name-part^]
+##                     (wrap [[(|> aliases (dictionary.get first-part) (maybe.default first-part))
+##                             second-part]
+##                            ($_ "lux i64 +"
+##                                (text.size first-part)
+##                                1
+##                                (text.size second-part))]))
+##                   (wrap [["" first-part]
+##                          (text.size first-part)])))))
+
+## (do-template [ 
  ]
+##   [(def: #export ( current-module aliases)
+##      (-> Text Aliases Syntax)
+##      (function (_ where)
+##        (do p.Monad
+##          [[value length] (<| 
+##                              (name^ current-module aliases))]
+##          (wrap [(update@ #.column (n/+ ) where)
+##                 [where ( value)]]))))]
+
+##   [tag        (p.after (l.this ..sigil)) #.Tag        ("lux i64 +" 1 length)]
+##   [identifier (|>)                       #.Identifier length]
+##   )
 
 ## (do-template [ ]
 ##   [(def: 
@@ -595,8 +595,8 @@
               (..text where))
           ## (<| (..timed "identifier")
           ##     (..identifier current-module aliases where))
-          (<| (..timed "tag")
-              (..tag current-module aliases where))
+          ## (<| (..timed "tag")
+          ##     (..tag current-module aliases where))
           ## (<| (..timed "form")
           ##     (..form ast' where))
           ## (<| (..timed "tuple")
@@ -610,28 +610,36 @@
               (p.fail (ex.construct unrecognized-input where))))
           ))))
 
-(type: Simple
-  (-> Source (Error [Source Code])))
+(type: Tracker
+  {#new-line Offset})
 
-(type: Reader
-  (-> Text Aliases Simple))
+(def: fresh-tracker
+  Tracker
+  {#new-line 0})
+
+(type: (Simple a)
+  (-> Tracker Source (Error [Tracker Source a])))
+
+(type: (Reader a)
+  (-> Text Aliases (Simple a)))
 
 (do-template [ ]
   [(template: ( value)
      ( value 1))]
 
-  [inc! "lux i64 +"]
-  [dec! "lux i64 -"]
+  [!inc "lux i64 +"]
+  [!dec "lux i64 -"]
   )
 
 (do-template [  ]
-  [(def: ( read-code source)
-     (-> Simple Simple)
-     (loop [source source
+  [(def: ( read-code tracker source)
+     (-> (Simple Code) (Simple Code))
+     (loop [tracker tracker
+            source source
             stack (: (List Code) #.Nil)]
-       (case (read-code source)
-         (#error.Success [source' top])
-         (recur source' (#.Cons top stack))
+       (case (read-code tracker source)
+         (#error.Success [tracker' source' top])
+         (recur tracker' source' (#.Cons top stack))
          
          (#error.Error error)
          (let [[where offset source-code] source]
@@ -639,8 +647,9 @@
              (#.Some char)
              (`` (case char
                    (^ (char (~~ (static ))))
-                   (#error.Success [[(update@ #.column inc where)
-                                     (inc! offset)
+                   (#error.Success [tracker
+                                    [(update@ #.column inc where)
+                                     (!inc offset)
                                      source-code]
                                     [where ( (list.reverse stack))]])
 
@@ -657,35 +666,36 @@
   [read-tuple ..close-tuple #.Tuple]
   )
 
-(template: (clip! from to text)
+(template: (!clip from to text)
   ## TODO: Optimize away "maybe.assume"
   (maybe.assume ("lux text clip" text from to)))
 
-(def: (read-text [where offset source-code])
-  Simple
+(def: (read-text tracker [where offset source-code])
+  (Simple Code)
   (case ("lux text index" source-code (static ..text-delimiter) offset)
     (#.Some end)
-    (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end offset)) where)
-                      (inc! end)
+    (#error.Success [tracker
+                     [(update@ #.column (n/+ ("lux i64 -" end offset)) where)
+                      (!inc end)
                       source-code]
                      [where
-                      (#.Text (clip! offset end source-code))]])
+                      (#.Text (!clip offset end source-code))]])
     
     _
     (ex.throw unrecognized-input where)))
 
-(def: digit-bottom Nat (dec! (char "0")))
-(def: digit-top Nat (inc! (char "9")))
+(def: digit-bottom Nat (!dec (char "0")))
+(def: digit-top Nat (!inc (char "9")))
 
-(template: (digit? char)
+(template: (!digit? char)
   (and ("lux int <" (:coerce Int (static ..digit-bottom)) (:coerce Int char))
        ("lux int <" (:coerce Int char) (:coerce Int (static ..digit-top)))))
 
-(`` (template: (digit?+ char)
-      (or (digit? char)
+(`` (template: (!digit?+ char)
+      (or (!digit? char)
           ("lux i64 =" (.char (~~ (static ..digit-separator))) char))))
 
-(`` (template: (name-char? char)
+(`` (template: (!strict-name-char? char)
       (not (or ("lux i64 =" (.char (~~ (static ..white-space))) char)
                ("lux i64 =" (.char (~~ (static ..new-line))) char)
 
@@ -703,42 +713,48 @@
                ("lux i64 =" (.char (~~ (static ..text-delimiter))) char)
                ("lux i64 =" (.char (~~ (static ..sigil))) char)))))
 
-(template: (name-char?+ char)
-  (or (name-char? char)
-      (digit? char)))
+(template: (!name-char?|head char)
+  (and (!strict-name-char? char)
+       (not (!digit? char))))
 
-(with-expansions [ (case (:: number.Codec decode (clip! start end source-code))
+(template: (!name-char? char)
+  (or (!strict-name-char? char)
+      (!digit? char)))
+
+(with-expansions [ (case (:: number.Codec decode (!clip start end source-code))
                              (#error.Success output)
-                             (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end start)) where)
+                             (#error.Success [tracker
+                                              [(update@ #.column (n/+ ("lux i64 -" end start)) where)
                                                end
                                                source-code]
                                               [where (#.Nat output)]])
 
                              (#error.Error error)
                              (#error.Error error))]
-  (def: (read-nat start [where offset source-code])
-    (-> Offset Simple)
+  (def: (read-nat start tracker [where offset source-code])
+    (-> Offset (Simple Code))
     (loop [end offset]
       (case ("lux text char" source-code end)
         (#.Some char)
-        (if (digit?+ char)
-          (recur (inc! end))
+        (if (!digit?+ char)
+          (recur (!inc end))
           )
         
         _
         ))))
 
-(with-expansions [ (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end start)) where)
+(with-expansions [ (#error.Success [tracker
+                                            [(update@ #.column (n/+ ("lux i64 -" end start)) where)
                                              end
                                              source-code]
-                                            [where (#.Identifier ["" (clip! start end source-code)])]])]
-  (def: (read-name start [where offset source-code])
-    (-> Offset Simple)
+                                            ["" (!clip start end source-code)]])]
+  (def: (read-name start tracker [where offset source-code])
+    (-> Offset (Simple Name))
     (loop [end offset]
       (case ("lux text char" source-code end)
         (#.Some char)
-        (cond (name-char?+ char)
-              (recur (inc! end))
+        (cond (!name-char? char)
+              (recur (!inc end))
 
               ## else
               )
@@ -746,65 +762,99 @@
         _
         ))))
 
-(template: (leap-bit! value)
+(template: (!leap-bit value)
   ("lux i64 +" value 2))
 
-(with-expansions [ (as-is [where (inc! offset) source-code])]
-  (def: (read-code current-module aliases source)
-    Reader
+(template: (!new-line where)
+  (let [[where::file where::line where::column] where]
+    [where::file (!inc where::line) 0]))
+
+(template: (!read-name @offset @tracker @source @where @tag)
+  (case (..read-name @offset @tracker @source)
+    (#error.Success [tracker' source' name])
+    (#error.Success [tracker' source' [@where (@tag name)]])
+    
+    (#error.Error error)
+    (#error.Error error)))
+
+(with-expansions [ (as-is [where (!inc offset) source-code])
+                   (as-is (recur tracker
+                                               [where ("lux text size" source-code) source-code]))]
+  (def: (read-code current-module aliases tracker source)
+    (Reader Code)
     (let [read-code' (read-code current-module aliases)]
-      (loop [[where offset source-code] source]
+      (loop [tracker tracker
+             [where offset source-code] source]
         (case ("lux text char" source-code offset)
-          (#.Some char)
-          (`` (case char
+          (#.Some current)
+          (`` (case current
+                ## White-space
                 (^template [ ]
                   (^ (char ))
-                  (recur [(update@  inc where)
-                          (inc! offset)
+                  (recur tracker
+                         [(update@  inc where)
+                          (!inc offset)
                           source-code]))
                 ([(~~ (static ..white-space))     #.column]
                  [(~~ (static ..carriage-return)) #.column])
 
                 (^ (char (~~ (static ..new-line))))
-                (let [[where::file where::line where::column] where]
-                  (recur [[where::file (inc! where::line) 0]
-                          (inc! offset)
-                          source-code]))
-                
+                (recur tracker [(!new-line where) (!inc offset) source-code])
+
+                ## Form
                 (^ (char (~~ (static ..open-form))))
-                (read-form read-code' )
+                (read-form read-code' tracker )
 
+                ## Tuple
                 (^ (char (~~ (static ..open-tuple))))
-                (read-tuple read-code' )
+                (read-tuple read-code' tracker )
 
+                ## Text
                 (^ (char (~~ (static ..text-delimiter))))
-                (read-text )
+                (read-text tracker )
 
+                ## Special code
                 (^ (char (~~ (static ..sigil))))
-                (case ("lux text char" source-code (inc! offset))
-                  (#.Some next)
-                  (case next
-                    (^template [ ]
-                      (^ (char ))
-                      (#error.Success [[(update@ #.column (|>> leap-bit!) where)
-                                        (leap-bit! offset)
-                                        source-code]
-                                       [where (#.Bit )]]))
-                    (["0" #0]
-                     ["1" #1])
-
+                (let [offset' (!inc offset)]
+                  (case ("lux text char" source-code offset')
+                    (#.Some next)
+                    (case next
+                      (^template [ ]
+                        (^ (char ))
+                        (#error.Success [tracker
+                                         [(update@ #.column (|>> !leap-bit) where)
+                                          (!leap-bit offset)
+                                          source-code]
+                                         [where (#.Bit )]]))
+                      (["0" #0]
+                       ["1" #1])
+
+                      ## Single-line comment
+                      (^ (char (~~ (static ..sigil))))
+                      (case ("lux text index" source-code (static ..new-line) offset')
+                        (#.Some end)
+                        (recur tracker [(!new-line where) (!inc end) source-code])
+                        
+                        _
+                        )
+
+                      _
+                      (cond (!name-char?|head next) ## Tag
+                            (!read-name offset tracker  where #.Tag)
+
+                            ## else
+                            (ex.throw unrecognized-input where)))
+                    
                     _
-                    (ex.throw unrecognized-input where))
-                  
-                  _
-                  (ex.throw end-of-file current-module))
+                    (ex.throw end-of-file current-module)))
 
                 _
-                (cond (digit? char)
-                      (read-nat offset )
+                (cond (!digit? current) ## Natural number
+                      (read-nat offset tracker )
 
-                      (name-char? char)
-                      (read-name offset )
+                      ## Identifier
+                      (!name-char?|head current)
+                      (!read-name offset tracker  where #.Identifier)
                       
                       ## else
                       (ex.throw unrecognized-input where))))
@@ -813,7 +863,14 @@
           (ex.throw end-of-file current-module))))))
 
 ## [where offset source-code]
-(def: #export read Reader read-code)
+(def: #export (read current-module aliases source)
+  (-> Text Aliases Source (Error [Source Code]))
+  (case (read-code current-module aliases fresh-tracker source)
+    (#error.Error error)
+    (#error.Error error)
+
+    (#error.Success [tracker' source' output])
+    (#error.Success [source' output])))
 
 ## (def: #export (read current-module aliases source)
 ##   (-> Text Aliases Source (Error [Source Code]))
-- 
cgit v1.2.3


From d4f1c93801003d68cb15e792f81784be1d488020 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 00:22:23 -0400
Subject: Full parsing of names (for both identifiers and tags).

---
 stdlib/source/lux/compiler/default.lux        |   4 +-
 stdlib/source/lux/compiler/default/syntax.lux | 261 ++++++++++++++++----------
 stdlib/source/lux/interpreter.lux             |   2 +-
 3 files changed, 169 insertions(+), 98 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default.lux b/stdlib/source/lux/compiler/default.lux
index 16c1a2b0e..e9678c87c 100644
--- a/stdlib/source/lux/compiler/default.lux
+++ b/stdlib/source/lux/compiler/default.lux
@@ -36,8 +36,6 @@
   ##       [cache/io])
   )
 
-(def: #export prelude Text "lux")
-
 (def: (read current-module aliases)
   (-> Text Aliases (analysis.Operation Code))
   (function (_ [bundle compiler])
@@ -186,7 +184,7 @@
       (->  Configuration  (! Any)))
     (do (:: (get@ #file-system platform) &monad)
       [compiler (initialize platform configuration translation-bundle)
-       _ (compile-module platform (set@ #cli.module ..prelude configuration) compiler)
+       _ (compile-module platform (set@ #cli.module syntax.prelude configuration) compiler)
        _ (compile-module platform configuration compiler)
        ## _ (cache/io.clean target ...)
        ]
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 1ae6a8620..6a52687ec 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -82,6 +82,8 @@
 (type: #export Aliases (Dictionary Text Text))
 (def: #export no-aliases Aliases (dictionary.new text.Hash))
 
+(def: #export prelude Text "lux")
+
 (def: digits "0123456789")
 (def: digits+ (format "_" ..digits))
 
@@ -623,12 +625,13 @@
 (type: (Reader a)
   (-> Text Aliases (Simple a)))
 
-(do-template [ ]
+(do-template [  ]
   [(template: ( value)
-     ( value 1))]
+     ( value ))]
 
-  [!inc "lux i64 +"]
-  [!dec "lux i64 -"]
+  [!inc   "lux i64 +" 1]
+  [!inc/2 "lux i64 +" 2]
+  [!dec   "lux i64 -" 1]
   )
 
 (do-template [  ]
@@ -743,13 +746,12 @@
         _
         ))))
 
-(with-expansions [ (#error.Success [tracker
-                                            [(update@ #.column (n/+ ("lux i64 -" end start)) where)
+(with-expansions [ (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end start)) where)
                                              end
                                              source-code]
-                                            ["" (!clip start end source-code)]])]
-  (def: (read-name start tracker [where offset source-code])
-    (-> Offset (Simple Name))
+                                            (!clip start end source-code)])]
+  (def: (read-name-part start [where offset source-code])
+    (-> Offset Source (Error [Source Text]))
     (loop [end offset]
       (case ("lux text char" source-code end)
         (#.Some char)
@@ -769,98 +771,167 @@
   (let [[where::file where::line where::column] where]
     [where::file (!inc where::line) 0]))
 
-(template: (!read-name @offset @tracker @source @where @tag)
-  (case (..read-name @offset @tracker @source)
-    (#error.Success [tracker' source' name])
-    (#error.Success [tracker' source' [@where (@tag name)]])
-    
-    (#error.Error error)
-    (#error.Error error)))
+(with-expansions [ (ex.throw end-of-file current-module)
+                   (ex.throw unrecognized-input where)
+                   (as-is [where ("lux i64 +" offset 1) source-code])
+                   (as-is [where ("lux i64 +" offset 2) source-code])
+                   (as-is [where ("lux i64 +" offset 3) source-code])]
+
+  (template: (!with-char @source-code @offset @char @body)
+    (case ("lux text char" @source-code @offset)
+      (#.Some @char)
+      @body
+      
+      _
+      ))
+
+  (template: (!read-half-name @offset//pre @offset//post @char @module)
+    (let [@offset//post (!inc @offset//pre)]
+      (cond (!name-char?|head @char)
+            (case (..read-name-part @offset//post [where @offset//post source-code])
+              (#error.Success [source' name])
+              (#error.Success [source' [@module name]])
+              
+              (#error.Error error)
+              (#error.Error error))
+
+            ## else
+            )))
+
+  (`` (def: (read-short-name current-module [where offset/0 source-code])
+        (-> Text Source (Error [Source Name]))
+        (<| (!with-char source-code offset/0 char/0)
+            (case char/0
+              (^ (char (~~ (static ..name-separator))))
+              (let [offset/1 (!inc offset/0)]
+                (<| (!with-char source-code offset/1 char/1)
+                    (!read-half-name offset/1 offset/2 char/1 current-module)))
+
+              _
+              (!read-half-name offset/0 offset/1 char/0 ..prelude)))))
+
+  (template: (!read-short-name @current-module @tracker @source @where @tag)
+    (case (..read-short-name @current-module @source)
+      (#error.Success [source' name])
+      (#error.Success [@tracker source' [@where (@tag name)]])
+      
+      (#error.Error error)
+      (#error.Error error)))
+
+  (with-expansions [ (as-is (#error.Success [source' ["" simple]]))]
+    (`` (def: (read-full-name start source)
+          (-> Offset Source (Error [Source Name]))
+          (case (..read-name-part start source)
+            (#error.Success [source' simple])
+            (let [[where' offset' source-code'] source']
+              (case ("lux text char" source-code' offset')
+                (#.Some char/separator)
+                (case char/separator
+                  (^ (char (~~ (static ..name-separator))))
+                  (let [offset'' (!inc offset')]
+                    (case (..read-name-part offset'' [where' offset'' source-code'])
+                      (#error.Success [source'' complex])
+                      (#error.Success [source'' [simple complex]])
+                      
+                      (#error.Error error)
+                      (#error.Error error)))
 
-(with-expansions [ (as-is [where (!inc offset) source-code])
-                   (as-is (recur tracker
-                                               [where ("lux text size" source-code) source-code]))]
+                  _
+                  )
+                
+                _
+                ))
+            
+            (#error.Error error)
+            (#error.Error error)))))
+
+  (template: (!read-full-name @offset @tracker @source @where @tag)
+    (case (..read-full-name @offset @source)
+      (#error.Success [source' full-name])
+      (#error.Success [@tracker source' [@where (@tag full-name)]])
+      
+      (#error.Error error)
+      (#error.Error error)))
+  
   (def: (read-code current-module aliases tracker source)
     (Reader Code)
     (let [read-code' (read-code current-module aliases)]
       (loop [tracker tracker
              [where offset source-code] source]
-        (case ("lux text char" source-code offset)
-          (#.Some current)
-          (`` (case current
-                ## White-space
-                (^template [ ]
-                  (^ (char ))
-                  (recur tracker
-                         [(update@  inc where)
-                          (!inc offset)
-                          source-code]))
-                ([(~~ (static ..white-space))     #.column]
-                 [(~~ (static ..carriage-return)) #.column])
-
-                (^ (char (~~ (static ..new-line))))
-                (recur tracker [(!new-line where) (!inc offset) source-code])
-
-                ## Form
-                (^ (char (~~ (static ..open-form))))
-                (read-form read-code' tracker )
-
-                ## Tuple
-                (^ (char (~~ (static ..open-tuple))))
-                (read-tuple read-code' tracker )
-
-                ## Text
-                (^ (char (~~ (static ..text-delimiter))))
-                (read-text tracker )
-
-                ## Special code
-                (^ (char (~~ (static ..sigil))))
-                (let [offset' (!inc offset)]
-                  (case ("lux text char" source-code offset')
-                    (#.Some next)
-                    (case next
-                      (^template [ ]
-                        (^ (char ))
-                        (#error.Success [tracker
-                                         [(update@ #.column (|>> !leap-bit) where)
-                                          (!leap-bit offset)
-                                          source-code]
-                                         [where (#.Bit )]]))
-                      (["0" #0]
-                       ["1" #1])
-
-                      ## Single-line comment
-                      (^ (char (~~ (static ..sigil))))
-                      (case ("lux text index" source-code (static ..new-line) offset')
-                        (#.Some end)
-                        (recur tracker [(!new-line where) (!inc end) source-code])
+        (<| (!with-char source-code offset char/0)
+            (`` (case char/0
+                  ## White-space
+                  (^template [ ]
+                    (^ (char ))
+                    (recur tracker
+                           [(update@  inc where)
+                            (!inc offset)
+                            source-code]))
+                  ([(~~ (static ..white-space))     #.column]
+                   [(~~ (static ..carriage-return)) #.column])
+
+                  (^ (char (~~ (static ..new-line))))
+                  (recur tracker [(!new-line where) (!inc offset) source-code])
+
+                  ## Form
+                  (^ (char (~~ (static ..open-form))))
+                  (read-form read-code' tracker )
+
+                  ## Tuple
+                  (^ (char (~~ (static ..open-tuple))))
+                  (read-tuple read-code' tracker )
+
+                  ## Text
+                  (^ (char (~~ (static ..text-delimiter))))
+                  (read-text tracker )
+
+                  ## Special code
+                  (^ (char (~~ (static ..sigil))))
+                  (let [offset' (!inc offset)]
+                    (<| (!with-char source-code offset' char/1)
+                        (case char/1
+                          (^template [ ]
+                            (^ (char ))
+                            (#error.Success [tracker
+                                             [(update@ #.column (|>> !leap-bit) where)
+                                              (!leap-bit offset)
+                                              source-code]
+                                             [where (#.Bit )]]))
+                          (["0" #0]
+                           ["1" #1])
+
+                          ## Single-line comment
+                          (^ (char (~~ (static ..sigil))))
+                          (case ("lux text index" source-code (static ..new-line) offset')
+                            (#.Some end)
+                            (recur tracker [(!new-line where) (!inc end) source-code])
+                            
+                            _
+                            )
+
+                          (^ (char (~~ (static ..name-separator))))
+                          (!read-short-name current-module tracker  where #.Identifier)
+
+                          _
+                          (cond (!name-char?|head char/1) ## Tag
+                                (!read-full-name offset tracker  where #.Tag)
+
+                                ## else
+                                ))))
+
+                  (^ (char (~~ (static ..name-separator))))
+                  (!read-short-name current-module tracker  where #.Identifier)
+
+                  _
+                  (cond (!digit? char/0) ## Natural number
+                        (read-nat offset tracker )
+
+                        ## Identifier
+                        (!name-char?|head char/0)
+                        (!read-full-name offset tracker  where #.Identifier)
                         
-                        _
-                        )
-
-                      _
-                      (cond (!name-char?|head next) ## Tag
-                            (!read-name offset tracker  where #.Tag)
-
-                            ## else
-                            (ex.throw unrecognized-input where)))
-                    
-                    _
-                    (ex.throw end-of-file current-module)))
-
-                _
-                (cond (!digit? current) ## Natural number
-                      (read-nat offset tracker )
-
-                      ## Identifier
-                      (!name-char?|head current)
-                      (!read-name offset tracker  where #.Identifier)
-                      
-                      ## else
-                      (ex.throw unrecognized-input where))))
-          
-          _
-          (ex.throw end-of-file current-module))))))
+                        ## else
+                        ))))))))
 
 ## [where offset source-code]
 (def: #export (read current-module aliases source)
@@ -880,3 +951,5 @@
 
 ##     (#error.Success [[offset' remaining] [where' output]])
 ##     (#error.Success [[where' offset' remaining] output])))
+
+## (yolo)
diff --git a/stdlib/source/lux/interpreter.lux b/stdlib/source/lux/interpreter.lux
index 36cef324d..df475475a 100644
--- a/stdlib/source/lux/interpreter.lux
+++ b/stdlib/source/lux/interpreter.lux
@@ -68,7 +68,7 @@
   (do Monad
     [state (default.initialize platform configuration)
      state (default.compile-module platform
-                                   (set@ #cli.module default.prelude configuration)
+                                   (set@ #cli.module syntax.prelude configuration)
                                    (set@ [#extension.state
                                           #statement.analysis #statement.state
                                           #extension.state
-- 
cgit v1.2.3


From 6c896325238b63b6fc09f774968be6da0b9c89c1 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 17:40:33 -0400
Subject: No more multi-line comments.

---
 stdlib/source/lux/compiler/default/syntax.lux    | 63 +-----------------------
 stdlib/test/test/lux/compiler/default/syntax.lux | 36 ++------------
 2 files changed, 5 insertions(+), 94 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 6a52687ec..3b3b3e411 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -132,7 +132,7 @@
 
 ## Single-line comments can start anywhere, but only go up to the
 ## next new-line.
-(def: (single-line-comment^ where)
+(def: (comment^ where)
   (-> Cursor (Lexer Cursor))
   (do p.Monad
     [_ (l.this ..single-line-comment-marker)
@@ -142,67 +142,6 @@
               (update@ #.line inc)
               (set@ #.column 0)))))
 
-## This is just a helper parser to find text which doesn't run into
-## any special character sequences for multi-line comments.
-(def: multi-line-comment-start^ (l.this (format ..sigil open-form)))
-(def: multi-line-comment-end^ (l.this (format close-form ..sigil)))
-
-(def: multi-line-comment-bound^
-  (Lexer Any)
-  ($_ p.either
-      ..new-line^
-      ..multi-line-comment-start^
-      ..multi-line-comment-end^))
-
-## Multi-line comments are bounded by #( these delimiters, #(and, they may
-## also be nested)# )#.
-## Multi-line comment syntax must be balanced.
-## That is, any nested comment must have matched delimiters.
-## Unbalanced comments ought to be rejected as invalid code.
-(def: (multi-line-comment^ where)
-  (-> Cursor (Lexer Cursor))
-  (do p.Monad
-    [_ ..multi-line-comment-start^]
-    (loop [where (update@ #.column (n/+ 2) where)]
-      ($_ p.either
-          ## These are normal chunks of commented text.
-          (do @
-            [chunk (l.many! (l.not! multi-line-comment-bound^))]
-            (recur (|> where
-                       (update@ #.column (n/+ (get@ #l.distance chunk))))))
-          ## This is a special rule to handle new-lines within
-          ## comments properly.
-          (do @
-            [_ ..new-line^]
-            (recur (|> where
-                       (update@ #.line inc)
-                       (set@ #.column 0))))
-          ## This is the rule for handling nested sub-comments.
-          ## Ultimately, the whole comment is just treated as text
-          ## (the comment must respect the syntax structure, but the
-          ## output produced is just a block of text).
-          ## That is why the sub-comment is covered in delimiters
-          ## and then appended to the rest of the comment text.
-          (do @
-            [sub-where (multi-line-comment^ where)]
-            (recur sub-where))
-          ## Finally, this is the rule for closing the comment.
-          (do @
-            [_ ..multi-line-comment-end^]
-            (wrap (update@ #.column (n/+ 2) where)))
-          ))))
-
-## This is the only parser that should be used directly by other
-## parsers, since all comments must be treated as either being
-## single-line or multi-line.
-## That is, there is no syntactic rule prohibiting one type of comment
-## from being used in any situation (alternatively, forcing one type
-## of comment to be the only usable one).
-(def: (comment^ where)
-  (-> Cursor (Lexer Cursor))
-  (p.either (single-line-comment^ where)
-            (multi-line-comment^ where)))
-
 ## To simplify parsing, I remove any left-padding that a Code token
 ## may have prior to parsing the token itself.
 ## Left-padding is assumed to be either white-space or a comment.
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index a9baa546c..1bcb9dad8 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -114,25 +114,16 @@
 
 (def: comment-text^
   (r.Random Text)
-  (let [char-gen (|> r.nat (r.filter (function (_ value)
-                                       (not (or (text.space? value)
-                                                (n/= (char "#") value)
-                                                (n/= (char "(") value)
-                                                (n/= (char ")") value))))))]
+  (let [char-gen (|> r.nat (r.filter (|>> (n/= (char "\n")) not)))]
     (do r.Monad
       [size (|> r.nat (r/map (n/% 20)))]
       (r.text char-gen size))))
 
 (def: comment^
   (r.Random Text)
-  (r.either (do r.Monad
-              [comment comment-text^]
-              (wrap (format "## " comment "\n")))
-            (r.rec (function (_ nested^)
-                     (do r.Monad
-                       [comment (r.either comment-text^
-                                          nested^)]
-                       (wrap (format "#( " comment " )#")))))))
+  (do r.Monad
+    [comment comment-text^]
+    (wrap (format "## " comment "\n"))))
 
 (context: "Multi-line text & comments."
   (<| (seed 12137892244981970631)
@@ -189,23 +180,4 @@
 
                     (#e.Success [_ parsed])
                     (:: code.Equivalence = parsed sample)))
-            (test "Will reject unbalanced multi-line comments."
-                  (and (case (&.read "" (dict.new text.Hash)
-                                     [default-cursor 0
-                                      (format "#(" "#(" unbalanced-comment ")#"
-                                              (code.to-text sample))])
-                         (#e.Error error)
-                         #1
-
-                         (#e.Success [_ parsed])
-                         #0)
-                       (case (&.read "" (dict.new text.Hash)
-                                     [default-cursor 0
-                                      (format "#(" unbalanced-comment ")#" ")#"
-                                              (code.to-text sample))])
-                         (#e.Error error)
-                         #1
-
-                         (#e.Success [_ parsed])
-                         #0)))
             ))))
-- 
cgit v1.2.3


From b60d60ef6c0c70821991991fe716935e73038832 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 19:42:17 -0400
Subject: No more multi-line text.

---
 stdlib/source/lux.lux                            | 769 +++++++++++------------
 stdlib/source/lux/concurrency/actor.lux          |   4 +-
 stdlib/source/lux/concurrency/atom.lux           |  13 +-
 stdlib/source/lux/concurrency/stm.lux            |   8 +-
 stdlib/source/lux/control/comonad.lux            |   5 +-
 stdlib/source/lux/control/exception.lux          |   5 +-
 stdlib/source/lux/control/hash.lux               |   5 +-
 stdlib/source/lux/control/monoid.lux             |   5 +-
 stdlib/source/lux/data/bit.lux                   |   4 +-
 stdlib/source/lux/data/collection/dictionary.lux |  10 +-
 stdlib/source/lux/data/collection/list.lux       |  10 +-
 stdlib/source/lux/data/collection/sequence.lux   |  13 +-
 stdlib/source/lux/data/format/json.lux           |   5 +-
 stdlib/source/lux/data/maybe.lux                 |  13 +-
 stdlib/source/lux/macro.lux                      |  20 +-
 stdlib/source/lux/macro/syntax/common.lux        |   5 +-
 stdlib/source/lux/math/modular.lux               |   4 +-
 stdlib/source/lux/math/random.lux                |  10 +-
 stdlib/source/lux/time/date.lux                  |   5 +-
 stdlib/source/lux/time/instant.lux               |   5 +-
 20 files changed, 446 insertions(+), 472 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 1114b069c..1b64aa22b 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -19,9 +19,9 @@
          (1 [[dummy-cursor (7 ["lux" "export?"])]
              [dummy-cursor (0 #1)]]
             (1 [[dummy-cursor (7 ["lux" "doc"])]
-                [dummy-cursor (5 "The type of things whose type is irrelevant.
-
-                                  It can be used to write functions or data-structures that can take, or return, anything.")]]
+                [dummy-cursor (5 ("lux text concat"
+                                  "The type of things whose type is irrelevant.\n\n"
+                                  "It can be used to write functions or data-structures that can take, or return, anything."))]]
                (0)))))])
 
 ## (type: Nothing
@@ -35,9 +35,9 @@
          (1 [[dummy-cursor (7 ["lux" "export?"])]
              [dummy-cursor (0 #1)]]
             (1 [[dummy-cursor (7 ["lux" "doc"])]
-                [dummy-cursor (5 "The type of things whose type is undefined.
-
-                                  Useful for expressions that cause errors or other \"extraordinary\" conditions.")]]
+                [dummy-cursor (5 ("lux text concat"
+                                  "The type of things whose type is undefined.\n\n"
+                                  "Useful for expressions that cause errors or other \"extraordinary\" conditions."))]]
                (0)))))])
 
 ## (type: (List a)
@@ -98,9 +98,9 @@
              (#Cons [[dummy-cursor (7 ["lux" "export?"])]
                      [dummy-cursor (0 #1)]]
                     (#Cons [[dummy-cursor (7 ["lux" "doc"])]
-                            [dummy-cursor (5 "Natural numbers (unsigned integers).
-
-                                              They start at zero (0) and extend in the positive direction.")]]
+                            [dummy-cursor (5 ("lux text concat"
+                                              "Natural numbers (unsigned integers).\n\n"
+                                              "They start at zero (0) and extend in the positive direction."))]]
                            #Nil))))])
 
 ("lux def" Int
@@ -124,9 +124,9 @@
              (#Cons [[dummy-cursor (7 ["lux" "export?"])]
                      [dummy-cursor (0 #1)]]
                     (#Cons [[dummy-cursor (7 ["lux" "doc"])]
-                            [dummy-cursor (5 "Fractional numbers that live in the interval [0,1).
-
-                                              Useful for probability, and other domains that work within that interval.")]]
+                            [dummy-cursor (5 ("lux text concat"
+                                              "Fractional numbers that live in the interval [0,1).\n\n"
+                                              "Useful for probability, and other domains that work within that interval."))]]
                            #Nil))))])
 
 ("lux def" Frac
@@ -162,9 +162,9 @@
              (#Cons [[dummy-cursor (7 ["lux" "export?"])]
                      [dummy-cursor (0 #1)]]
                     (#Cons [[dummy-cursor (7 ["lux" "doc"])]
-                            [dummy-cursor (5 "A name.
-
-                                              It is used as part of Lux syntax to represent identifiers and tags.")]]
+                            [dummy-cursor (5 ("lux text concat"
+                                              "A name.\n\n"
+                                              "It is used as part of Lux syntax to represent identifiers and tags."))]]
                            #Nil))))])
 
 ## (type: (Maybe a)
@@ -747,11 +747,11 @@
                                                                                                        (#Cons (text$ "host")
                                                                                                               #Nil)))))))))))))]
                  (#Cons [(tag$ ["lux" "doc"])
-                         (text$ "Represents the state of the Lux compiler during a run.
-
-                                  It is provided to macros during their invocation, so they can access compiler data.
-
-                                  Caveat emptor: Avoid fiddling with it, unless you know what you're doing.")]
+                         (text$ ("lux text concat"
+                                 "Represents the state of the Lux compiler during a run.\n\n"
+                                 ("lux text concat"
+                                  "It is provided to macros during their invocation, so they can access compiler data.\n\n"
+                                  "Caveat emptor: Avoid fiddling with it, unless you know what you're doing.")))]
                         default-def-meta-exported))))
 
 ## (type: (Meta a)
@@ -763,9 +763,9 @@
                             (#Apply (#Product Lux (#Parameter 1))
                                     (#Apply Text Either)))))
  (record$ (#Cons [(tag$ ["lux" "doc"])
-                  (text$ "Computations that can have access to the state of the compiler.
-
-                           These computations may fail, or modify the state of the compiler.")]
+                  (text$ ("lux text concat"
+                          "Computations that can have access to the state of the compiler.\n\n"
+                          "These computations may fail, or modify the state of the compiler."))]
                  (#Cons [(tag$ ["lux" "type-args"])
                          (tuple$ (#Cons (text$ "a") #Nil))]
                         default-def-meta-exported))))
@@ -1027,9 +1027,11 @@
 
 (macro:' #export (comment tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Throws away any code given to it.
-                         ## Great for commenting-out code, while retaining syntax high-lighting and formatting in your text editor.
-                         (comment +1 +2 +3 +4)")]
+                 (text$ ("lux text concat"
+                         "## Throws away any code given to it.\n\n"
+                         ("lux text concat"
+                          "## Great for commenting-out code, while retaining syntax high-lighting and formatting in your text editor.\n\n"
+                          "(comment +1 +2 +3 +4)")))]
                 #Nil)
          (return #Nil))
 
@@ -1219,14 +1221,13 @@
 
 (macro:' #export (All tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Universal quantification.
-                         (All [a]
-                           (-> a a))
-
-                         ## A name can be provided, to specify a recursive type.
-                         (All List [a]
-                           (| Any
-                              [a (List a)]))")]
+                 (text$ ("lux text concat"
+                         "## Universal quantification.\n\n"
+                         ("lux text concat"
+                          "(All [a] (-> a a))\n\n"
+                          ("lux text concat"
+                           "## A name can be provided, to specify a recursive type.\n\n"
+                           "(All List [a] (| Any [a (List a)]))"))))]
                 #Nil)
          (let'' [self-name tokens] ({(#Cons [_ (#Identifier "" self-name)] tokens)
                                      [self-name tokens]
@@ -1264,16 +1265,13 @@
 
 (macro:' #export (Ex tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Existential quantification.
-                         (Ex [a]
-                           [(Codec Text a)
-                           a])
-
-                         ## A name can be provided, to specify a recursive type.
-                         (Ex Self [a]
-                           [(Codec Text a)
-                            a
-                            (List (Self a))])")]
+                 (text$ ("lux text concat"
+                         "## Existential quantification.\n\n"
+                         ("lux text concat"
+                          "(Ex [a] [(Codec Text a) a])\n\n"
+                          ("lux text concat"
+                           "## A name can be provided, to specify a recursive type.\n\n"
+                           "(Ex Self [a] [(Codec Text a) a (List (Self a))])"))))]
                 #Nil)
          (let'' [self-name tokens] ({(#Cons [_ (#Identifier "" self-name)] tokens)
                                      [self-name tokens]
@@ -1319,10 +1317,11 @@
 
 (macro:' #export (-> tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Function types:
-                         (-> Int Int Int)
-
-                         ## This is the type of a function that takes 2 Ints and returns an Int.")]
+                 (text$ ("lux text concat"
+                         "## Function types:\n\n"
+                         ("lux text concat"
+                          "(-> Int Int Int)\n\n"
+                          "## This is the type of a function that takes 2 Ints and returns an Int.")))]
                 #Nil)
          ({(#Cons output inputs)
            (return (#Cons (list/fold ("lux check" (#Function Code (#Function Code Code))
@@ -1337,8 +1336,9 @@
 
 (macro:' #export (list xs)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## List-construction macro.
-                         (list +1 +2 +3)")]
+                 (text$ ("lux text concat"
+                         "## List-construction macro.\n\n"
+                         "(list +1 +2 +3)"))]
                 #Nil)
          (return (#Cons (list/fold (function'' [head tail]
                                                (form$ (#Cons (tag$ ["lux" "Cons"])
@@ -1350,9 +1350,11 @@
 
 (macro:' #export (list& xs)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## List-construction macro, with the last element being a tail-list.
-                         ## In other words, this macro prepends elements to another list.
-                         (list& +1 +2 +3 (list +4 +5 +6))")]
+                 (text$ ("lux text concat"
+                         "## List-construction macro, with the last element being a tail-list.\n\n"
+                         ("lux text concat"
+                          "## In other words, this macro prepends elements to another list.\n\n"
+                          "(list& +1 +2 +3 (list +4 +5 +6))")))]
                 #Nil)
          ({(#Cons last init)
            (return (list (list/fold (function'' [head tail]
@@ -1367,11 +1369,13 @@
 
 (macro:' #export (& tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Tuple types:
-                         (& Text Int Bit)
-
-                         ## Any.
-                         (&)")]
+                 (text$ ("lux text concat"
+                         "## Tuple types:\n\n"
+                         ("lux text concat"
+                          "(& Text Int Bit)\n\n"
+                          ("lux text concat"
+                           "## Any.\n\n"
+                           "(&)"))))]
                 #Nil)
          ({#Nil
            (return (list (identifier$ ["lux" "Any"])))
@@ -1384,11 +1388,13 @@
 
 (macro:' #export (| tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Variant types:
-                         (| Text Int Bit)
-
-                         ## Nothing.
-                         (|)")]
+                 (text$ ("lux text concat"
+                         "## Variant types:\n\n"
+                         ("lux text concat"
+                          "(| Text Int Bit)\n\n"
+                          ("lux text concat"
+                           "## Nothing.\n\n"
+                           "(|)"))))]
                 #Nil)
          ({#Nil
            (return (list (identifier$ ["lux" "Nothing"])))
@@ -1563,11 +1569,13 @@
 
 (macro:' #export (_$ tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Left-association for the application of binary functions over variadic arguments.
-                         (_$ text/compose \"Hello, \" name \".\\nHow are you?\")
-
-                         ## =>
-                         (text/compose (text/compose \"Hello, \" name) \".\\nHow are you?\")")]
+                 (text$ ("lux text concat"
+                         "## Left-association for the application of binary functions over variadic arguments.\n\n"
+                         ("lux text concat"
+                          "(_$ text/compose \"Hello, \" name \".\\nHow are you?\")\n\n"
+                          ("lux text concat"
+                           "## =>\n\n"
+                           "(text/compose (text/compose \"Hello, \" name) \".\\nHow are you?\")"))))]
                 #Nil)
          ({(#Cons op tokens')
            ({(#Cons first nexts)
@@ -1583,11 +1591,13 @@
 
 (macro:' #export ($_ tokens)
          (#Cons [(tag$ ["lux" "doc"])
-                 (text$ "## Right-association for the application of binary functions over variadic arguments.
-                         ($_ text/compose \"Hello, \" name \".\\nHow are you?\")
-
-                         ## =>
-                         (text/compose \"Hello, \" (text/compose name \".\\nHow are you?\"))")]
+                 (text$ ("lux text concat"
+                         "## Right-association for the application of binary functions over variadic arguments.\n\n"
+                         ("lux text concat"
+                          "($_ text/compose \"Hello, \" name \".\\nHow are you?\")\n\n"
+                          ("lux text concat"
+                           "## =>\n\n"
+                           "(text/compose \"Hello, \" (text/compose name \".\\nHow are you?\"))"))))]
                 #Nil)
          ({(#Cons op tokens')
            ({(#Cons last prevs)
@@ -1715,13 +1725,10 @@
 
 (macro:' #export (if tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "Picks which expression to evaluate based on a bit test value.
-
-                        (if #1
-                          \"Oh, yeah!\"
-                          \"Aw hell naw!\")
-
-                        => \"Oh, yeah!\"")])
+                (text$ ($_ "lux text concat"
+                           "Picks which expression to evaluate based on a bit test value." "\n\n"
+                           "(if #1 \"Oh, yeah!\" \"Aw hell naw!\")" "\n\n"
+                           "=> \"Oh, yeah!\""))])
          ({(#Cons test (#Cons then (#Cons else #Nil)))
            (return (list (form$ (list (record$ (list [(bit$ #1)  then]
                                                      [(bit$ #0) else]))
@@ -1759,9 +1766,9 @@
 
 (def:''' #export (log! message)
          (list [(tag$ ["lux" "doc"])
-                (text$ "Logs message to standard output.
-
-                        Useful for debugging.")])
+                (text$ ($_ "lux text concat"
+                           "Logs message to standard output." "\n\n"
+                           "Useful for debugging."))])
          (-> Text Any)
          ("lux io log" message))
 
@@ -1966,10 +1973,10 @@
 
 (macro:' #export (primitive tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Macro to treat define new primitive types.
-                        (primitive \"java.lang.Object\")
-
-                        (primitive \"java.util.List\" [(primitive \"java.lang.Long\")])")])
+                (text$ ($_ "lux text concat"
+                           "## Macro to treat define new primitive types." "\n\n"
+                           "(primitive \"java.lang.Object\")" "\n\n"
+                           "(primitive \"java.util.List\" [(primitive \"java.lang.Long\")])"))])
          ({(#Cons [_ (#Text class-name)] #Nil)
            (return (list (form$ (list (tag$ ["lux" "Primitive"]) (text$ class-name) (tag$ ["lux" "Nil"])))))
 
@@ -1997,11 +2004,10 @@
 
 (macro:' #export (` tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Hygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms.
-                        ## All unprefixed macros will receive their parent module's prefix if imported; otherwise will receive the prefix of the module on which the quasi-quote is being used.
-                        (` (def: (~ name)
-                             (function ((~' _) (~+ args))
-                               (~ body))))")])
+                (text$ ($_ "lux text concat"
+                           "## Hygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms." "\n\n"
+                           "## All unprefixed macros will receive their parent module's prefix if imported; otherwise will receive the prefix of the module on which the quasi-quote is being used." "\n\n"
+                           "(` (def: (~ name) (function ((~' _) (~+ args)) (~ body))))"))])
          ({(#Cons template #Nil)
            (do Monad
              [current-module current-module-name
@@ -2016,10 +2022,9 @@
 
 (macro:' #export (`' tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Unhygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms.
-                        (`' (def: (~ name)
-                              (function (_ (~+ args))
-                                (~ body))))")])
+                (text$ ($_ "lux text concat"
+                           "## Unhygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms." "\n\n"
+                           "(`' (def: (~ name) (function (_ (~+ args)) (~ body))))"))])
          ({(#Cons template #Nil)
            (do Monad
              [=template (untemplate #1 "" template)]
@@ -2031,8 +2036,9 @@
 
 (macro:' #export (' tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Quotation as a macro.
-                        (' \"YOLO\")")])
+                (text$ ($_ "lux text concat"
+                           "## Quotation as a macro." "\n\n"
+                           "(' \"YOLO\")"))])
          ({(#Cons template #Nil)
            (do Monad
              [=template (untemplate #0 "" template)]
@@ -2044,13 +2050,11 @@
 
 (macro:' #export (|> tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Piping macro.
-                        (|> elems (list/map int/encode) (interpose \" \") (fold text/compose \"\"))
-
-                        ## =>
-                        (fold text/compose \"\"
-                              (interpose \" \"
-                                         (list/map int/encode elems)))")])
+                (text$ ($_ "lux text concat"
+                           "## Piping macro." "\n\n"
+                           "(|> elems (list/map int/encode) (interpose \" \") (fold text/compose \"\"))" "\n\n"
+                           "## =>" "\n\n"
+                           "(fold text/compose \"\" (interpose \" \" (list/map int/encode elems)))"))])
          ({(#Cons [init apps])
            (return (list (list/fold ("lux check" (-> Code Code Code)
                                      (function' [app acc]
@@ -2072,13 +2076,11 @@
 
 (macro:' #export (<| tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Reverse piping macro.
-                        (<| (fold text/compose \"\") (interpose \" \") (list/map int/encode) elems)
-
-                        ## =>
-                        (fold text/compose \"\"
-                              (interpose \" \"
-                                         (list/map int/encode elems)))")])
+                (text$ ($_ "lux text concat"
+                           "## Reverse piping macro." "\n\n"
+                           "(<| (fold text/compose \"\") (interpose \" \") (list/map int/encode) elems)" "\n\n"
+                           "## =>" "\n\n"
+                           "(fold text/compose \"\" (interpose \" \" (list/map int/encode elems)))"))])
          ({(#Cons [init apps])
            (return (list (list/fold ("lux check" (-> Code Code Code)
                                      (function' [app acc]
@@ -2249,14 +2251,12 @@
 
 (macro:' #export (do-template tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## By specifying a pattern (with holes), and the input data to fill those holes, repeats the pattern as many times as necessary.
-                        (do-template [ ]
-                          [(def: #export 
-                             (-> Int Int)
-                             (i/+ ))]
-
-                          [inc +1]
-                          [dec -1])")])
+                (text$ ($_ "lux text concat"
+                           "## By specifying a pattern (with holes), and the input data to fill those holes, repeats the pattern as many times as necessary." "\n\n"
+                           "(do-template [ ]" "\n"
+                           "  " "[(def: #export  (-> Int Int) (i/+ ))]" "\n\n"
+                           "  " "[inc +1]" "\n"
+                           "  " "[dec -1]"))])
          ({(#Cons [[_ (#Tuple bindings)] (#Cons [[_ (#Tuple templates)] data])])
            ({[(#Some bindings') (#Some data')]
              (let' [apply ("lux check" (-> RepEnv ($' List Code))
@@ -2602,11 +2602,10 @@
 
 (def:''' #export (not x)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Bit negation.
-
-                        (not #1) => #0
-
-                        (not #0) => #1")])
+                (text$ ($_ "lux text concat"
+                           "## Bit negation." "\n\n"
+                           "(not #1) => #0" "\n\n"
+                           "(not #0) => #1"))])
          (-> Bit Bit)
          (if x #0 #1))
 
@@ -2815,8 +2814,9 @@
 
 (macro:' #export (type tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Takes a type expression and returns it's representation as data-structure.
-                        (type (All [a] (Maybe (List a))))")])
+                (text$ ($_ "lux text concat"
+                           "## Takes a type expression and returns it's representation as data-structure." "\n\n"
+                           "(type (All [a] (Maybe (List a))))"))])
          ({(#Cons type #Nil)
            (do Monad
              [type+ (macro-expand-all type)]
@@ -2833,8 +2833,9 @@
 
 (macro:' #export (: tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## The type-annotation macro.
-                        (: (List Int) (list +1 +2 +3))")])
+                (text$ ($_ "lux text concat"
+                           "## The type-annotation macro." "\n\n"
+                           "(: (List Int) (list +1 +2 +3))"))])
          ({(#Cons type (#Cons value #Nil))
            (return (list (` ("lux check" (type (~ type)) (~ value)))))
 
@@ -2844,8 +2845,9 @@
 
 (macro:' #export (:coerce tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## The type-coercion macro.
-                        (:coerce Dinosaur (list +1 +2 +3))")])
+                (text$ ($_ "lux text concat"
+                           "## The type-coercion macro." "\n\n"
+                           "(:coerce Dinosaur (list +1 +2 +3))"))])
          ({(#Cons type (#Cons value #Nil))
            (return (list (` ("lux coerce" (type (~ type)) (~ value)))))
 
@@ -2941,10 +2943,10 @@
 
 (macro:' #export (Rec tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Parameter-less recursive types.
-                        ## A name has to be given to the whole type, to use it within its body.
-                        (Rec Self
-                          [Int (List Self)])")])
+                (text$ ($_ "lux text concat"
+                           "## Parameter-less recursive types." "\n\n"
+                           "## A name has to be given to the whole type, to use it within its body." "\n\n"
+                           "(Rec Self [Int (List Self)])"))])
          ({(#Cons [_ (#Identifier "" name)] (#Cons body #Nil))
            (let' [body' (replace-syntax (list [name (` (#.Apply (~ (make-parameter 1)) (~ (make-parameter 0))))])
                                         (update-parameters body))]
@@ -2956,12 +2958,13 @@
 
 (macro:' #export (exec tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Sequential execution of expressions (great for side-effects).
-                        (exec
-                          (log! \"#1\")
-                          (log! \"#2\")
-                          (log! \"#3\")
-                          \"YOLO\")")])
+                (text$ ($_ "lux text concat"
+                           "## Sequential execution of expressions (great for side-effects)." "\n\n"
+                           "(exec" "\n"
+                           "  " "(log! \"#1\")" "\n"
+                           "  " "(log! \"#2\")" "\n"
+                           "  " "(log! \"#3\")" "\n"
+                           "\"YOLO\")"))])
          ({(#Cons value actions)
            (let' [dummy (identifier$ ["" ""])]
                  (return (list (list/fold ("lux check" (-> Code Code Code)
@@ -3113,14 +3116,14 @@
 
 (macro:' #export (case tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## The pattern-matching macro.
-                        ## Allows the usage of macros within the patterns to provide custom syntax.
-                        (case (: (List Int) (list +1 +2 +3))
-                          (#Cons x (#Cons y (#Cons z #Nil)))
-                          (#Some ($_ i/* x y z))
-
-                          _
-                          #None)")])
+                (text$ ($_ "lux text concat"
+                           "## The pattern-matching macro." "\n"
+                           "## Allows the usage of macros within the patterns to provide custom syntax." "\n"
+                           "(case (: (List Int) (list +1 +2 +3))" "\n"
+                           "  " "(#Cons x (#Cons y (#Cons z #Nil)))" "\n"
+                           "  " "(#Some ($_ i/* x y z))" "\n\n"
+                           "  " "_" "\n"
+                           "  " "#None)"))])
          ({(#Cons value branches)
            (do Monad
              [expansion (expander branches)]
@@ -3132,14 +3135,15 @@
 
 (macro:' #export (^ tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Macro-expanding patterns.
-                        ## It's a special macro meant to be used with 'case'.
-                        (case (: (List Int) (list +1 +2 +3))
-                          (^ (list x y z))
-                          (#Some ($_ i/* x y z))
-
-                          _
-                          #None)")])
+                (text$ ($_ "lux text concat"
+                           "## Macro-expanding patterns." "\n"
+                           "## It's a special macro meant to be used with 'case'." "\n"
+                           "(case (: (List Int) (list +1 +2 +3))" "\n"
+                           "  (^ (list x y z))" "\n"
+                           "  (#Some ($_ i/* x y z))"
+                           "\n\n"
+                           "  _" "\n"
+                           "  #None)"))])
          (case tokens
            (#Cons [_ (#Form (#Cons pattern #Nil))] (#Cons body branches))
            (do Monad
@@ -3156,25 +3160,19 @@
 
 (macro:' #export (^or tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Or-patterns.
-                        ## It's a special macro meant to be used with 'case'.
-                        (type: Weekday
-                          #Monday
-                          #Tuesday
-                          #Wednesday
-                          #Thursday
-                          #Friday
-                          #Saturday
-                          #Sunday)
-
-                        (def: (weekend? day)
-                          (-> Weekday Bit)
-                          (case day
-                            (^or #Saturday #Sunday)
-                            #1
-
-                            _
-                            #0))")])
+                (text$ ($_ "lux text concat"
+                           "## Or-patterns." "\n"
+                           "## It's a special macro meant to be used with 'case'." "\n"
+                           "(type: Weekday #Monday #Tuesday #Wednesday #Thursday #Friday #Saturday #Sunday)"
+                           "\n\n"
+                           "(def: (weekend? day)" "\n"
+                           "  (-> Weekday Bit)" "\n"
+                           "  (case day" "\n"
+                           "    (^or #Saturday #Sunday)" "\n"
+                           "    #1"
+                           "\n\n"
+                           "    _" "\n"
+                           "    #0))"))])
          (case tokens
            (^ (list& [_ (#Form patterns)] body branches))
            (case patterns
@@ -3200,11 +3198,12 @@
 
 (macro:' #export (let tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Creates local bindings.
-                        ## Can (optionally) use pattern-matching macros when binding.
-                        (let [x (foo bar)
-                              y (baz quux)]
-                          (op x y))")])
+                (text$ ($_ "lux text concat"
+                           "## Creates local bindings." "\n"
+                           "## Can (optionally) use pattern-matching macros when binding." "\n"
+                           "(let [x (foo bar)" "\n"
+                           "      y (baz quux)]" "\n"
+                           "  (op x y))"))])
          (case tokens
            (^ (list [_ (#Tuple bindings)] body))
            (if (multiple? 2 (list/size bindings))
@@ -3225,13 +3224,14 @@
 
 (macro:' #export (function tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Syntax for creating functions.
-                        ## Allows for giving the function itself a name, for the sake of recursion.
-                        (: (All [a b] (-> a b a))
-                           (function (_ x y) x))
-
-                        (: (All [a b] (-> a b a))
-                           (function (const x y) x))")])
+                (text$ ($_ "lux text concat"
+                           "## Syntax for creating functions." "\n"
+                           "## Allows for giving the function itself a name, for the sake of recursion." "\n"
+                           "(: (All [a b] (-> a b a))" "\n"
+                           "   (function (_ x y) x))"
+                           "\n\n"
+                           "(: (All [a b] (-> a b a))" "\n"
+                           "   (function (const x y) x))"))])
          (case (: (Maybe [Text Code (List Code) Code])
                   (case tokens
                     (^ (list [_ (#Form (list& [_ (#Identifier ["" name])] head tail))] body))
@@ -3343,15 +3343,16 @@
 
 (macro:' #export (def: tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "## Defines global constants/functions.
-                        (def: (rejoin-pair pair)
-                          (-> [Code Code] (List Code))
-                          (let [[left right] pair]
-                            (list left right)))
-
-                        (def: branching-exponent
-                          Int
-                          +5)")])
+                (text$ ($_ "lux text concat"
+                           "## Defines global constants/functions." "\n"
+                           "(def: (rejoin-pair pair)" "\n"
+                           "  (-> [Code Code] (List Code))" "\n"
+                           "  (let [[left right] pair]" "\n"
+                           "    (list left right)))"
+                           "\n\n"
+                           "(def: branching-exponent" "\n"
+                           "  Int" "\n"
+                           "  +5)"))])
          (let [[export? tokens'] (export^ tokens)
                parts (: (Maybe [Code (List Code) (Maybe Code) Code (List [Code Code])])
                         (case tokens'
@@ -3427,17 +3428,17 @@
 
 (macro:' #export (macro: tokens)
          (list [(tag$ ["lux" "doc"])
-                (text$ "Macro-definition macro.
-
-                        (macro: #export (name-of tokens)
-                          (case tokens
-                            (^template []
-                              (^ (list [_ ( [prefix name])]))
-                              (return (list (` [(~ (text$ prefix)) (~ (text$ name))]))))
-                                            ([#Identifier] [#Tag])
-
-                            _
-                            (fail \"Wrong syntax for name-of\")))")])
+                (text$ ($_ "lux text concat"
+                           "## Macro-definition macro." "\n"
+                           "(macro: #export (name-of tokens)" "\n"
+                           "  (case tokens" "\n"
+                           "    (^template []" "\n"
+                           "      (^ (list [_ ( [prefix name])]))" "\n"
+                           "      (return (list (` [(~ (text$ prefix)) (~ (text$ name))]))))" "\n"
+                           "    ([#Identifier] [#Tag])"
+                           "\n\n"
+                           "    _" "\n"
+                           "    (fail \"Wrong syntax for name-of\")))"))])
          (let [[exported? tokens] (export^ tokens)
                name+args+meta+body?? (: (Maybe [Name (List Code) Code Code])
                                         (case tokens
@@ -3474,18 +3475,19 @@
              (fail "Wrong syntax for macro:"))))
 
 (macro: #export (signature: tokens)
-  {#.doc "## Definition of signatures ala ML.
-          (signature: #export (Ord a)
-            (: (Equivalence a)
-               eq)
-            (: (-> a a Bit)
-               <)
-            (: (-> a a Bit)
-               <=)
-            (: (-> a a Bit)
-               >)
-            (: (-> a a Bit)
-               >=))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Definition of signatures ala ML." "\n"
+                    "(signature: #export (Ord a)" "\n"
+                    "  (: (Equivalence a)" "\n"
+                    "     eq)" "\n"
+                    "  (: (-> a a Bit)" "\n"
+                    "     <)" "\n"
+                    "  (: (-> a a Bit)" "\n"
+                    "     <=)" "\n"
+                    "  (: (-> a a Bit)" "\n"
+                    "     >)" "\n"
+                    "  (: (-> a a Bit)" "\n"
+                    "     >=))"))}
   (let [[exported? tokens'] (export^ tokens)
         ?parts (: (Maybe [Name (List Code) Code (List Code)])
                   (case tokens'
@@ -3600,17 +3602,20 @@
   ("lux text clip" text from to))
 
 (def: #export (error! message)
-  {#.doc "## Causes an error, with the given error message.
-          (error! \"OH NO!\")"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Causes an error, with the given error message." "\n"
+                    "(error! \"OH NO!\")"))}
   (-> Text Nothing)
   ("lux io error" message))
 
 (macro: (default tokens state)
-  {#.doc "## Allows you to provide a default value that will be used
-          ## if a (Maybe x) value turns out to be #.None.
-          (default +20 (#.Some +10)) => +10
-
-          (default +20 #.None) => +20"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Allows you to provide a default value that will be used" "\n"
+                    "## if a (Maybe x) value turns out to be #.None."
+                    "\n\n"
+                    "(default +20 (#.Some +10)) ## => +10"
+                    "\n\n"
+                    "(default +20 #.None) ## => +20"))}
   (case tokens
     (^ (list else maybe))
     (let [g!temp (: Code [dummy-cursor (#Identifier ["" ""])])
@@ -3883,19 +3888,20 @@
   (|> parts list/reverse (list/fold text/compose "")))
 
 (macro: #export (structure: tokens)
-  {#.doc "## Definition of structures ala ML.
-          (structure: #export Ord (Ord Int)
-            (def: eq Equivalence)
-            (def: (< test subject)
-              (lux.< test subject))
-            (def: (<= test subject)
-              (or (lux.< test subject)
-                  (lux.= test subject)))
-            (def: (lux.> test subject)
-              (lux.> test subject))
-            (def: (lux.>= test subject)
-              (or (lux.> test subject)
-                  (lux.= test subject))))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Definition of structures ala ML." "\n"
+                    "(structure: #export Ord (Ord Int)" "\n"
+                    "  (def: eq Equivalence)" "\n"
+                    "  (def: (< test subject)" "\n"
+                    "    (lux.i/< test subject))" "\n"
+                    "  (def: (<= test subject)" "\n"
+                    "    (or (lux.i/< test subject)" "\n"
+                    "        (lux.i/= test subject)))" "\n"
+                    "  (def: (> test subject)" "\n"
+                    "    (lux.i/> test subject))" "\n"
+                    "  (def: (>= test subject)" "\n"
+                    "    (or (lux.i/> test subject)" "\n"
+                    "        (lux.i/= test subject))))"))}
   (let [[exported? tokens'] (export^ tokens)
         ?parts (: (Maybe [Code (List Code) Code Code (List Code)])
                   (case tokens'
@@ -3961,17 +3967,14 @@
       (fail "Wrong syntax for structure:"))))
 
 (def: #export (id x)
-  {#.doc "Identity function.
-
-          Does nothing to it's argument and just returns it."}
+  {#.doc "Identity function. Does nothing to it's argument and just returns it."}
   (All [a] (-> a a))
   x)
 
 (macro: #export (type: tokens)
-  {#.doc "## The type-definition macro.
-          (type: (List a)
-            #Nil
-            (#Cons a (List a)))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## The type-definition macro." "\n"
+                    "(type: (List a) #Nil (#Cons a (List a)))"))}
   (let [[exported? tokens'] (export^ tokens)
         [rec? tokens'] (case tokens'
                          (#Cons [_ (#Tag [_ "rec"])] tokens')
@@ -4202,7 +4205,7 @@
                        0 prefix
                        _ ($_ text/compose prefix "/" clean))]
           (return output))
-        (fail ($_ text/compose
+        (fail ($_ "lux text concat"
                   "Cannot climb the module hierarchy...\n"
                   "Importing module: " module "\n"
                   "   Relative Root: " relative-root "\n"))))))
@@ -4488,11 +4491,12 @@
     ))
 
 (macro: #export (^open tokens)
-  {#.doc "## Same as the \"open\" macro, but meant to be used as a pattern-matching macro for generating local bindings.
-          ## Takes an \"alias\" text for the generated local bindings.
-          (def: #export (range (^open \".\") from to)
-            (All [a] (-> (Enum a) a a (List a)))
-            (range' <= succ from to))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Same as the \"open\" macro, but meant to be used as a pattern-matching macro for generating local bindings." "\n"
+                    "## Takes an \"alias\" text for the generated local bindings." "\n"
+                    "(def: #export (range (^open \".\") from to)" "\n"
+                    "  (All [a] (-> (Enum a) a a (List a)))" "\n"
+                    "  (range' <= succ from to))"))}
   (case tokens
     (^ (list& [_ (#Form (list [_ (#Text alias)]))] body branches))
     (do Monad
@@ -4538,11 +4542,13 @@
     (fail "Wrong syntax for ^open")))
 
 (macro: #export (cond tokens)
-  {#.doc "## Branching structures with multiple test conditions.
-          (cond (n/even? num) \"even\"
-                (n/odd? num) \"odd\"
-                ## else-branch
-                \"???\")"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Branching structures with multiple test conditions." "\n"
+                    "(cond (n/even? num) \"even\"" "\n"
+                    "      (n/odd? num) \"odd\""
+                    "\n\n"
+                    "      ## else-branch" "\n"
+                    "      \"???\")"))}
   (if (n/= 0 (n/% 2 (list/size tokens)))
     (fail "cond requires an uneven number of arguments.")
     (case (list/reverse tokens)
@@ -4571,16 +4577,16 @@
   (enumerate' 0 xs))
 
 (macro: #export (get@ tokens)
-  {#.doc "## Accesses the value of a record at a given tag.
-          (get@ #field my-record)
-
-          ## Can also work with multiple levels of nesting:
-          (get@ [#foo #bar #baz] my-record)
-
-          ## And, if only the slot/path is given, generates an
-          ## accessor function:
-          (let [getter (get@ [#foo #bar #baz])]
-            (getter my-record))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Accesses the value of a record at a given tag." "\n"
+                    "(get@ #field my-record)"
+                    "\n\n"
+                    "## Can also work with multiple levels of nesting:" "\n"
+                    "(get@ [#foo #bar #baz] my-record)"
+                    "\n\n"
+                    "## And, if only the slot/path is given, generates an accessor function:" "\n"
+                    "(let [getter (get@ [#foo #bar #baz])]" "\n"
+                    "  (getter my-record))"))}
   (case tokens
     (^ (list [_ (#Tag slot')] record))
     (do Monad
@@ -4639,14 +4645,17 @@
                         [(~ cursor-code) (#.Record #Nil)])))))))
 
 (macro: #export (open: tokens)
-  {#.doc "## Opens a structure and generates a definition for each of its members (including nested members).
-          ## For example:
-          (open: \"i:.\" Number)
-          ## Will generate:
-          (def: i:+ (:: Number +))
-          (def: i:- (:: Number -))
-          (def: i:* (:: Number *))
-          ..."}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Opens a structure and generates a definition for each of its members (including nested members)."
+                    "\n\n"
+                    "## For example:" "\n"
+                    "(open: \"i:.\" Number)"
+                    "\n\n"
+                    "## Will generate:" "\n"
+                    "(def: i:+ (:: Number +))" "\n"
+                    "(def: i:- (:: Number -))" "\n"
+                    "(def: i:* (:: Number *))" "\n"
+                    "..."))}
   (case tokens
     (^ (list [_ (#Text alias)] struct))
     (case struct
@@ -4678,26 +4687,22 @@
     (fail "Wrong syntax for open:")))
 
 (macro: #export (|>> tokens)
-  {#.doc "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it.
-          (|>> (list/map int/encode) (interpose \" \") (fold text/compose \"\"))
-          ## =>
-          (function (_ )
-            (fold text/compose \"\"
-                  (interpose \" \"
-                             (list/map int/encode ))))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." "\n"
+                    "(|>> (list/map int/encode) (interpose \" \") (fold text/compose \"\"))" "\n"
+                    "## =>" "\n"
+                    "(function (_ ) (fold text/compose \"\" (interpose \" \" (list/map int/encode ))))"))}
   (do Monad
     [g!_ (gensym "_")
      g!arg (gensym "arg")]
     (return (list (` (function ((~ g!_) (~ g!arg)) (|> (~ g!arg) (~+ tokens))))))))
 
 (macro: #export (<<| tokens)
-  {#.doc "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it.
-          (<<| (fold text/compose \"\") (interpose \" \") (list/map int/encode))
-          ## =>
-          (function (_ )
-            (fold text/compose \"\"
-                  (interpose \" \"
-                             (list/map int/encode ))))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." "\n"
+                    "(<<| (fold text/compose \"\") (interpose \" \") (list/map int/encode))" "\n"
+                    "## =>" "\n"
+                    "(function (_ ) (fold text/compose \"\" (interpose \" \" (list/map int/encode ))))"))}
   (do Monad
     [g!_ (gensym "_")
      g!arg (gensym "arg")]
@@ -4821,26 +4826,23 @@
                 (~+ openings)))))
 
 (macro: #export (module: tokens)
-  {#.doc "Module-definition macro.
-
-          Can take optional annotations and allows the specification of modules to import.
-
-          ## Examples
-          (.module: {#.doc \"Some documentation...\"}
-            [lux #*
-             [control
-              [\"M\" monad #*]]
-             [data
-              maybe
-              [\".\" name (\"name/.\" Codec)]
-              [\".\" text (\"text/.\" Monoid)]
-              [collection
-               [list (\"list/.\" Monad)]]]
-             meta
-             [macro
-              code]]
-            [//
-             [type (\".\" Equivalence)]])"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Module-definition macro."
+                    "\n\n"
+                    "## Can take optional annotations and allows the specification of modules to import."
+                    "\n\n"
+                    "## Example" "\n"
+                    "(.module: {#.doc \"Some documentation...\"}" "\n"
+                    "  [lux #*" "\n"
+                    "   [control" "\n"
+                    "    [\"M\" monad #*]]" "\n"
+                    "   [data" "\n"
+                    "    maybe" "\n"
+                    "    [\".\" name (\"name/.\" Codec)]]" "\n"
+                    "   [macro" "\n"
+                    "    code]]" "\n"
+                    "  [//" "\n"
+                    "   [type (\".\" Equivalence)]])"))}
   (do Monad
     [#let [[_meta _imports] (: [(List [Code Code]) (List Code)]
                                (case tokens
@@ -4866,11 +4868,12 @@
     (wrap (#Cons =module =refers))))
 
 (macro: #export (:: tokens)
-  {#.doc "## Allows accessing the value of a structure's member.
-          (:: Codec encode)
-
-          ## Also allows using that value as a function.
-          (:: Codec encode +123)"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Allows accessing the value of a structure's member." "\n"
+                    "(:: Codec encode)"
+                    "\n\n"
+                    "## Also allows using that value as a function." "\n"
+                    "(:: Codec encode +123)"))}
   (case tokens
     (^ (list struct [_ (#Identifier member)]))
     (return (list (` (let [(^open ".") (~ struct)] (~ (identifier$ member))))))
@@ -4882,19 +4885,16 @@
     (fail "Wrong syntax for ::")))
 
 (macro: #export (set@ tokens)
-  {#.doc "## Sets the value of a record at a given tag.
-          (set@ #name \"Lux\" lang)
-
-          ## Can also work with multiple levels of nesting:
-          (set@ [#foo #bar #baz] value my-record)
-
-          ## And, if only the slot/path and (optionally) the value are given, generates a
-          ## mutator function:
-          (let [setter (set@ [#foo #bar #baz] value)]
-            (setter my-record))
-
-          (let [setter (set@ [#foo #bar #baz])]
-            (setter value my-record))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Sets the value of a record at a given tag." "\n"
+                    "(set@ #name \"Lux\" lang)"
+                    "\n\n"
+                    "## Can also work with multiple levels of nesting:" "\n"
+                    "(set@ [#foo #bar #baz] value my-record)"
+                    "\n\n"
+                    "## And, if only the slot/path and (optionally) the value are given, generates a mutator function:" "\n"
+                    "(let [setter (set@ [#foo #bar #baz] value)] (setter my-record))" "\n"
+                    "(let [setter (set@ [#foo #bar #baz])] (setter value my-record))"))}
   (case tokens
     (^ (list [_ (#Tag slot')] value record))
     (do Monad
@@ -4972,19 +4972,16 @@
     (fail "Wrong syntax for set@")))
 
 (macro: #export (update@ tokens)
-  {#.doc "## Modifies the value of a record at a given tag, based on some function.
-          (update@ #age inc person)
-
-          ## Can also work with multiple levels of nesting:
-          (update@ [#foo #bar #baz] func my-record)
-
-          ## And, if only the slot/path and (optionally) the value are given, generates a
-          ## mutator function:
-          (let [updater (update@ [#foo #bar #baz] func)]
-            (updater my-record))
-
-          (let [updater (update@ [#foo #bar #baz])]
-            (updater func my-record))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Modifies the value of a record at a given tag, based on some function." "\n"
+                    "(update@ #age inc person)"
+                    "\n\n"
+                    "## Can also work with multiple levels of nesting:" "\n"
+                    "(update@ [#foo #bar #baz] func my-record)"
+                    "\n\n"
+                    "## And, if only the slot/path and (optionally) the value are given, generates a mutator function:" "\n"
+                    "(let [updater (update@ [#foo #bar #baz] func)] (updater my-record))" "\n"
+                    "(let [updater (update@ [#foo #bar #baz])] (updater func my-record))"))}
   (case tokens
     (^ (list [_ (#Tag slot')] fun record))
     (do Monad
@@ -5048,41 +5045,40 @@
     (fail "Wrong syntax for update@")))
 
 (macro: #export (^template tokens)
-  {#.doc "## It's similar to do-template, but meant to be used during pattern-matching.
-          (def: (beta-reduce env type)
-            (-> (List Type) Type Type)
-            (case type
-              (#.Primitive name params)
-              (#.Primitive name (list/map (beta-reduce env) params))
-
-              (^template []
-                ( left right)
-                ( (beta-reduce env left) (beta-reduce env right)))
-              ([#.Sum] [#.Product])
-
-              (^template []
-                ( left right)
-                ( (beta-reduce env left) (beta-reduce env right)))
-              ([#.Function]
-               [#.Apply])
-
-              (^template []
-                ( old-env def)
-                (case old-env
-                  #.Nil
-                  ( env def)
-
-                  _
-                  type))
-              ([#.UnivQ]
-               [#.ExQ])
-
-              (#.Parameter idx)
-              (default type (list.nth idx env))
-
-              _
-              type
-              ))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## It's similar to do-template, but meant to be used during pattern-matching." "\n"
+                    "(def: (beta-reduce env type)" "\n"
+                    "  (-> (List Type) Type Type)" "\n"
+                    "  (case type" "\n"
+                    "    (#.Primitive name params)" "\n"
+                    "    (#.Primitive name (list/map (beta-reduce env) params))"
+                    "\n\n"
+                    "    (^template []" "\n"
+                    "      ( left right)" "\n"
+                    "      ( (beta-reduce env left) (beta-reduce env right)))" "\n"
+                    "    ([#.Sum] [#.Product])"
+                    "\n\n"
+                    "    (^template []" "\n"
+                    "      ( left right)" "\n"
+                    "      ( (beta-reduce env left) (beta-reduce env right)))" "\n"
+                    "    ([#.Function] [#.Apply])"
+                    "\n\n"
+                    "    (^template []" "\n"
+                    "      ( old-env def)" "\n"
+                    "      (case old-env" "\n"
+                    "        #.Nil" "\n"
+                    "        ( env def)"
+                    "\n\n"
+                    "        _" "\n"
+                    "        type))" "\n"
+                    "    ([#.UnivQ] [#.ExQ])"
+                    "\n\n"
+                    "    (#.Parameter idx)" "\n"
+                    "    (default type (list.nth idx env))"
+                    "\n\n"
+                    "    _" "\n"
+                    "    type" "\n"
+                    "  ))"))}
   (case tokens
     (^ (list& [_ (#Form (list& [_ (#Tuple bindings)] templates))]
               [_ (#Form data)]
@@ -5282,16 +5278,17 @@
       (text/compose text "\n\n"))))
 
 (macro: #export (doc tokens)
-  {#.doc "## Creates code documentation, embedding text as comments and properly formatting the forms it's being given.
-
-          ## For Example:
-          (doc \"Allows arbitrary looping, using the \\\"recur\\\" form to re-start the loop.
-                Can be used in monadic code to create monadic loops.\"
-               (loop [count +0
-                      x init]
-                 (if (< +10 count)
-                   (recur (inc count) (f x))
-                   x)))"}
+  {#.doc (text$ ($_ "lux text concat"
+                    "## Creates code documentation, embedding text as comments and properly formatting the forms it's being given."
+                    "\n\n"
+                    "## For Example:" "\n"
+                    "(doc \"Allows arbitrary looping, using the \\\"recur\\\" form to re-start the loop.\"" "\n"
+                    "     \"Can be used in monadic code to create monadic loops.\"" "\n"
+                    "     (loop [count +0" "\n"
+                    "            x init]" "\n"
+                    "       (if (< +10 count)" "\n"
+                    "         (recur (inc count) (f x))" "\n"
+                    "         x)))"))}
   (return (list (` [(~ cursor-code)
                     (#.Text (~ (|> tokens
                                    (list/map (|>> identify-doc-fragment doc-fragment->Text))
diff --git a/stdlib/source/lux/concurrency/actor.lux b/stdlib/source/lux/concurrency/actor.lux
index a9154877e..0af0d09f9 100644
--- a/stdlib/source/lux/concurrency/actor.lux
+++ b/stdlib/source/lux/concurrency/actor.lux
@@ -140,8 +140,8 @@
    #end default-end})
 
 (def: #export (poison actor)
-  {#.doc "Kills the actor by sending a message that will kill it upon processing,
-          but allows the actor to handle previous messages."}
+  {#.doc (doc "Kills the actor by sending a message that will kill it upon processing,"
+              "but allows the actor to handle previous messages.")}
   (All [s] (-> (Actor s) (IO Bit)))
   (send (function (_ state self)
           (task.throw poisoned []))
diff --git a/stdlib/source/lux/concurrency/atom.lux b/stdlib/source/lux/concurrency/atom.lux
index b0c016a12..c04930171 100644
--- a/stdlib/source/lux/concurrency/atom.lux
+++ b/stdlib/source/lux/concurrency/atom.lux
@@ -33,19 +33,16 @@
                   (AtomicReference::get [] (:representation atom))})))
 
       (def: #export (compare-and-swap current new atom)
-        {#.doc "Only mutates an atom if you can present it's current value.
-
-          That guarantees that atom was not updated since you last read from it."}
+        {#.doc (doc "Only mutates an atom if you can present it's current value."
+                    "That guarantees that atom was not updated since you last read from it.")}
         (All [a] (-> a a (Atom a) (IO Bit)))
         (io (AtomicReference::compareAndSet [current new] (:representation atom))))
       ))
 
 (def: #export (update f atom)
-  {#.doc "Updates an atom by applying a function to its current value.
-
-          If it fails to update it (because some other process wrote to it first), it will retry until it succeeds.
-
-          The retries will be done with the new values of the atom, as they show up."}
+  {#.doc (doc "Updates an atom by applying a function to its current value."
+              "If it fails to update it (because some other process wrote to it first), it will retry until it succeeds."
+              "The retries will be done with the new values of the atom, as they show up.")}
   (All [a] (-> (-> a a) (Atom a) (IO a)))
   (loop [_ []]
     (do io.Monad
diff --git a/stdlib/source/lux/concurrency/stm.lux b/stdlib/source/lux/concurrency/stm.lux
index d736baf2e..3c6691acc 100644
--- a/stdlib/source/lux/concurrency/stm.lux
+++ b/stdlib/source/lux/concurrency/stm.lux
@@ -232,11 +232,9 @@
       )))
 
 (def: #export (commit stm-proc)
-  {#.doc "Commits a transaction and returns its result (asynchronously).
-
-          Note that a transaction may be re-run an indeterminate number of times if other transactions involving the same variables successfully commit first.
-
-          For this reason, it's important to note that transactions must be free from side-effects, such as I/O."}
+  {#.doc (doc "Commits a transaction and returns its result (asynchronously)."
+              "Note that a transaction may be re-run an indeterminate number of times if other transactions involving the same variables successfully commit first."
+              "For this reason, it's important to note that transactions must be free from side-effects, such as I/O.")}
   (All [a] (-> (STM a) (Promise a)))
   (let [output (promise #.None)]
     (exec (io.run init-processor!)
diff --git a/stdlib/source/lux/control/comonad.lux b/stdlib/source/lux/control/comonad.lux
index 23a059ae4..76fe954e5 100644
--- a/stdlib/source/lux/control/comonad.lux
+++ b/stdlib/source/lux/control/comonad.lux
@@ -8,9 +8,8 @@
 
 ## [Signatures]
 (signature: #export (CoMonad w)
-  {#.doc "CoMonads are the opposite/complement to monads.
-
-          CoMonadic structures are often infinite in size and built upon lazily-evaluated functions."}
+  {#.doc (doc "CoMonads are the opposite/complement to monads."
+              "CoMonadic structures are often infinite in size and built upon lazily-evaluated functions.")}
   (: (F.Functor w)
      functor)
   (: (All [a]
diff --git a/stdlib/source/lux/control/exception.lux b/stdlib/source/lux/control/exception.lux
index d2e9c705d..085269e54 100644
--- a/stdlib/source/lux/control/exception.lux
+++ b/stdlib/source/lux/control/exception.lux
@@ -31,9 +31,8 @@
   (text.starts-with? (get@ #label exception) error))
 
 (def: #export (catch exception then try)
-  {#.doc "If a particular exception is detected on a possibly-erroneous value, handle it.
-
-          If no exception was detected, or a different one from the one being checked, then pass along the original value."}
+  {#.doc (doc "If a particular exception is detected on a possibly-erroneous value, handle it."
+              "If no exception was detected, or a different one from the one being checked, then pass along the original value.")}
   (All [e a]
     (-> (Exception e) (-> Text a) (Error a)
         (Error a)))
diff --git a/stdlib/source/lux/control/hash.lux b/stdlib/source/lux/control/hash.lux
index aa668c7c7..4e50c3658 100644
--- a/stdlib/source/lux/control/hash.lux
+++ b/stdlib/source/lux/control/hash.lux
@@ -4,9 +4,8 @@
 
 ## [Signatures]
 (signature: #export (Hash a)
-  {#.doc "A way to produce hash-codes for a type's instances.
-
-          A necessity when working with some data-structures, such as dictionaries or sets."}
+  {#.doc (doc "A way to produce hash-codes for a type's instances."
+              "A necessity when working with some data-structures, such as dictionaries or sets.")}
   (: (Equivalence a)
      eq)
   (: (-> a Nat)
diff --git a/stdlib/source/lux/control/monoid.lux b/stdlib/source/lux/control/monoid.lux
index 4976830b6..7d89043a8 100644
--- a/stdlib/source/lux/control/monoid.lux
+++ b/stdlib/source/lux/control/monoid.lux
@@ -3,9 +3,8 @@
   [// [fold (#+ Fold)]])
 
 (signature: #export (Monoid a)
-  {#.doc "A way to compose values.
-
-          Includes an identity value which does not alter any other value when combined with."}
+  {#.doc (doc "A way to compose values."
+              "Includes an identity value which does not alter any other value when combined with.")}
   (: a
      identity)
   (: (-> a a a)
diff --git a/stdlib/source/lux/data/bit.lux b/stdlib/source/lux/data/bit.lux
index 026f8bcab..8cf671429 100644
--- a/stdlib/source/lux/data/bit.lux
+++ b/stdlib/source/lux/data/bit.lux
@@ -45,7 +45,7 @@
 
 ## [Values]
 (def: #export complement
-  {#.doc "Generates the complement of a predicate.
-          That is a predicate that returns the oposite of the original predicate."}
+  {#.doc (doc "Generates the complement of a predicate."
+              "That is a predicate that returns the oposite of the original predicate.")}
   (All [a] (-> (-> a Bit) (-> a Bit)))
   (compose not))
diff --git a/stdlib/source/lux/data/collection/dictionary.lux b/stdlib/source/lux/data/collection/dictionary.lux
index e61d657a5..503ea312d 100644
--- a/stdlib/source/lux/data/collection/dictionary.lux
+++ b/stdlib/source/lux/data/collection/dictionary.lux
@@ -623,18 +623,16 @@
   )
 
 (def: #export (merge dict2 dict1)
-  {#.doc "Merges 2 dictionaries.
-
-          If any collisions with keys occur, the values of dict2 will overwrite those of dict1."}
+  {#.doc (doc "Merges 2 dictionaries."
+              "If any collisions with keys occur, the values of dict2 will overwrite those of dict1.")}
   (All [k v] (-> (Dictionary k v) (Dictionary k v) (Dictionary k v)))
   (list/fold (function (_ [key val] dict) (put key val dict))
              dict1
              (entries dict2)))
 
 (def: #export (merge-with f dict2 dict1)
-  {#.doc "Merges 2 dictionaries.
-
-          If any collisions with keys occur, a new value will be computed by applying 'f' to the values of dict2 and dict1."}
+  {#.doc (doc "Merges 2 dictionaries."
+              "If any collisions with keys occur, a new value will be computed by applying 'f' to the values of dict2 and dict1.")}
   (All [k v] (-> (-> v v v) (Dictionary k v) (Dictionary k v) (Dictionary k v)))
   (list/fold (function (_ [key val2] dict)
                (case (get key dict)
diff --git a/stdlib/source/lux/data/collection/list.lux b/stdlib/source/lux/data/collection/list.lux
index d11f0a080..ef1ebf5ac 100644
--- a/stdlib/source/lux/data/collection/list.lux
+++ b/stdlib/source/lux/data/collection/list.lux
@@ -53,9 +53,8 @@
   [(filter p xs) (filter (complement p) xs)])
 
 (def: #export (as-pairs xs)
-  {#.doc "Cut the list into pairs of 2.
-
-          Caveat emptor: If the list has an uneven number of elements, the last one will be skipped."}
+  {#.doc (doc "Cut the list into pairs of 2."
+              "Caveat emptor: If the list has an uneven number of elements, the last one will be skipped.")}
   (All [a] (-> (List a) (List [a a])))
   (case xs
     (^ (#.Cons [x1 (#.Cons [x2 xs'])]))
@@ -517,9 +516,8 @@
     (last xs')))
 
 (def: #export (inits xs)
-  {#.doc "For a list of size N, returns the first N-1 elements.
-
-          Empty lists will result in a #.None value being returned instead."}
+  {#.doc (doc "For a list of size N, returns the first N-1 elements."
+              "Empty lists will result in a #.None value being returned instead.")}
   (All [a] (-> (List a) (Maybe (List a))))
   (case xs
     #.Nil
diff --git a/stdlib/source/lux/data/collection/sequence.lux b/stdlib/source/lux/data/collection/sequence.lux
index 6529a1ced..06209f4d6 100644
--- a/stdlib/source/lux/data/collection/sequence.lux
+++ b/stdlib/source/lux/data/collection/sequence.lux
@@ -41,9 +41,8 @@
   (pending [x (repeat x)]))
 
 (def: #export (cycle xs)
-  {#.doc "Go over the elements of a list forever.
-
-          The list should not be empty."}
+  {#.doc (doc "Go over the elements of a list forever."
+              "The list should not be empty.")}
   (All [a]
     (-> (List a) (Maybe (Sequence a))))
   (case xs
@@ -111,11 +110,9 @@
       (filter p xs'))))
 
 (def: #export (partition p xs)
-  {#.doc "Split a sequence in two based on a predicate.
-
-          The left side contains all entries for which the predicate is #1.
-
-          The right side contains all entries for which the predicate is #0."}
+  {#.doc (doc "Split a sequence in two based on a predicate."
+              "The left side contains all entries for which the predicate is #1."
+              "The right side contains all entries for which the predicate is #0.")}
   (All [a] (-> (-> a Bit) (Sequence a) [(Sequence a) (Sequence a)]))
   [(filter p xs) (filter (complement p) xs)])
 
diff --git a/stdlib/source/lux/data/format/json.lux b/stdlib/source/lux/data/format/json.lux
index 3594ef28c..c26df1893 100644
--- a/stdlib/source/lux/data/format/json.lux
+++ b/stdlib/source/lux/data/format/json.lux
@@ -1,6 +1,5 @@
-(.module: {#.doc "Functionality for reading and writing values in the JSON format.
-
-                  For more information, please see: http://www.json.org/"}
+(.module: {#.doc (.doc "Functionality for reading and writing values in the JSON format."
+                       "For more information, please see: http://www.json.org/")}
   [lux #*
    [control
     ["." monad (#+ do Monad)]
diff --git a/stdlib/source/lux/data/maybe.lux b/stdlib/source/lux/data/maybe.lux
index 57ff95727..d0dfe1886 100644
--- a/stdlib/source/lux/data/maybe.lux
+++ b/stdlib/source/lux/data/maybe.lux
@@ -82,11 +82,14 @@
   (monad.lift Monad (:: Monad wrap)))
 
 (macro: #export (default tokens state)
-  {#.doc "## Allows you to provide a default value that will be used
-          ## if a (Maybe x) value turns out to be #.None.
-          (default +20 (#.Some +10)) => +10
-
-          (default +20 #.None) => +20"}
+  {#.doc (doc "Allows you to provide a default value that will be used"
+              "if a (Maybe x) value turns out to be #.None."
+              (default +20 (#.Some +10))
+              "=>"
+              +10
+              (default +20 #.None)
+              "=>"
+              +20)}
   (case tokens
     (^ (list else maybe))
     (let [g!temp (: Code [dummy-cursor (#.Identifier ["" ""])])
diff --git a/stdlib/source/lux/macro.lux b/stdlib/source/lux/macro.lux
index 7564518f4..88299a812 100644
--- a/stdlib/source/lux/macro.lux
+++ b/stdlib/source/lux/macro.lux
@@ -264,9 +264,8 @@
         #.None))))
 
 (def: #export (normalize name)
-  {#.doc "If given a name without a module prefix, gives it the current module's name as prefix.
-
-          Otherwise, returns the name as-is."}
+  {#.doc (doc "If given a name without a module prefix, gives it the current module's name as prefix."
+              "Otherwise, returns the name as-is.")}
   (-> Name (Meta Name))
   (case name
     ["" name]
@@ -287,9 +286,8 @@
          (#e.Success [compiler (find-macro' (get@ #.modules compiler) this-module module name)])))))
 
 (def: #export (expand-once syntax)
-  {#.doc "Given code that requires applying a macro, does it once and returns the result.
-
-          Otherwise, returns the code as-is."}
+  {#.doc (doc "Given code that requires applying a macro, does it once and returns the result."
+              "Otherwise, returns the code as-is.")}
   (-> Code (Meta (List Code)))
   (case syntax
     [_ (#.Form (#.Cons [[_ (#.Identifier name)] args]))]
@@ -306,9 +304,8 @@
     (:: Monad wrap (list syntax))))
 
 (def: #export (expand syntax)
-  {#.doc "Given code that requires applying a macro, expands repeatedly until no more direct macro-calls are left.
-
-          Otherwise, returns the code as-is."}
+  {#.doc (doc "Given code that requires applying a macro, expands repeatedly until no more direct macro-calls are left."
+              "Otherwise, returns the code as-is.")}
   (-> Code (Meta (List Code)))
   (case syntax
     [_ (#.Form (#.Cons [[_ (#.Identifier name)] args]))]
@@ -367,9 +364,8 @@
                  (get@ #.seed compiler)])))
 
 (def: #export (gensym prefix)
-  {#.doc "Generates a unique name as an Code node (ready to be used in code templates).
-
-          A prefix can be given (or just be empty text \"\") to better identify the code for debugging purposes."}
+  {#.doc (doc "Generates a unique name as an Code node (ready to be used in code templates)."
+              "A prefix can be given (or just be empty text \"\") to better identify the code for debugging purposes.")}
   (-> Text (Meta Code))
   (function (_ compiler)
     (#e.Success [(update@ #.seed inc compiler)
diff --git a/stdlib/source/lux/macro/syntax/common.lux b/stdlib/source/lux/macro/syntax/common.lux
index dc38d1409..0729c05fe 100644
--- a/stdlib/source/lux/macro/syntax/common.lux
+++ b/stdlib/source/lux/macro/syntax/common.lux
@@ -1,6 +1,5 @@
-(.module: {#.doc "Commons syntax readers and writers.
-
-                  The goal is to be able to reuse common syntax in macro definitions across libraries."}
+(.module: {#.doc (.doc "Commons syntax readers and writers."
+                       "The goal is to be able to reuse common syntax in macro definitions across libraries.")}
   [lux (#- Definition)])
 
 (type: #export Declaration
diff --git a/stdlib/source/lux/math/modular.lux b/stdlib/source/lux/math/modular.lux
index ef0f36bb2..883febecb 100644
--- a/stdlib/source/lux/math/modular.lux
+++ b/stdlib/source/lux/math/modular.lux
@@ -19,8 +19,8 @@
 (exception: #export zero-cannot-be-a-modulus)
 
 (abstract: #export (Modulus m)
-  {#.doc "A number used as a modulus in modular arithmetic.
-          It cannot be 0."}
+  {#.doc (doc "A number used as a modulus in modular arithmetic."
+              "It cannot be 0.")}
   
   Int
 
diff --git a/stdlib/source/lux/math/random.lux b/stdlib/source/lux/math/random.lux
index 92eced24d..ffb7bc592 100644
--- a/stdlib/source/lux/math/random.lux
+++ b/stdlib/source/lux/math/random.lux
@@ -268,9 +268,8 @@
 (def: pcg-32-magic-mult Nat 6364136223846793005)
 
 (def: #export (pcg-32 [inc seed])
-  {#.doc "An implementation of the PCG32 algorithm.
-
-          For more information, please see: http://www.pcg-random.org/"}
+  {#.doc (doc "An implementation of the PCG32 algorithm."
+              "For more information, please see: http://www.pcg-random.org/")}
   (-> [(I64 Any) (I64 Any)] PRNG)
   (function (_ _)
     [(|> seed .nat (n/* pcg-32-magic-mult) ("lux i64 +" inc) [inc] pcg-32)
@@ -283,9 +282,8 @@
            .i64))]))
 
 (def: #export (xoroshiro-128+ [s0 s1])
-  {#.doc "An implementation of the Xoroshiro128+ algorithm.
-
-          For more information, please see: http://xoroshiro.di.unimi.it/"}
+  {#.doc (doc "An implementation of the Xoroshiro128+ algorithm."
+              "For more information, please see: http://xoroshiro.di.unimi.it/")}
   (-> [(I64 Any) (I64 Any)] PRNG)
   (function (_ _)
     [(let [s01 (i64.xor s0 s1)]
diff --git a/stdlib/source/lux/time/date.lux b/stdlib/source/lux/time/date.lux
index b902b631f..0e8f5468a 100644
--- a/stdlib/source/lux/time/date.lux
+++ b/stdlib/source/lux/time/date.lux
@@ -318,9 +318,8 @@
   (l.run input lex-date))
 
 (structure: #export _
-  {#.doc "Based on ISO 8601.
-
-          For example: 2017-01-15"}
+  {#.doc (doc "Based on ISO 8601."
+              "For example: 2017-01-15")}
   (Codec Text Date)
   (def: encode encode)
   (def: decode decode))
diff --git a/stdlib/source/lux/time/instant.lux b/stdlib/source/lux/time/instant.lux
index 64d4fe172..70890ce4b 100644
--- a/stdlib/source/lux/time/instant.lux
+++ b/stdlib/source/lux/time/instant.lux
@@ -304,9 +304,8 @@
   (l.run input lex-instant))
 
 ## (structure: #export _
-##   {#.doc "Based on ISO 8601.
-
-##           For example: 2017-01-15T21:14:51.827Z"}
+##   {#.doc (doc "Based on ISO 8601."
+##               "For example: 2017-01-15T21:14:51.827Z")}
 ##   (Codec Text Instant)
 ##   (def: encode encode)
 ##   (def: decode decode))
-- 
cgit v1.2.3


From d2efa1fd37efa50a460dfa609ddd274d82d082e3 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 22:13:21 -0400
Subject: Partial implementation of text-escaping.

---
 stdlib/source/lux/compiler/default/syntax.lux | 491 +++++++++++++++-----------
 1 file changed, 283 insertions(+), 208 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 3b3b3e411..f333917d8 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -50,35 +50,6 @@
 (type: #export Syntax
   (-> Cursor (Lexer [Cursor Code])))
 
-(def: (timed' description lexer)
-  (All [a]
-    (-> Text (Lexer a) (Lexer a)))
-  (do p.Monad
-    [_ (wrap [])
-     #let [pre (io.run instant.now)]
-     output lexer
-     #let [_ (log! (|> instant.now
-                       io.run
-                       instant.relative
-                       (duration.difference (instant.relative pre))
-                       %duration
-                       (format "[" description "]: ")))]]
-    (wrap output)))
-
-(def: (timed description lexer)
-  (-> Text (Lexer [Cursor Code]) (Lexer [Cursor Code]))
-  (do p.Monad
-    [_ (wrap [])
-     #let [pre (io.run instant.now)]
-     [where output] lexer
-     #let [_ (log! (|> instant.now
-                       io.run
-                       instant.relative
-                       (duration.difference (instant.relative pre))
-                       %duration
-                       (format (%code output) " [" description "]: ")))]]
-    (wrap [where output])))
-
 (type: #export Aliases (Dictionary Text Text))
 (def: #export no-aliases Aliases (dictionary.new text.Hash))
 
@@ -90,10 +61,10 @@
 (def: white-space " ")
 (def: carriage-return "\r")
 (def: new-line "\n")
-(def: new-line^ (l.this new-line))
+## (def: new-line^ (l.this new-line))
 
 (def: text-delimiter "\"")
-(def: text-delimiter^ (l.this text-delimiter))
+## (def: text-delimiter^ (l.this text-delimiter))
 
 (def: open-form "(")
 (def: close-form ")")
@@ -112,50 +83,50 @@
 
 (def: single-line-comment-marker (format ..sigil ..sigil))
 
-## This is the parser for white-space.
-## Whenever a new-line is encountered, the column gets reset to 0, and
-## the line gets incremented.
-## It operates recursively in order to produce the longest continuous
-## chunk of white-space.
-(def: (space^ where)
-  (-> Cursor (Lexer Cursor))
-  (p.either (do p.Monad
-              [content (l.many! (l.one-of! white-space))]
-              (wrap (update@ #.column (n/+ (get@ #l.distance content)) where)))
-            ## New-lines must be handled as a separate case to ensure line
-            ## information is handled properly.
-            (do p.Monad
-              [content (l.many! (l.one-of! new-line))]
-              (wrap (|> where
-                        (update@ #.line (n/+ (get@ #l.distance content)))
-                        (set@ #.column 0))))))
-
-## Single-line comments can start anywhere, but only go up to the
-## next new-line.
-(def: (comment^ where)
-  (-> Cursor (Lexer Cursor))
-  (do p.Monad
-    [_ (l.this ..single-line-comment-marker)
-     _ (l.some! (l.none-of! new-line))
-     _ ..new-line^]
-    (wrap (|> where
-              (update@ #.line inc)
-              (set@ #.column 0)))))
-
-## To simplify parsing, I remove any left-padding that a Code token
-## may have prior to parsing the token itself.
-## Left-padding is assumed to be either white-space or a comment.
-## The cursor gets updated, but the padding gets ignored.
-(def: (left-padding^ where)
-  (-> Cursor (Lexer Cursor))
-  ($_ p.either
-      (do p.Monad
-        [where (comment^ where)]
-        (left-padding^ where))
-      (do p.Monad
-        [where (space^ where)]
-        (left-padding^ where))
-      (:: p.Monad wrap where)))
+## ## This is the parser for white-space.
+## ## Whenever a new-line is encountered, the column gets reset to 0, and
+## ## the line gets incremented.
+## ## It operates recursively in order to produce the longest continuous
+## ## chunk of white-space.
+## (def: (space^ where)
+##   (-> Cursor (Lexer Cursor))
+##   (p.either (do p.Monad
+##               [content (l.many! (l.one-of! white-space))]
+##               (wrap (update@ #.column (n/+ (get@ #l.distance content)) where)))
+##             ## New-lines must be handled as a separate case to ensure line
+##             ## information is handled properly.
+##             (do p.Monad
+##               [content (l.many! (l.one-of! new-line))]
+##               (wrap (|> where
+##                         (update@ #.line (n/+ (get@ #l.distance content)))
+##                         (set@ #.column 0))))))
+
+## ## Single-line comments can start anywhere, but only go up to the
+## ## next new-line.
+## (def: (comment^ where)
+##   (-> Cursor (Lexer Cursor))
+##   (do p.Monad
+##     [_ (l.this ..single-line-comment-marker)
+##      _ (l.some! (l.none-of! new-line))
+##      _ ..new-line^]
+##     (wrap (|> where
+##               (update@ #.line inc)
+##               (set@ #.column 0)))))
+
+## ## To simplify parsing, I remove any left-padding that a Code token
+## ## may have prior to parsing the token itself.
+## ## Left-padding is assumed to be either white-space or a comment.
+## ## The cursor gets updated, but the padding gets ignored.
+## (def: (left-padding^ where)
+##   (-> Cursor (Lexer Cursor))
+##   ($_ p.either
+##       (do p.Monad
+##         [where (comment^ where)]
+##         (left-padding^ where))
+##       (do p.Monad
+##         [where (space^ where)]
+##         (left-padding^ where))
+##       (:: p.Monad wrap where)))
 
 ## Escaped character sequences follow the usual syntax of
 ## back-slash followed by a letter (e.g. \n).
@@ -263,78 +234,78 @@
       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
              [where (#.Frac value)]]))))
 
-## This parser looks so complex because text in Lux can be multi-line
-## and there are rules regarding how this is handled.
-(def: #export (text where)
-  Syntax
-  (do p.Monad
-    [## Lux text "is delimited by double-quotes", as usual in most
-     ## programming languages.
-     _ ..text-delimiter^
-     ## I must know what column the text body starts at (which is
-     ## always 1 column after the left-delimiting quote).
-     ## This is important because, when procesing subsequent lines,
-     ## they must all start at the same column, being left-padded with
-     ## as many spaces as necessary to be column-aligned.
-     ## This helps ensure that the formatting on the text in the
-     ## source-code matches the formatting of the Text value.
-     #let [offset ("lux i64 +" 1 (get@ #.column where))]
-     [where' text-read] (: (Lexer [Cursor Text])
-                           ## I must keep track of how much of the
-                           ## text body has been read, how far the
-                           ## cursor has progressed, and whether I'm
-                           ## processing a subsequent line, or just
-                           ## processing normal text body.
-                           (loop [text-read ""
-                                  where (|> where
-                                            (update@ #.column inc))
-                                  must-have-offset? #0]
-                             (p.either (if must-have-offset?
-                                         ## If I'm at the start of a
-                                         ## new line, I must ensure the
-                                         ## space-offset is at least
-                                         ## as great as the column of
-                                         ## the text's body's column,
-                                         ## to ensure they are aligned.
-                                         (do @
-                                           [_ (p.exactly offset (l.this ..white-space))]
-                                           (recur text-read
-                                                  (update@ #.column (n/+ offset) where)
-                                                  #0))
-                                         ($_ p.either
-                                             ## Normal text characters.
-                                             (do @
-                                               [normal (l.slice (l.many! (l.none-of! (format ..escape ..text-delimiter ..new-line))))]
-                                               (recur (format text-read normal)
-                                                      (update@ #.column (n/+ (text.size normal)) where)
-                                                      #0))
-                                             ## Must handle escaped
-                                             ## chars separately.
-                                             (do @
-                                               [[chars-consumed char] escaped-char^]
-                                               (recur (format text-read char)
-                                                      (update@ #.column (n/+ chars-consumed) where)
-                                                      #0))
-                                             ## The text ends when it
-                                             ## reaches the right-delimiter.
-                                             (do @
-                                               [_ ..text-delimiter^]
-                                               (wrap [(update@ #.column inc where)
-                                                      text-read]))))
-                                       ## If a new-line is
-                                       ## encountered, it gets
-                                       ## appended to the value and
-                                       ## the loop is alerted that the
-                                       ## next line must have an offset.
-                                       (do @
-                                         [_ ..new-line^]
-                                         (recur (format text-read new-line)
-                                                (|> where
-                                                    (update@ #.line inc)
-                                                    (set@ #.column 0))
-                                                #1)))))]
-    (wrap [where'
-           [where (#.Text text-read)]])))
+## ## This parser looks so complex because text in Lux can be multi-line
+## ## and there are rules regarding how this is handled.
+## (def: #export (text where)
+##   Syntax
+##   (do p.Monad
+##     [## Lux text "is delimited by double-quotes", as usual in most
+##      ## programming languages.
+##      _ ..text-delimiter^
+##      ## I must know what column the text body starts at (which is
+##      ## always 1 column after the left-delimiting quote).
+##      ## This is important because, when procesing subsequent lines,
+##      ## they must all start at the same column, being left-padded with
+##      ## as many spaces as necessary to be column-aligned.
+##      ## This helps ensure that the formatting on the text in the
+##      ## source-code matches the formatting of the Text value.
+##      #let [offset ("lux i64 +" 1 (get@ #.column where))]
+##      [where' text-read] (: (Lexer [Cursor Text])
+##                            ## I must keep track of how much of the
+##                            ## text body has been read, how far the
+##                            ## cursor has progressed, and whether I'm
+##                            ## processing a subsequent line, or just
+##                            ## processing normal text body.
+##                            (loop [text-read ""
+##                                   where (|> where
+##                                             (update@ #.column inc))
+##                                   must-have-offset? #0]
+##                              (p.either (if must-have-offset?
+##                                          ## If I'm at the start of a
+##                                          ## new line, I must ensure the
+##                                          ## space-offset is at least
+##                                          ## as great as the column of
+##                                          ## the text's body's column,
+##                                          ## to ensure they are aligned.
+##                                          (do @
+##                                            [_ (p.exactly offset (l.this ..white-space))]
+##                                            (recur text-read
+##                                                   (update@ #.column (n/+ offset) where)
+##                                                   #0))
+##                                          ($_ p.either
+##                                              ## Normal text characters.
+##                                              (do @
+##                                                [normal (l.slice (l.many! (l.none-of! (format ..escape ..text-delimiter ..new-line))))]
+##                                                (recur (format text-read normal)
+##                                                       (update@ #.column (n/+ (text.size normal)) where)
+##                                                       #0))
+##                                              ## Must handle escaped
+##                                              ## chars separately.
+##                                              (do @
+##                                                [[chars-consumed char] escaped-char^]
+##                                                (recur (format text-read char)
+##                                                       (update@ #.column (n/+ chars-consumed) where)
+##                                                       #0))
+##                                              ## The text ends when it
+##                                              ## reaches the right-delimiter.
+##                                              (do @
+##                                                [_ ..text-delimiter^]
+##                                                (wrap [(update@ #.column inc where)
+##                                                       text-read]))))
+##                                        ## If a new-line is
+##                                        ## encountered, it gets
+##                                        ## appended to the value and
+##                                        ## the loop is alerted that the
+##                                        ## next line must have an offset.
+##                                        (do @
+##                                          [_ ..new-line^]
+##                                          (recur (format text-read new-line)
+##                                                 (|> where
+##                                                     (update@ #.line inc)
+##                                                     (set@ #.column 0))
+##                                                 #1)))))]
+##     (wrap [where'
+##            [where (#.Text text-read)]])))
 
 (def: (composite open close element)
   (All [a]
@@ -347,23 +318,20 @@
       (do p.Monad
         [_ open^]
         (loop [where (update@ #.column inc where)]
-          (p.either (<| (timed' "composite CONS")
-                        (do @
-                          [## Must update the cursor as I
-                           ## go along, to keep things accurate.
-                           [where' head] (<| (timed' "composite HEAD")
-                                             (element where))]
-                          (parser/map (product.both id (|>> (#.Cons head)))
-                                      (recur where'))))
-                    (<| (timed' "composite NIL")
-                        (do @
-                          [## Must take into account any
-                           ## padding present before the
-                           ## end-delimiter.
-                           where' (left-padding^ where)
-                           _ close^]
-                          (wrap [(update@ #.column inc where')
-                                 #.Nil])))))))))
+          (p.either (do @
+                      [## Must update the cursor as I
+                       ## go along, to keep things accurate.
+                       [where' head] (element where)]
+                      (parser/map (product.both id (|>> (#.Cons head)))
+                                  (recur where')))
+                    (do @
+                      [## Must take into account any
+                       ## padding present before the
+                       ## end-delimiter.
+                       ## where (left-padding^ where)
+                       _ close^]
+                      (wrap [(update@ #.column inc where)
+                             #.Nil]))))))))
 
 ## (do-template [   ]
 ##   [(def: ( ast where)
@@ -516,34 +484,30 @@
              ["Line" (%n line)]
              ["Column" (%n column)]))
 
+(exception: #export (text-cannot-contain-new-lines {text Text})
+  (ex.report ["Text" (%t text)]))
+
+(exception: #export (invalid-escape-syntax)
+  "")
+
 (def: (ast current-module aliases)
   (-> Text Aliases Syntax)
   (function (ast' where)
     (do p.Monad
-      [where (left-padding^ where)]
+      [## where (left-padding^ where)
+       ]
       ($_ p.either
-          ## (<| (..timed "bit")
-          ##     (..bit where))
-          ## (<| (..timed "nat")
-          ##     (..nat where))
-          (<| (..timed "frac")
-              (..frac where))
-          (<| (..timed "rev")
-              (..rev where))
-          (<| (..timed "int")
-              (..int where))
-          (<| (..timed "text")
-              (..text where))
-          ## (<| (..timed "identifier")
-          ##     (..identifier current-module aliases where))
-          ## (<| (..timed "tag")
-          ##     (..tag current-module aliases where))
-          ## (<| (..timed "form")
-          ##     (..form ast' where))
-          ## (<| (..timed "tuple")
-          ##     (..tuple ast' where))
-          (<| (..timed "record")
-              (..record ast' where))
+          ## (..bit where)
+          ## (..nat where)
+          (..frac where)
+          (..rev where)
+          (..int where)
+          ## (..text where)
+          ## (..identifier current-module aliases where)
+          ## (..tag current-module aliases where)
+          ## (..form ast' where)
+          ## (..tuple ast' where)
+          (..record ast' where)
           (do @
             [end? l.end?]
             (if end?
@@ -552,11 +516,11 @@
           ))))
 
 (type: Tracker
-  {#new-line Offset})
+  {#next-escape Offset})
 
 (def: fresh-tracker
   Tracker
-  {#new-line 0})
+  {#next-escape 0})
 
 (type: (Simple a)
   (-> Tracker Source (Error [Tracker Source a])))
@@ -609,29 +573,142 @@
   )
 
 (template: (!clip from to text)
-  ## TODO: Optimize away "maybe.assume"
+  ## TODO: Optimize-away "maybe.assume"
   (maybe.assume ("lux text clip" text from to)))
 
-(def: (read-text tracker [where offset source-code])
+(template: (!i/< reference subject)
+  ("lux int <" subject reference))
+
+(do-template [ ]
+  [(template: ( param subject)
+     ( subject param))]
+
+  [!n/+ "lux i64 +"]
+  [!n/- "lux i64 -"]
+  )
+
+(with-expansions [ ($_ "lux text concat" total output (!clip g!post-escape end source-code))]
+  (template: (!find-next-escape diff current-escape end source-code total output)
+    (let [g!post-escape (!n/+ diff current-escape)]
+      (case ("lux text index" source-code (static ..escape) g!post-escape)
+        ## More escaping work needs to be done
+        (#.Some g!next-escape)
+        (if (!i/< (:coerce Int end)
+                  (:coerce Int g!next-escape))
+          ## For the current text.
+          (recur end g!next-escape ($_ "lux text concat" total output (!clip g!post-escape g!next-escape source-code)))
+          ## For another text.
+          (#error.Success [g!next-escape (!inc end) ]))
+
+        ## No more escaping... ever!
+        _
+        (#error.Success [("lux text size" source-code) (!inc end) ])))))
+
+(template: (!guarantee-no-new-lines content body)
+  (case ("lux text index" content (static ..new-line) 0)
+    (#.Some g!_)
+    (ex.throw ..text-cannot-contain-new-lines content)
+
+    g!_
+    body))
+
+(def: (read-escaped-text next-escape end offset source-code)
+  (-> Offset Offset Offset Text (Error [Offset Offset Text]))
+  (with-expansions [ (!n/+ 1 next-escape)
+                     (!n/+ 5 next-escape)]
+    (loop [end end
+           next-escape next-escape
+           total (!clip offset next-escape source-code)]
+      ## TODO: Optimize-away "maybe.assume"
+      (`` (case (maybe.assume ("lux text char" source-code ))
+            (^template [ ]
+              (^ (char ))
+              (!find-next-escape 2 next-escape end source-code total ))
+            (["t" "\t"]
+             ["v" "\v"]
+             ["b" "\b"]
+             ["n" (static ..new-line)]
+             ["r" "\r"]
+             ["f" "\f"]
+             [(~~ (static ..escape)) (static ..escape)])
+
+            (^ (char (~~ (static ..text-delimiter))))
+            (case (!find-next-escape 2 next-escape end source-code total (static ..text-delimiter))
+              (#error.Error error)
+              (#error.Error error)
+              
+              (#error.Success [next-escape' post-delimiter so-far])
+              (case ("lux text index" source-code (static ..text-delimiter) post-delimiter)
+                (#.Some end')
+                (recur end' next-escape' so-far)
+
+                _
+                (ex.throw invalid-escape-syntax [])))
+
+            ## Handle unicode escapes.
+            (^ (char "u"))
+            (if (!i/< (:coerce Int end)
+                      (:coerce Int ))
+              (case (:: number.Hex@Codec decode (!clip   source-code))
+                (#error.Success value)
+                (!find-next-escape 6 next-escape end source-code total (text.from-code value))
+                
+                (#error.Error error)
+                (#error.Error error))
+              (ex.throw invalid-escape-syntax []))
+
+            _
+            (ex.throw invalid-escape-syntax []))))))
+
+(def: (read-text next-escape (^@ source [where offset source-code]))
   (Simple Code)
-  (case ("lux text index" source-code (static ..text-delimiter) offset)
-    (#.Some end)
-    (#error.Success [tracker
-                     [(update@ #.column (n/+ ("lux i64 -" end offset)) where)
-                      (!inc end)
-                      source-code]
-                     [where
-                      (#.Text (!clip offset end source-code))]])
-    
-    _
-    (ex.throw unrecognized-input where)))
+  (if (!i/< (:coerce Int offset)
+            (:coerce Int next-escape))
+    ## Must update next-escape.
+    (case ("lux text index" source-code (static ..escape) offset)
+      ## There is a escape further down the road.
+      (#.Some next-escape')
+      (read-text next-escape' source)
+
+      ## There are no escapes left.
+      _
+      (read-text ("lux text size" source-code) source))
+    (case ("lux text index" source-code (static ..text-delimiter) offset)
+      (#.Some end)
+      (if (!i/< (:coerce Int end)
+                (:coerce Int next-escape))
+        ## Must handle escape
+        (case (read-escaped-text next-escape end offset source-code)
+          (#error.Error error)
+          (#error.Error error)
+
+          (#error.Success [next-escape' offset' content])
+          (<| (!guarantee-no-new-lines content)
+              (#error.Success [next-escape'
+                               [(update@ #.column (n/+ (!n/- offset offset')) where)
+                                offset'
+                                source-code]
+                               [where
+                                (#.Text content)]])))
+        ## No escape to handle at the moment.
+        (let [content (!clip offset end source-code)]
+          (<| (!guarantee-no-new-lines content)
+              (#error.Success [next-escape
+                               [(update@ #.column (n/+ (!n/- offset end)) where)
+                                (!inc end)
+                                source-code]
+                               [where
+                                (#.Text content)]]))))
+      
+      _
+      (ex.throw unrecognized-input where))))
 
 (def: digit-bottom Nat (!dec (char "0")))
 (def: digit-top Nat (!inc (char "9")))
 
 (template: (!digit? char)
-  (and ("lux int <" (:coerce Int (static ..digit-bottom)) (:coerce Int char))
-       ("lux int <" (:coerce Int char) (:coerce Int (static ..digit-top)))))
+  (and (!i/< (:coerce Int char) (:coerce Int (static ..digit-bottom)))
+       (!i/< (:coerce Int (static ..digit-top)) (:coerce Int char))))
 
 (`` (template: (!digit?+ char)
       (or (!digit? char)
@@ -666,7 +743,7 @@
 (with-expansions [ (case (:: number.Codec decode (!clip start end source-code))
                              (#error.Success output)
                              (#error.Success [tracker
-                                              [(update@ #.column (n/+ ("lux i64 -" end start)) where)
+                                              [(update@ #.column (n/+ (!n/- start end)) where)
                                                end
                                                source-code]
                                               [where (#.Nat output)]])
@@ -685,7 +762,7 @@
         _
         ))))
 
-(with-expansions [ (#error.Success [[(update@ #.column (n/+ ("lux i64 -" end start)) where)
+(with-expansions [ (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
                                              end
                                              source-code]
                                             (!clip start end source-code)])]
@@ -890,5 +967,3 @@
 
 ##     (#error.Success [[offset' remaining] [where' output]])
 ##     (#error.Success [[where' offset' remaining] output])))
-
-## (yolo)
-- 
cgit v1.2.3


From 5e13ae0ad68947249a98dc69ab513bdbeca1697e Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 22:50:33 -0400
Subject: No more escaping of horizontal-tab.

---
 stdlib/source/lux.lux                              | 12 +-----
 .../compiler/default/phase/analysis/expression.lux |  4 +-
 .../lux/compiler/default/phase/extension.lux       |  6 ++-
 .../default/phase/extension/analysis/host.jvm.lux  |  2 +-
 stdlib/source/lux/compiler/default/syntax.lux      |  4 +-
 stdlib/source/lux/data/collection/list.lux         | 12 +++---
 stdlib/source/lux/data/format/json.lux             | 21 ++++++----
 stdlib/source/lux/data/text.lux                    | 47 +++++++++++++---------
 stdlib/source/lux/data/text/regex.lux              | 20 ++++-----
 stdlib/source/lux/host.jvm.lux                     |  2 +-
 stdlib/test/test/lux/compiler/default/syntax.lux   |  2 +-
 stdlib/test/test/lux/data/text/regex.lux           |  6 +--
 12 files changed, 71 insertions(+), 67 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 1b64aa22b..5ffe8d939 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -5154,17 +5154,7 @@
 
 (def: (text/encode original)
   (-> Text Text)
-  (let [escaped (|> original
-                    (replace-all "\t" "\\t")
-                    (replace-all "\v" "\\v")
-                    (replace-all "\b" "\\b")
-                    (replace-all "\n" "\\n")
-                    (replace-all "\r" "\\r")
-                    (replace-all "\f" "\\f")
-                    (replace-all "\"" "\\\"")
-                    (replace-all "\\" "\\\\")
-                    )]
-    ($_ text/compose "\"" escaped "\"")))
+  ($_ text/compose "\"" original "\""))
 
 (do-template [  ]
   [(def: #export ( value)
diff --git a/stdlib/source/lux/compiler/default/phase/analysis/expression.lux b/stdlib/source/lux/compiler/default/phase/analysis/expression.lux
index ed2f81735..073cc9950 100644
--- a/stdlib/source/lux/compiler/default/phase/analysis/expression.lux
+++ b/stdlib/source/lux/compiler/default/phase/analysis/expression.lux
@@ -26,14 +26,14 @@
 (exception: #export (macro-expansion-failed {macro Name} {inputs (List Code)} {error Text})
   (ex.report ["Macro" (%name macro)]
              ["Inputs" (|> inputs
-                           (list/map (|>> %code (format "\n\t")))
+                           (list/map (|>> %code (format "\n" text.tab)))
                            (text.join-with ""))]
              ["Error" error]))
 
 (exception: #export (macro-call-must-have-single-expansion {macro Name} {inputs (List Code)})
   (ex.report ["Macro" (%name macro)]
              ["Inputs" (|> inputs
-                           (list/map (|>> %code (format "\n\t")))
+                           (list/map (|>> %code (format "\n" text.tab)))
                            (text.join-with ""))]))
 
 (exception: #export (unrecognized-syntax {code Code})
diff --git a/stdlib/source/lux/compiler/default/phase/extension.lux b/stdlib/source/lux/compiler/default/phase/extension.lux
index 38ca02700..c7a2048a8 100644
--- a/stdlib/source/lux/compiler/default/phase/extension.lux
+++ b/stdlib/source/lux/compiler/default/phase/extension.lux
@@ -49,7 +49,7 @@
              ["Available" (|> bundle
                               dictionary.keys
                               (list.sort text/<)
-                              (list/map (|>> %t (format "\n\t")))
+                              (list/map (|>> %t (format "\n" text.tab)))
                               (text.join-with ""))]))
 
 (exception: #export (incorrect-arity {name Text} {arity Nat} {args Nat})
@@ -75,7 +75,9 @@
       (ex.throw unknown [where name bundle])
       
       (#.Some handler)
-      ((handler name phase) parameters stateE))))
+      ((<| (//.timed (name-of ..apply) (%t name))
+           ((handler name phase) parameters))
+       stateE))))
 
 (def: #export (localized get set transform)
   (All [s s' i o v]
diff --git a/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux b/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux
index 5406ac20a..31f4b33ff 100644
--- a/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux
+++ b/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux
@@ -95,7 +95,7 @@
      (ex.report ["Class" class]
                 ["Method" method]
                 ["Hints" (|> hints
-                             (list/map (|>> product.left %type (format "\n\t")))
+                             (list/map (|>> product.left %type (format "\n" text.tab)))
                              (text.join-with ""))]))]
 
   [no-candidates]
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index f333917d8..2aaa46992 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -140,7 +140,6 @@
              [code l.any]
              (case code
                ## Handle special cases.
-               "t" (wrap [2 "\t"])
                "v" (wrap [2 "\v"])
                "b" (wrap [2 "\b"])
                "n" (wrap [2 ..new-line])
@@ -624,8 +623,7 @@
             (^template [ ]
               (^ (char ))
               (!find-next-escape 2 next-escape end source-code total ))
-            (["t" "\t"]
-             ["v" "\v"]
+            (["v" "\v"]
              ["b" "\b"]
              ["n" (static ..new-line)]
              ["r" "\r"]
diff --git a/stdlib/source/lux/data/collection/list.lux b/stdlib/source/lux/data/collection/list.lux
index ef1ebf5ac..c49a7ba9f 100644
--- a/stdlib/source/lux/data/collection/list.lux
+++ b/stdlib/source/lux/data/collection/list.lux
@@ -435,8 +435,8 @@
                                      (identifier$ ("lux text concat" base "'"))]))))
             pattern (` [(~+ (map (function (_ [v vs]) (` (#.Cons (~ v) (~ vs))))
                                  vars+lists))])
-            g!step (identifier$ "\tstep\t")
-            g!blank (identifier$ "\t_\t")
+            g!step (identifier$ "0step0")
+            g!blank (identifier$ "0_0")
             list-vars (map product.right vars+lists)
             code (` (: (~ zip-type)
                        (function ((~ g!step) (~+ list-vars))
@@ -466,8 +466,8 @@
     (if (n/> 0 num-lists)
       (let [(^open ".") Functor
             indices (..indices num-lists)
-            g!return-type (identifier$ "\treturn-type\t")
-            g!func (identifier$ "\tfunc\t")
+            g!return-type (identifier$ "0return-type0")
+            g!func (identifier$ "0func0")
             type-vars (: (List Code) (map (|>> nat/encode identifier$) indices))
             zip-type (` (All [(~+ type-vars) (~ g!return-type)]
                           (-> (-> (~+ type-vars) (~ g!return-type))
@@ -482,8 +482,8 @@
                                      (identifier$ ("lux text concat" base "'"))]))))
             pattern (` [(~+ (map (function (_ [v vs]) (` (#.Cons (~ v) (~ vs))))
                                  vars+lists))])
-            g!step (identifier$ "\tstep\t")
-            g!blank (identifier$ "\t_\t")
+            g!step (identifier$ "0step0")
+            g!blank (identifier$ "0_0")
             list-vars (map product.right vars+lists)
             code (` (: (~ zip-type)
                        (function ((~ g!step) (~ g!func) (~+ list-vars))
diff --git a/stdlib/source/lux/data/format/json.lux b/stdlib/source/lux/data/format/json.lux
index c26df1893..1d0837b90 100644
--- a/stdlib/source/lux/data/format/json.lux
+++ b/stdlib/source/lux/data/format/json.lux
@@ -452,13 +452,20 @@
 (def: escaped~
   (l.Lexer Text)
   ($_ p.either
-      (p.after (l.this "\\t") (parser/wrap "\t"))
-      (p.after (l.this "\\b") (parser/wrap "\b"))
-      (p.after (l.this "\\n") (parser/wrap "\n"))
-      (p.after (l.this "\\r") (parser/wrap "\r"))
-      (p.after (l.this "\\f") (parser/wrap "\f"))
-      (p.after (l.this "\\\"") (parser/wrap "\""))
-      (p.after (l.this "\\\\") (parser/wrap "\\"))))
+      (p.after (l.this "\\t")
+               (parser/wrap text.tab))
+      (p.after (l.this "\\b")
+               (parser/wrap text.back-space))
+      (p.after (l.this "\\n")
+               (parser/wrap text.new-line))
+      (p.after (l.this "\\r")
+               (parser/wrap text.carriage-return))
+      (p.after (l.this "\\f")
+               (parser/wrap text.form-feed))
+      (p.after (l.this (text/compose "\\" text.double-quote))
+               (parser/wrap text.double-quote))
+      (p.after (l.this "\\\\")
+               (parser/wrap "\\"))))
 
 (def: string~
   (l.Lexer String)
diff --git a/stdlib/source/lux/data/text.lux b/stdlib/source/lux/data/text.lux
index 48f35febe..0c6a5ea45 100644
--- a/stdlib/source/lux/data/text.lux
+++ b/stdlib/source/lux/data/text.lux
@@ -216,30 +216,37 @@
   (-> Text Text Text)
   (enclose [boundary boundary] content))
 
-(def: #export encode
-  (-> Text Text)
-  (|>> (replace-all "\\" "\\\\")
-       (replace-all "\t" "\\t")
-       (replace-all "\v" "\\v")
-       (replace-all "\b" "\\b")
-       (replace-all "\n" "\\n")
-       (replace-all "\r" "\\r")
-       (replace-all "\f" "\\f")
-       (replace-all "\"" "\\\"")
-       (..enclose' "\"")))
-
 (def: #export from-code
   (-> Nat Text)
   (|>> (:coerce Int) "lux int char"))
 
+(do-template [ ]
+  [(def: #export  (from-code ))]
+
+  [back-space 8]
+  [tab 9]
+  [new-line 10]
+  [vertical-tab 11]
+  [form-feed 12]
+  [carriage-return 13]
+  [double-quote 34]
+  )
+
+(def: #export encode
+  (-> Text Text)
+  (..enclose' ..double-quote))
+
 (def: #export (space? char)
   {#.doc "Checks whether the character is white-space."}
   (-> Nat Bit)
-  (case char
-    (^or (^ (char "\t")) (^ (char "\v"))
-         (^ (char " "))  (^ (char "\n"))
-         (^ (char "\r")) (^ (char "\f")))
-    #1
-
-    _
-    #0))
+  (`` (case char
+        (^or (^ (char (~~ (static ..tab))))
+             (^ (char (~~ (static ..vertical-tab))))
+             (^ (char " "))
+             (^ (char (~~ (static ..new-line))))
+             (^ (char (~~ (static ..carriage-return))))
+             (^ (char (~~ (static ..form-feed)))))
+        #1
+
+        _
+        #0)))
diff --git a/stdlib/source/lux/data/text/regex.lux b/stdlib/source/lux/data/text/regex.lux
index ffd937d8e..a5409438e 100644
--- a/stdlib/source/lux/data/text/regex.lux
+++ b/stdlib/source/lux/data/text/regex.lux
@@ -8,14 +8,14 @@
     ["e" error]
     ["." maybe]
     ["." number ("int/." Codec)]
-    ["." text
-     ["l" lexer]
-     format]
     [collection
      ["." list ("list/." Fold Monad)]]]
    ["." macro (#+ with-gensyms)
     ["." code]
-    ["s" syntax (#+ syntax:)]]])
+    ["s" syntax (#+ syntax:)]]]
+  ["." //
+   ["l" lexer]
+   format])
 
 ## [Utils]
 (def: regex-char^
@@ -50,7 +50,7 @@
   (-> (l.Lexer (List Text)) (l.Lexer Text))
   (do p.Monad
     [parts part^]
-    (wrap (text.join-with "" parts))))
+    (wrap (//.join-with "" parts))))
 
 (def: name-char^
   (l.Lexer Text)
@@ -81,9 +81,9 @@
 (def: re-range^
   (l.Lexer Code)
   (do p.Monad
-    [from (|> regex-char^ (:: @ map (|>> (text.nth 0) maybe.assume)))
+    [from (|> regex-char^ (:: @ map (|>> (//.nth 0) maybe.assume)))
      _ (l.this "-")
-     to (|> regex-char^ (:: @ map (|>> (text.nth 0) maybe.assume)))]
+     to (|> regex-char^ (:: @ map (|>> (//.nth 0) maybe.assume)))]
     (wrap (` (l.range (~ (code.nat from)) (~ (code.nat to)))))))
 
 (def: re-char^
@@ -122,7 +122,7 @@
 
 (def: blank^
   (l.Lexer Text)
-  (l.one-of " \t"))
+  (l.one-of (format " " //.tab)))
 
 (def: ascii^
   (l.Lexer Text)
@@ -278,7 +278,7 @@
                                              [idx
                                               names
                                               (list& (list g!temp complex
-                                                           (' #let) (` [(~ g!total) (:: (~! text.Monoid) (~' compose) (~ g!total) (~ g!temp))]))
+                                                           (' #let) (` [(~ g!total) (:: (~! //.Monoid) (~' compose) (~ g!total) (~ g!temp))]))
                                                      steps)]
                                              
                                              (#.Right [(#Capturing [?name num-captures]) scoped])
@@ -294,7 +294,7 @@
                                                [idx!
                                                 (list& name! names)
                                                 (list& (list name! scoped
-                                                             (' #let) (` [(~ g!total) (:: (~! text.Monoid) (~' compose) (~ g!total) (~ access))]))
+                                                             (' #let) (` [(~ g!total) (:: (~! //.Monoid) (~' compose) (~ g!total) (~ access))]))
                                                        steps)])
                                              )))
                                       [+0
diff --git a/stdlib/source/lux/host.jvm.lux b/stdlib/source/lux/host.jvm.lux
index b7a55dfaa..9bb839aec 100644
--- a/stdlib/source/lux/host.jvm.lux
+++ b/stdlib/source/lux/host.jvm.lux
@@ -1088,7 +1088,7 @@
 
 (def: (annotation$ [name params])
   (-> Annotation JVM-Code)
-  (format "(" name " " "{" (text.join-with "\t" (list/map annotation-param$ params)) "}" ")"))
+  (format "(" name " " "{" (text.join-with text.tab (list/map annotation-param$ params)) "}" ")"))
 
 (def: (bound-kind$ kind)
   (-> BoundKind JVM-Code)
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index 1bcb9dad8..6a447e9c1 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -30,7 +30,7 @@
   (do r.Monad
     [#let [digits "0123456789"
            delimiters "()[]{}#.\""
-           space "\t\v \n\r\f"
+           space "\v \n\r\f"
            invalid-range (format digits delimiters space)
            char-gen (|> r.nat
                         (:: @ map (|>> (n/% 256) (n/max 1)))
diff --git a/stdlib/test/test/lux/data/text/regex.lux b/stdlib/test/test/lux/data/text/regex.lux
index 96f56c3d9..7a6e88d33 100644
--- a/stdlib/test/test/lux/data/text/regex.lux
+++ b/stdlib/test/test/lux/data/text/regex.lux
@@ -5,7 +5,7 @@
     pipe
     ["p" parser]]
    [data
-    [text ("text/." Equivalence)
+    ["." text ("text/." Equivalence)
      format
      ["." lexer (#+ Lexer)]
      ["&" regex]]]
@@ -117,10 +117,10 @@
                  (and (should-pass (&.regex "\\p{OctDigit}") "6")
                       (should-fail (&.regex "\\p{OctDigit}") "."))
 
-                 (and (should-pass (&.regex "\\p{Blank}") "\t")
+                 (and (should-pass (&.regex "\\p{Blank}") text.tab)
                       (should-fail (&.regex "\\p{Blank}") "."))
 
-                 (and (should-pass (&.regex "\\p{ASCII}") "\t")
+                 (and (should-pass (&.regex "\\p{ASCII}") text.tab)
                       (should-fail (&.regex "\\p{ASCII}") "\u1234"))
 
                  (and (should-pass (&.regex "\\p{Contrl}") "\u0012")
-- 
cgit v1.2.3


From bf893b3aa2b43c11b1cbb95fb8641f6ae6aa06b0 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 22:53:11 -0400
Subject: No more escaping of back-space.

---
 stdlib/source/lux/compiler/default/syntax.lux | 2 --
 1 file changed, 2 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 2aaa46992..1d1572859 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -141,7 +141,6 @@
              (case code
                ## Handle special cases.
                "v" (wrap [2 "\v"])
-               "b" (wrap [2 "\b"])
                "n" (wrap [2 ..new-line])
                "r" (wrap [2 "\r"])
                "f" (wrap [2 "\f"])
@@ -624,7 +623,6 @@
               (^ (char ))
               (!find-next-escape 2 next-escape end source-code total ))
             (["v" "\v"]
-             ["b" "\b"]
              ["n" (static ..new-line)]
              ["r" "\r"]
              ["f" "\f"]
-- 
cgit v1.2.3


From 533864f86be183cbbb7c11516910acf711d281f4 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 22:54:59 -0400
Subject: No more escaping of form-feed.

---
 stdlib/source/lux/compiler/default/syntax.lux    | 2 --
 stdlib/test/test/lux/compiler/default/syntax.lux | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 1d1572859..aa77be1e5 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -143,7 +143,6 @@
                "v" (wrap [2 "\v"])
                "n" (wrap [2 ..new-line])
                "r" (wrap [2 "\r"])
-               "f" (wrap [2 "\f"])
                (^ (static ..text-delimiter)) (wrap [2 ..text-delimiter])
                (^ (static ..escape)) (wrap [2 ..escape])
 
@@ -625,7 +624,6 @@
             (["v" "\v"]
              ["n" (static ..new-line)]
              ["r" "\r"]
-             ["f" "\f"]
              [(~~ (static ..escape)) (static ..escape)])
 
             (^ (char (~~ (static ..text-delimiter))))
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index 6a447e9c1..e8b5bb5b4 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -30,7 +30,7 @@
   (do r.Monad
     [#let [digits "0123456789"
            delimiters "()[]{}#.\""
-           space "\v \n\r\f"
+           space "\v \n\r"
            invalid-range (format digits delimiters space)
            char-gen (|> r.nat
                         (:: @ map (|>> (n/% 256) (n/max 1)))
-- 
cgit v1.2.3


From f4f1d14416770cc223676a7d89ed15a11222ef1b Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 22:56:56 -0400
Subject: No more escaping of carriage-return.

---
 stdlib/source/lux/compiler/default/syntax.lux    | 5 +----
 stdlib/test/test/lux/compiler/default/syntax.lux | 2 +-
 2 files changed, 2 insertions(+), 5 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index aa77be1e5..06672b2aa 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -59,7 +59,6 @@
 (def: digits+ (format "_" ..digits))
 
 (def: white-space " ")
-(def: carriage-return "\r")
 (def: new-line "\n")
 ## (def: new-line^ (l.this new-line))
 
@@ -142,7 +141,6 @@
                ## Handle special cases.
                "v" (wrap [2 "\v"])
                "n" (wrap [2 ..new-line])
-               "r" (wrap [2 "\r"])
                (^ (static ..text-delimiter)) (wrap [2 ..text-delimiter])
                (^ (static ..escape)) (wrap [2 ..escape])
 
@@ -623,7 +621,6 @@
               (!find-next-escape 2 next-escape end source-code total ))
             (["v" "\v"]
              ["n" (static ..new-line)]
-             ["r" "\r"]
              [(~~ (static ..escape)) (static ..escape)])
 
             (^ (char (~~ (static ..text-delimiter))))
@@ -878,7 +875,7 @@
                             (!inc offset)
                             source-code]))
                   ([(~~ (static ..white-space))     #.column]
-                   [(~~ (static ..carriage-return)) #.column])
+                   [(~~ (static text.carriage-return)) #.column])
 
                   (^ (char (~~ (static ..new-line))))
                   (recur tracker [(!new-line where) (!inc offset) source-code])
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index e8b5bb5b4..14de95b52 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -30,7 +30,7 @@
   (do r.Monad
     [#let [digits "0123456789"
            delimiters "()[]{}#.\""
-           space "\v \n\r"
+           space "\v \n"
            invalid-range (format digits delimiters space)
            char-gen (|> r.nat
                         (:: @ map (|>> (n/% 256) (n/max 1)))
-- 
cgit v1.2.3


From 79c2988c1b514657cc384070e66539e51e105987 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 22:59:20 -0400
Subject: No more escaping of vertical-tab.

---
 stdlib/source/lux/compiler/default/syntax.lux    | 4 +---
 stdlib/test/test/lux/compiler/default/syntax.lux | 2 +-
 2 files changed, 2 insertions(+), 4 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 06672b2aa..89087d482 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -139,7 +139,6 @@
              [code l.any]
              (case code
                ## Handle special cases.
-               "v" (wrap [2 "\v"])
                "n" (wrap [2 ..new-line])
                (^ (static ..text-delimiter)) (wrap [2 ..text-delimiter])
                (^ (static ..escape)) (wrap [2 ..escape])
@@ -619,8 +618,7 @@
             (^template [ ]
               (^ (char ))
               (!find-next-escape 2 next-escape end source-code total ))
-            (["v" "\v"]
-             ["n" (static ..new-line)]
+            (["n" (static ..new-line)]
              [(~~ (static ..escape)) (static ..escape)])
 
             (^ (char (~~ (static ..text-delimiter))))
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index 14de95b52..5ac8e16da 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -30,7 +30,7 @@
   (do r.Monad
     [#let [digits "0123456789"
            delimiters "()[]{}#.\""
-           space "\v \n"
+           space " \n"
            invalid-range (format digits delimiters space)
            char-gen (|> r.nat
                         (:: @ map (|>> (n/% 256) (n/max 1)))
-- 
cgit v1.2.3


From 324665cef68fa326d358733d36ed20feba5dbbd6 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Wed, 22 Aug 2018 23:25:04 -0400
Subject: No more escaping of unicode.

---
 stdlib/source/lux/compiler/default/syntax.lux | 25 -------------------------
 stdlib/source/lux/data/text/regex.lux         | 10 +++++-----
 stdlib/source/lux/macro/poly.lux              |  4 ++--
 stdlib/test/test/lux/data/text/regex.lux      |  9 +++++----
 stdlib/test/test/lux/math/logic/fuzzy.lux     |  8 ++++----
 5 files changed, 16 insertions(+), 40 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 89087d482..dc22de5d0 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -129,8 +129,6 @@
 
 ## Escaped character sequences follow the usual syntax of
 ## back-slash followed by a letter (e.g. \n).
-## Unicode escapes are possible, with hexadecimal sequences between 1
-## and 4 characters long (e.g. \u12aB).
 ## Escaped characters may show up in Char and Text literals.
 (def: escaped-char^
   (Lexer [Nat Text])
@@ -143,17 +141,6 @@
                (^ (static ..text-delimiter)) (wrap [2 ..text-delimiter])
                (^ (static ..escape)) (wrap [2 ..escape])
 
-               ## Handle unicode escapes.
-               "u"
-               (do p.Monad
-                 [code (l.between 1 4 l.hexadecimal)]
-                 (wrap (case (:: number.Hex@Codec decode code)
-                         (#.Right value)
-                         [("lux i64 +" 2 (text.size code)) (text.from-code value)]
-
-                         _
-                         (undefined))))
-
                _
                (p.fail (format "Invalid escaping syntax: " (%t code)))))))
 
@@ -634,18 +621,6 @@
                 _
                 (ex.throw invalid-escape-syntax [])))
 
-            ## Handle unicode escapes.
-            (^ (char "u"))
-            (if (!i/< (:coerce Int end)
-                      (:coerce Int ))
-              (case (:: number.Hex@Codec decode (!clip   source-code))
-                (#error.Success value)
-                (!find-next-escape 6 next-escape end source-code total (text.from-code value))
-                
-                (#error.Error error)
-                (#error.Error error))
-              (ex.throw invalid-escape-syntax []))
-
             _
             (ex.throw invalid-escape-syntax []))))))
 
diff --git a/stdlib/source/lux/data/text/regex.lux b/stdlib/source/lux/data/text/regex.lux
index a5409438e..e491873dc 100644
--- a/stdlib/source/lux/data/text/regex.lux
+++ b/stdlib/source/lux/data/text/regex.lux
@@ -7,7 +7,7 @@
     ["." product]
     ["e" error]
     ["." maybe]
-    ["." number ("int/." Codec)]
+    ["." number (#+ hex) ("int/." Codec)]
     [collection
      ["." list ("list/." Fold Monad)]]]
    ["." macro (#+ with-gensyms)
@@ -126,12 +126,12 @@
 
 (def: ascii^
   (l.Lexer Text)
-  (l.range (char "\u0000") (char "\u007F")))
+  (l.range (hex "0") (hex "7F")))
 
 (def: control^
   (l.Lexer Text)
-  (p.either (l.range (char "\u0000") (char "\u001F"))
-            (l.one-of "\u007F")))
+  (p.either (l.range (hex "0") (hex "1F"))
+            (l.one-of (//.from-code (hex "7F")))))
 
 (def: punct^
   (l.Lexer Text)
@@ -144,7 +144,7 @@
 (def: print^
   (l.Lexer Text)
   (p.either graph^
-            (l.one-of "\u0020")))
+            (l.one-of (//.from-code (hex "20")))))
 
 (def: re-system-class^
   (l.Lexer Code)
diff --git a/stdlib/source/lux/macro/poly.lux b/stdlib/source/lux/macro/poly.lux
index 72a56b81d..7b3bc49a2 100644
--- a/stdlib/source/lux/macro/poly.lux
+++ b/stdlib/source/lux/macro/poly.lux
@@ -12,7 +12,7 @@
     ["." maybe]
     [name ("name/." Codec)]
     ["e" error]
-    ["." number ("nat/." Codec)]
+    ["." number (#+ hex) ("nat/." Codec)]
     ["." text ("text/." Monoid)
      format]
     [collection
@@ -131,7 +131,7 @@
 
 (def: (label idx)
   (-> Nat Code)
-  (code.local-identifier (text/compose "label\u0000" (nat/encode idx))))
+  (code.local-identifier ($_ text/compose "label" text.tab (nat/encode idx))))
 
 (def: #export (with-extension type poly)
   (All [a] (-> Type (Poly a) (Poly [Code a])))
diff --git a/stdlib/test/test/lux/data/text/regex.lux b/stdlib/test/test/lux/data/text/regex.lux
index 7a6e88d33..7c54d8385 100644
--- a/stdlib/test/test/lux/data/text/regex.lux
+++ b/stdlib/test/test/lux/data/text/regex.lux
@@ -5,6 +5,7 @@
     pipe
     ["p" parser]]
    [data
+    [number (#+ hex)]
     ["." text ("text/." Equivalence)
      format
      ["." lexer (#+ Lexer)]
@@ -121,9 +122,9 @@
                       (should-fail (&.regex "\\p{Blank}") "."))
 
                  (and (should-pass (&.regex "\\p{ASCII}") text.tab)
-                      (should-fail (&.regex "\\p{ASCII}") "\u1234"))
+                      (should-fail (&.regex "\\p{ASCII}") (text.from-code (hex "1234"))))
 
-                 (and (should-pass (&.regex "\\p{Contrl}") "\u0012")
+                 (and (should-pass (&.regex "\\p{Contrl}") (text.from-code (hex "12")))
                       (should-fail (&.regex "\\p{Contrl}") "a"))
 
                  (and (should-pass (&.regex "\\p{Punct}") "@")
@@ -132,8 +133,8 @@
                  (and (should-pass (&.regex "\\p{Graph}") "@")
                       (should-fail (&.regex "\\p{Graph}") " "))
 
-                 (and (should-pass (&.regex "\\p{Print}") "\u0020")
-                      (should-fail (&.regex "\\p{Print}") "\u1234"))
+                 (and (should-pass (&.regex "\\p{Print}") (text.from-code (hex "20")))
+                      (should-fail (&.regex "\\p{Print}") (text.from-code (hex "1234"))))
                  ))
       ))
 
diff --git a/stdlib/test/test/lux/math/logic/fuzzy.lux b/stdlib/test/test/lux/math/logic/fuzzy.lux
index fe36a58c5..38f1cc75a 100644
--- a/stdlib/test/test/lux/math/logic/fuzzy.lux
+++ b/stdlib/test/test/lux/math/logic/fuzzy.lux
@@ -153,13 +153,13 @@
         [#let [set-10 (set.from-list number.Hash (list.n/range 0 10))]
          sample (|> r.nat (:: @ map (n/% 20)))]
         ($_ seq
-            (test "Values that satisfy a predicate have membership = 1.
-                   Values that don't have membership = 0."
+            (test (format "Values that satisfy a predicate have membership = 1."
+                          "Values that don't have membership = 0.")
                   (bit/= (r/= _.true (&.membership sample (&.from-predicate n/even?)))
                          (n/even? sample)))
 
-            (test "Values that belong to a set have membership = 1.
-                   Values that don't have membership = 0."
+            (test (format "Values that belong to a set have membership = 1."
+                          "Values that don't have membership = 0.")
                   (bit/= (r/= _.true (&.membership sample (&.from-set set-10)))
                          (set.member? set-10 sample)))
             ))))
-- 
cgit v1.2.3


From a89088576c4e586d3dad18f82eb451ff4eaa14fb Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 00:03:26 -0400
Subject: No more escaping of double-quotes.

---
 stdlib/source/lux.lux                            | 127 ++++++++++++-----------
 stdlib/source/lux/cli.lux                        |   4 +-
 stdlib/source/lux/compiler/default/syntax.lux    |  36 ++-----
 stdlib/source/lux/control/comonad.lux            |   2 +-
 stdlib/source/lux/control/pipe.lux               |   2 +-
 stdlib/source/lux/data/format/html.lux           |  18 ++--
 stdlib/source/lux/data/format/json.lux           |  12 +--
 stdlib/source/lux/data/format/xml.lux            |  12 +--
 stdlib/source/lux/data/number.lux                |   2 +-
 stdlib/source/lux/data/text/regex.lux            |   5 +-
 stdlib/source/lux/host.jvm.lux                   |   4 +-
 stdlib/source/lux/interpreter.lux                |   2 +-
 stdlib/source/lux/io.lux                         |   2 +-
 stdlib/source/lux/macro.lux                      |   2 +-
 stdlib/source/lux/macro/syntax.lux               |   2 +-
 stdlib/test/test/lux/compiler/default/syntax.lux |  45 +-------
 stdlib/test/test/lux/data/text/format.lux        |   2 +-
 stdlib/test/test/lux/host.jvm.lux                |   2 +-
 stdlib/test/test/lux/macro/code.lux              |   4 +-
 19 files changed, 120 insertions(+), 165 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 5ffe8d939..5e14a9806 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -1,3 +1,8 @@
+("lux def" double-quote
+ ("lux check" (0 "#Text" (0))
+  ("lux int char" +34))
+ [["" 0 0] (10 (0))])
+
 ("lux def" dummy-cursor
  ("lux check" (2 (0 "#Text" (0))
                  (2 (0 "#I64" (1 (0 "#Nat" (0)) (0)))
@@ -37,7 +42,7 @@
             (1 [[dummy-cursor (7 ["lux" "doc"])]
                 [dummy-cursor (5 ("lux text concat"
                                   "The type of things whose type is undefined.\n\n"
-                                  "Useful for expressions that cause errors or other \"extraordinary\" conditions."))]]
+                                  "Useful for expressions that cause errors or other 'extraordinary' conditions."))]]
                (0)))))])
 
 ## (type: (List a)
@@ -1572,10 +1577,10 @@
                  (text$ ("lux text concat"
                          "## Left-association for the application of binary functions over variadic arguments.\n\n"
                          ("lux text concat"
-                          "(_$ text/compose \"Hello, \" name \".\\nHow are you?\")\n\n"
+                          "(_$ text/compose ''Hello, '' name ''.\\nHow are you?'')\n\n"
                           ("lux text concat"
                            "## =>\n\n"
-                           "(text/compose (text/compose \"Hello, \" name) \".\\nHow are you?\")"))))]
+                           "(text/compose (text/compose ''Hello, '' name) ''.\\nHow are you?'')"))))]
                 #Nil)
          ({(#Cons op tokens')
            ({(#Cons first nexts)
@@ -1594,10 +1599,10 @@
                  (text$ ("lux text concat"
                          "## Right-association for the application of binary functions over variadic arguments.\n\n"
                          ("lux text concat"
-                          "($_ text/compose \"Hello, \" name \".\\nHow are you?\")\n\n"
+                          "($_ text/compose ''Hello, '' name ''.\\nHow are you?'')\n\n"
                           ("lux text concat"
                            "## =>\n\n"
-                           "(text/compose \"Hello, \" (text/compose name \".\\nHow are you?\"))"))))]
+                           "(text/compose ''Hello, '' (text/compose name ''.\\nHow are you?''))"))))]
                 #Nil)
          ({(#Cons op tokens')
            ({(#Cons last prevs)
@@ -1727,8 +1732,8 @@
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
                            "Picks which expression to evaluate based on a bit test value." "\n\n"
-                           "(if #1 \"Oh, yeah!\" \"Aw hell naw!\")" "\n\n"
-                           "=> \"Oh, yeah!\""))])
+                           "(if #1 ''Oh, yeah!'' ''Aw hell naw!'')" "\n\n"
+                           "=> ''Oh, yeah!''"))])
          ({(#Cons test (#Cons then (#Cons else #Nil)))
            (return (list (form$ (list (record$ (list [(bit$ #1)  then]
                                                      [(bit$ #0) else]))
@@ -1975,8 +1980,8 @@
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
                            "## Macro to treat define new primitive types." "\n\n"
-                           "(primitive \"java.lang.Object\")" "\n\n"
-                           "(primitive \"java.util.List\" [(primitive \"java.lang.Long\")])"))])
+                           "(primitive ''java.lang.Object'')" "\n\n"
+                           "(primitive ''java.util.List'' [(primitive ''java.lang.Long'')])"))])
          ({(#Cons [_ (#Text class-name)] #Nil)
            (return (list (form$ (list (tag$ ["lux" "Primitive"]) (text$ class-name) (tag$ ["lux" "Nil"])))))
 
@@ -2038,7 +2043,7 @@
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
                            "## Quotation as a macro." "\n\n"
-                           "(' \"YOLO\")"))])
+                           "(' YOLO)"))])
          ({(#Cons template #Nil)
            (do Monad
              [=template (untemplate #0 "" template)]
@@ -2052,9 +2057,9 @@
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
                            "## Piping macro." "\n\n"
-                           "(|> elems (list/map int/encode) (interpose \" \") (fold text/compose \"\"))" "\n\n"
+                           "(|> elems (list/map int/encode) (interpose '' '') (fold text/compose ''''))" "\n\n"
                            "## =>" "\n\n"
-                           "(fold text/compose \"\" (interpose \" \" (list/map int/encode elems)))"))])
+                           "(fold text/compose '''' (interpose '' '' (list/map int/encode elems)))"))])
          ({(#Cons [init apps])
            (return (list (list/fold ("lux check" (-> Code Code Code)
                                      (function' [app acc]
@@ -2078,9 +2083,9 @@
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
                            "## Reverse piping macro." "\n\n"
-                           "(<| (fold text/compose \"\") (interpose \" \") (list/map int/encode) elems)" "\n\n"
+                           "(<| (fold text/compose '''') (interpose '' '') (list/map int/encode) elems)" "\n\n"
                            "## =>" "\n\n"
-                           "(fold text/compose \"\" (interpose \" \" (list/map int/encode elems)))"))])
+                           "(fold text/compose '''' (interpose '' '' (list/map int/encode elems)))"))])
          ({(#Cons [init apps])
            (return (list (list/fold ("lux check" (-> Code Code Code)
                                      (function' [app acc]
@@ -2961,10 +2966,10 @@
                 (text$ ($_ "lux text concat"
                            "## Sequential execution of expressions (great for side-effects)." "\n\n"
                            "(exec" "\n"
-                           "  " "(log! \"#1\")" "\n"
-                           "  " "(log! \"#2\")" "\n"
-                           "  " "(log! \"#3\")" "\n"
-                           "\"YOLO\")"))])
+                           "  " "(log! ''#1'')" "\n"
+                           "  " "(log! ''#2'')" "\n"
+                           "  " "(log! ''#3'')" "\n"
+                           "''YOLO'')"))])
          ({(#Cons value actions)
            (let' [dummy (identifier$ ["" ""])]
                  (return (list (list/fold ("lux check" (-> Code Code Code)
@@ -3046,7 +3051,7 @@
          (frac/encode value)
 
          [_ (#Text value)]
-         ($_ text/compose "\"" value "\"")
+         ($_ text/compose ..double-quote value ..double-quote)
          
          [_ (#Identifier [prefix name])]
          (if (text/= "" prefix)
@@ -3107,11 +3112,11 @@
          (do Monad [] (wrap (list)))
 
          _
-         (fail ($_ text/compose "\"lux.case\" expects an even number of tokens: " (|> branches
-                                                                                      (list/map code-to-text)
-                                                                                      (interpose " ")
-                                                                                      list/reverse
-                                                                                      (list/fold text/compose ""))))}
+         (fail ($_ text/compose "'lux.case' expects an even number of tokens: " (|> branches
+                                                                                    (list/map code-to-text)
+                                                                                    (interpose " ")
+                                                                                    list/reverse
+                                                                                    (list/fold text/compose ""))))}
         branches))
 
 (macro:' #export (case tokens)
@@ -3438,7 +3443,7 @@
                            "    ([#Identifier] [#Tag])"
                            "\n\n"
                            "    _" "\n"
-                           "    (fail \"Wrong syntax for name-of\")))"))])
+                           "    (fail ''Wrong syntax for name-of'')))"))])
          (let [[exported? tokens] (export^ tokens)
                name+args+meta+body?? (: (Maybe [Name (List Code) Code Code])
                                         (case tokens
@@ -3568,8 +3573,8 @@
        _
        (fail )))]
 
-  [and (if (~ pre) (~ post) #0) "'and' requires >=1 clauses." "Short-circuiting \"and\".\n(and #1 #0 #1) ## => #0"]
-  [or  (if (~ pre) #1 (~ post))  "'or' requires >=1 clauses."  "Short-circuiting \"or\".\n(or #1 #0 #1) ## => #1"])
+  [and (if (~ pre) (~ post) #0) "'and' requires >=1 clauses." "Short-circuiting 'and'.\n(and #1 #0 #1) ## => #0"]
+  [or  (if (~ pre) #1 (~ post))  "'or' requires >=1 clauses."  "Short-circuiting 'or'.\n(or #1 #0 #1) ## => #1"])
 
 (def: (index-of part text)
   (-> Text Text (Maybe Nat))
@@ -3604,7 +3609,7 @@
 (def: #export (error! message)
   {#.doc (text$ ($_ "lux text concat"
                     "## Causes an error, with the given error message." "\n"
-                    "(error! \"OH NO!\")"))}
+                    "(error! ''OH NO!'')"))}
   (-> Text Nothing)
   ("lux io error" message))
 
@@ -3851,7 +3856,7 @@
         (#Left "Not expecting any type.")))))
 
 (macro: #export (structure tokens)
-  {#.doc "Not meant to be used directly. Prefer \"structure:\"."}
+  {#.doc "Not meant to be used directly. Prefer 'structure:'."}
   (do Monad
     [tokens' (monad/map Monad macro-expand tokens)
      struct-type get-expected-type
@@ -3961,7 +3966,7 @@
                              (structure (~+ definitions)))))))
 
         #None
-        (fail "Cannot infer name, so struct must have a name other than \"_\"!"))
+        (fail "Cannot infer name, so struct must have a name other than '_'!"))
 
       #None
       (fail "Wrong syntax for structure:"))))
@@ -4492,9 +4497,9 @@
 
 (macro: #export (^open tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Same as the \"open\" macro, but meant to be used as a pattern-matching macro for generating local bindings." "\n"
-                    "## Takes an \"alias\" text for the generated local bindings." "\n"
-                    "(def: #export (range (^open \".\") from to)" "\n"
+                    "## Same as the 'open' macro, but meant to be used as a pattern-matching macro for generating local bindings." "\n"
+                    "## Takes an 'alias' text for the generated local bindings." "\n"
+                    "(def: #export (range (^open ''.'') from to)" "\n"
                     "  (All [a] (-> (Enum a) a a (List a)))" "\n"
                     "  (range' <= succ from to))"))}
   (case tokens
@@ -4509,7 +4514,7 @@
        struct-evidence (resolve-type-tags init-type)]
       (case struct-evidence
         #None
-        (fail (text/compose "Can only \"open\" structs: " (type/encode init-type)))
+        (fail (text/compose "Can only 'open' structs: " (type/encode init-type)))
 
         (#Some tags&members)
         (do Monad
@@ -4544,11 +4549,11 @@
 (macro: #export (cond tokens)
   {#.doc (text$ ($_ "lux text concat"
                     "## Branching structures with multiple test conditions." "\n"
-                    "(cond (n/even? num) \"even\"" "\n"
-                    "      (n/odd? num) \"odd\""
+                    "(cond (n/even? num) ''even''" "\n"
+                    "      (n/odd? num) ''odd''"
                     "\n\n"
                     "      ## else-branch" "\n"
-                    "      \"???\")"))}
+                    "      ''???'')"))}
   (if (n/= 0 (n/% 2 (list/size tokens)))
     (fail "cond requires an uneven number of arguments.")
     (case (list/reverse tokens)
@@ -4649,7 +4654,7 @@
                     "## Opens a structure and generates a definition for each of its members (including nested members)."
                     "\n\n"
                     "## For example:" "\n"
-                    "(open: \"i:.\" Number)"
+                    "(open: ''i:.'' Number)"
                     "\n\n"
                     "## Will generate:" "\n"
                     "(def: i:+ (:: Number +))" "\n"
@@ -4674,7 +4679,7 @@
             (return (list/join decls')))
 
           _
-          (fail (text/compose "Can only \"open:\" structs: " (type/encode struct-type)))))
+          (fail (text/compose "Can only 'open:' structs: " (type/encode struct-type)))))
 
       _
       (do Monad
@@ -4689,9 +4694,9 @@
 (macro: #export (|>> tokens)
   {#.doc (text$ ($_ "lux text concat"
                     "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." "\n"
-                    "(|>> (list/map int/encode) (interpose \" \") (fold text/compose \"\"))" "\n"
+                    "(|>> (list/map int/encode) (interpose '' '') (fold text/compose ''''))" "\n"
                     "## =>" "\n"
-                    "(function (_ ) (fold text/compose \"\" (interpose \" \" (list/map int/encode ))))"))}
+                    "(function (_ ) (fold text/compose '''' (interpose '' '' (list/map int/encode ))))"))}
   (do Monad
     [g!_ (gensym "_")
      g!arg (gensym "arg")]
@@ -4700,9 +4705,9 @@
 (macro: #export (<<| tokens)
   {#.doc (text$ ($_ "lux text concat"
                     "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." "\n"
-                    "(<<| (fold text/compose \"\") (interpose \" \") (list/map int/encode))" "\n"
+                    "(<<| (fold text/compose '''') (interpose '' '') (list/map int/encode))" "\n"
                     "## =>" "\n"
-                    "(function (_ ) (fold text/compose \"\" (interpose \" \" (list/map int/encode ))))"))}
+                    "(function (_ ) (fold text/compose '''' (interpose '' '' (list/map int/encode ))))"))}
   (do Monad
     [g!_ (gensym "_")
      g!arg (gensym "arg")]
@@ -4832,17 +4837,17 @@
                     "## Can take optional annotations and allows the specification of modules to import."
                     "\n\n"
                     "## Example" "\n"
-                    "(.module: {#.doc \"Some documentation...\"}" "\n"
+                    "(.module: {#.doc ''Some documentation...''}" "\n"
                     "  [lux #*" "\n"
                     "   [control" "\n"
-                    "    [\"M\" monad #*]]" "\n"
+                    "    [''M'' monad #*]]" "\n"
                     "   [data" "\n"
                     "    maybe" "\n"
-                    "    [\".\" name (\"name/.\" Codec)]]" "\n"
+                    "    [''.'' name (''name/.'' Codec)]]" "\n"
                     "   [macro" "\n"
                     "    code]]" "\n"
                     "  [//" "\n"
-                    "   [type (\".\" Equivalence)]])"))}
+                    "   [type (''.'' Equivalence)]])"))}
   (do Monad
     [#let [[_meta _imports] (: [(List [Code Code]) (List Code)]
                                (case tokens
@@ -4887,7 +4892,7 @@
 (macro: #export (set@ tokens)
   {#.doc (text$ ($_ "lux text concat"
                     "## Sets the value of a record at a given tag." "\n"
-                    "(set@ #name \"Lux\" lang)"
+                    "(set@ #name ''Lux'' lang)"
                     "\n\n"
                     "## Can also work with multiple levels of nesting:" "\n"
                     "(set@ [#foo #bar #baz] value my-record)"
@@ -5154,7 +5159,7 @@
 
 (def: (text/encode original)
   (-> Text Text)
-  ($_ text/compose "\"" original "\""))
+  ($_ text/compose ..double-quote original ..double-quote))
 
 (do-template [  ]
   [(def: #export ( value)
@@ -5272,8 +5277,8 @@
                     "## Creates code documentation, embedding text as comments and properly formatting the forms it's being given."
                     "\n\n"
                     "## For Example:" "\n"
-                    "(doc \"Allows arbitrary looping, using the \\\"recur\\\" form to re-start the loop.\"" "\n"
-                    "     \"Can be used in monadic code to create monadic loops.\"" "\n"
+                    "(doc ''Allows arbitrary looping, using the \\''recur\\'' form to re-start the loop.''" "\n"
+                    "     ''Can be used in monadic code to create monadic loops.''" "\n"
                     "     (loop [count +0" "\n"
                     "            x init]" "\n"
                     "       (if (< +10 count)" "\n"
@@ -5337,7 +5342,7 @@
     (identifier$ [module name])))
 
 (macro: #export (loop tokens)
-  {#.doc (doc "Allows arbitrary looping, using the \"recur\" form to re-start the loop."
+  {#.doc (doc "Allows arbitrary looping, using the 'recur' form to re-start the loop."
               "Can be used in monadic code to create monadic loops."
               (loop [count +0
                      x init]
@@ -5480,18 +5485,18 @@
                               (compare  (:: Code/encode encode ))
                               (compare #1 (:: Equivalence =  ))]
 
-                             [(bit #1)                             "#1"        [_ (#.Bit #1)]]
-                             [(bit #0)                             "#0"        [_ (#.Bit #0)]]
+                             [(bit #1)                              "#1"         [_ (#.Bit #1)]]
+                             [(bit #0)                              "#0"         [_ (#.Bit #0)]]
                              [(int +123)                            "+123"       [_ (#.Int +123)]]
                              [(frac +123.0)                         "+123.0"     [_ (#.Frac +123.0)]]
-                             [(text "\n")                          "\"\\n\""   [_ (#.Text "\n")]]
-                             [(tag ["yolo" "lol"])                 "#yolo.lol" [_ (#.Tag ["yolo" "lol"])]]
-                             [(identifier ["yolo" "lol"])          "yolo.lol"  [_ (#.Identifier ["yolo" "lol"])]]
+                             [(text "\n")                           "'\\n'"      [_ (#.Text "\n")]]
+                             [(tag ["yolo" "lol"])                  "#yolo.lol"  [_ (#.Tag ["yolo" "lol"])]]
+                             [(identifier ["yolo" "lol"])           "yolo.lol"   [_ (#.Identifier ["yolo" "lol"])]]
                              [(form (list (bit #1) (int +123)))     "(#1 +123)"  (^ [_ (#.Form (list [_ (#.Bit #1)] [_ (#.Int +123)]))])]
                              [(tuple (list (bit #1) (int +123)))    "[#1 +123]"  (^ [_ (#.Tuple (list [_ (#.Bit #1)] [_ (#.Int +123)]))])]
                              [(record (list [(bit #1) (int +123)])) "{#1 +123}"  (^ [_ (#.Record (list [[_ (#.Bit #1)] [_ (#.Int +123)]]))])]
-                             [(local-tag "lol")                    "#lol"      [_ (#.Tag ["" "lol"])]]
-                             [(local-identifier "lol")             "lol"       [_ (#.Identifier ["" "lol"])]]
+                             [(local-tag "lol")                     "#lol"       [_ (#.Tag ["" "lol"])]]
+                             [(local-identifier "lol")              "lol"        [_ (#.Identifier ["" "lol"])]]
                              )]
                   (test-all ))))}
   (case tokens
@@ -5597,7 +5602,7 @@
       (wrap (list pattern')))
     
     _
-    (fail "Wrong syntax for \"static\".")))
+    (fail "Wrong syntax for 'static'.")))
 
 (type: Multi-Level-Case
   [Code (List [Code Code])])
@@ -5750,7 +5755,7 @@
     (fail "Wrong syntax for $")))
 
 (def: #export (is? reference sample)
-  {#.doc (doc "Tests whether the 2 values are identical (not just \"equal\")."
+  {#.doc (doc "Tests whether the 2 values are identical (not just 'equal')."
               "This one should succeed:"
               (let [value +5]
                 (is? value value))
diff --git a/stdlib/source/lux/cli.lux b/stdlib/source/lux/cli.lux
index abb1d0c38..07e79d86f 100644
--- a/stdlib/source/lux/cli.lux
+++ b/stdlib/source/lux/cli.lux
@@ -66,7 +66,7 @@
       [[remaining raw] (any inputs)]
       (if (text/= reference raw)
         (wrap [remaining []])
-        (E.fail (format "Missing token: \"" reference "\""))))))
+        (E.fail (format "Missing token: '" reference "'"))))))
 
 (def: #export (somewhere cli)
   {#.doc "Given a parser, tries to parse it somewhere in the inputs (i.e. not necessarily parsing the immediate inputs)."}
@@ -118,7 +118,7 @@
 (syntax: #export (program:
                    {args program-args^}
                    body)
-  {#.doc (doc "Defines the entry-point to a program (similar to the \"main\" function/method in other programming languages)."
+  {#.doc (doc "Defines the entry-point to a program (similar to the 'main' function/method in other programming languages)."
               "Can take a list of all the input parameters to the program, or can destructure them using CLI-option combinators from the lux/cli module."
               (program: all-args
                 (do Monad
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index dc22de5d0..faa072d88 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -62,25 +62,25 @@
 (def: new-line "\n")
 ## (def: new-line^ (l.this new-line))
 
-(def: text-delimiter "\"")
+(def: #export text-delimiter text.double-quote)
 ## (def: text-delimiter^ (l.this text-delimiter))
 
-(def: open-form "(")
-(def: close-form ")")
+(def: #export open-form "(")
+(def: #export close-form ")")
 
-(def: open-tuple "[")
-(def: close-tuple "]")
+(def: #export open-tuple "[")
+(def: #export close-tuple "]")
 
-(def: open-record "{")
-(def: close-record "}")
+(def: #export open-record "{")
+(def: #export close-record "}")
 
 (def: escape "\\")
 
-(def: sigil "#")
+(def: #export sigil "#")
 
-(def: digit-separator "_")
+(def: #export digit-separator "_")
 
-(def: single-line-comment-marker (format ..sigil ..sigil))
+## (def: comment-marker (format ..sigil ..sigil))
 
 ## ## This is the parser for white-space.
 ## ## Whenever a new-line is encountered, the column gets reset to 0, and
@@ -105,7 +105,7 @@
 ## (def: (comment^ where)
 ##   (-> Cursor (Lexer Cursor))
 ##   (do p.Monad
-##     [_ (l.this ..single-line-comment-marker)
+##     [_ (l.this ..comment-marker)
 ##      _ (l.some! (l.none-of! new-line))
 ##      _ ..new-line^]
 ##     (wrap (|> where
@@ -138,7 +138,6 @@
              (case code
                ## Handle special cases.
                "n" (wrap [2 ..new-line])
-               (^ (static ..text-delimiter)) (wrap [2 ..text-delimiter])
                (^ (static ..escape)) (wrap [2 ..escape])
 
                _
@@ -608,19 +607,6 @@
             (["n" (static ..new-line)]
              [(~~ (static ..escape)) (static ..escape)])
 
-            (^ (char (~~ (static ..text-delimiter))))
-            (case (!find-next-escape 2 next-escape end source-code total (static ..text-delimiter))
-              (#error.Error error)
-              (#error.Error error)
-              
-              (#error.Success [next-escape' post-delimiter so-far])
-              (case ("lux text index" source-code (static ..text-delimiter) post-delimiter)
-                (#.Some end')
-                (recur end' next-escape' so-far)
-
-                _
-                (ex.throw invalid-escape-syntax [])))
-
             _
             (ex.throw invalid-escape-syntax []))))))
 
diff --git a/stdlib/source/lux/control/comonad.lux b/stdlib/source/lux/control/comonad.lux
index 76fe954e5..2d96364ad 100644
--- a/stdlib/source/lux/control/comonad.lux
+++ b/stdlib/source/lux/control/comonad.lux
@@ -28,7 +28,7 @@
 (def: _cursor Cursor ["" 0 0])
 
 (macro: #export (be tokens state)
-  {#.doc (doc "A co-monadic parallel to the \"do\" macro."
+  {#.doc (doc "A co-monadic parallel to the 'do' macro."
               (let [square (function (_ n) (i/* n n))]
                 (be CoMonad
                   [inputs (iterate inc +2)]
diff --git a/stdlib/source/lux/control/pipe.lux b/stdlib/source/lux/control/pipe.lux
index 4895a4f66..a5f9eca95 100644
--- a/stdlib/source/lux/control/pipe.lux
+++ b/stdlib/source/lux/control/pipe.lux
@@ -128,7 +128,7 @@
                   (tuple> [(i/* +10)]
                           [dec (i// +2)]
                           [Int/encode]))
-              "Will become: [+50 +2 \"+5\"]")}
+              "Will become: [+50 +2 '+5']")}
   (with-gensyms [g!temp]
     (wrap (list (` (let [(~ g!temp) (~ prev)]
                      [(~+ (list/map (function (_ body) (` (|> (~ g!temp) (~+ body))))
diff --git a/stdlib/source/lux/data/format/html.lux b/stdlib/source/lux/data/format/html.lux
index cc5e6d0e9..45a7117ad 100644
--- a/stdlib/source/lux/data/format/html.lux
+++ b/stdlib/source/lux/data/format/html.lux
@@ -18,7 +18,7 @@
       (text.replace-all "&" "&")
       (text.replace-all "<" "<")
       (text.replace-all ">" ">")
-      (text.replace-all "\"" """)
+      (text.replace-all text.double-quote """)
       (text.replace-all "'" "'")
       (text.replace-all "/" "/")))
 
@@ -28,7 +28,7 @@
 
 (def: attrs-to-text
   (-> Attributes Text)
-  (|>> (list/map (function (_ [key val]) (format key "=" "\"" (text val) "\"")))
+  (|>> (list/map (function (_ [key val]) (format key "=" text.double-quote (text val) text.double-quote)))
        (text.join-with " ")))
 
 (def: #export (tag name attrs children)
@@ -39,13 +39,15 @@
           ""))
 
 (do-template [ ]
-  [(def: #export ( document)
+  [(def: #export 
      (-> HTML HTML)
-     (format 
-             document))]
+     (let [doc-type ]
+       (function (_ document)
+         (format doc-type
+                 document))))]
 
   [html-5    ""]
-  [html-4_01 ""]
-  [xhtml-1_0 ""]
-  [xhtml-1_1 ""]
+  [html-4_01 (format "")]
+  [xhtml-1_0 (format "")]
+  [xhtml-1_1 (format "")]
   )
diff --git a/stdlib/source/lux/data/format/json.lux b/stdlib/source/lux/data/format/json.lux
index 1d0837b90..9189b375f 100644
--- a/stdlib/source/lux/data/format/json.lux
+++ b/stdlib/source/lux/data/format/json.lux
@@ -113,10 +113,10 @@
       (#e.Success value)
 
       #.None
-      (#e.Error ($_ text/compose "Missing field \"" key "\" on object.")))
+      (#e.Error ($_ text/compose "Missing field '" key "' on object.")))
 
     _
-    (#e.Error ($_ text/compose "Cannot get field \"" key "\" of a non-object."))))
+    (#e.Error ($_ text/compose "Cannot get field '" key "' of a non-object."))))
 
 (def: #export (set key value json)
   {#.doc "A JSON object field setter."}
@@ -126,7 +126,7 @@
     (#e.Success (#Object (dict.put key value obj)))
 
     _
-    (#e.Error ($_ text/compose "Cannot set field \"" key "\" of a non-object."))))
+    (#e.Error ($_ text/compose "Cannot set field '" key "' of a non-object."))))
 
 (do-template [   ]
   [(def: #export ( key json)
@@ -352,7 +352,7 @@
           (fail error))
 
         _
-        (fail ($_ text/compose "JSON object does not have field \"" field-name "\".")))
+        (fail ($_ text/compose "JSON object does not have field '" field-name "'.")))
 
       _
       (fail "JSON value is not an object."))))
@@ -469,10 +469,10 @@
 
 (def: string~
   (l.Lexer String)
-  (<| (l.enclosed ["\"" "\""])
+  (<| (l.enclosed [text.double-quote text.double-quote])
       (loop [_ []])
       (do p.Monad
-        [chars (l.some (l.none-of "\\\""))
+        [chars (l.some (l.none-of (text/compose "\\" text.double-quote)))
          stop l.peek])
       (if (text/= "\\" stop)
         (do @
diff --git a/stdlib/source/lux/data/format/xml.lux b/stdlib/source/lux/data/format/xml.lux
index 61215813b..a5cb39ab5 100644
--- a/stdlib/source/lux/data/format/xml.lux
+++ b/stdlib/source/lux/data/format/xml.lux
@@ -33,7 +33,7 @@
       (p.after (l.this ">") (parser/wrap ">"))
       (p.after (l.this "&") (parser/wrap "&"))
       (p.after (l.this "'") (parser/wrap "'"))
-      (p.after (l.this """) (parser/wrap "\""))))
+      (p.after (l.this """) (parser/wrap text.double-quote))))
 
 (def: xml-unicode-escape-char^
   (l.Lexer Text)
@@ -56,7 +56,7 @@
 
 (def: xml-char^
   (l.Lexer Text)
-  (p.either (l.none-of "<>&'\"")
+  (p.either (l.none-of ($_ text/compose "<>&'" text.double-quote))
             xml-escape-char^))
 
 (def: xml-identifier
@@ -92,7 +92,7 @@
 (def: attr-value^
   (l.Lexer Text)
   (let [value^ (l.some xml-char^)]
-    (p.either (l.enclosed ["\"" "\""] value^)
+    (p.either (l.enclosed [text.double-quote text.double-quote] value^)
               (l.enclosed ["'" "'"] value^))))
 
 (def: attrs^
@@ -181,7 +181,7 @@
       (text.replace-all "<" "<")
       (text.replace-all ">" ">")
       (text.replace-all "'" "'")
-      (text.replace-all "\"" """)))
+      (text.replace-all text.double-quote """)))
 
 (def: (write-tag [namespace name])
   (-> Tag Text)
@@ -194,12 +194,12 @@
   (|> attrs
       d.entries
       (list/map (function (_ [key value])
-                  ($_ text/compose (write-tag key) "=" "\""(sanitize-value value) "\"")))
+                  ($_ text/compose (write-tag key) "=" text.double-quote (sanitize-value value) text.double-quote)))
       (text.join-with " ")))
 
 (def: xml-header
   Text
-  "")
+  ($_ text/compose ""))
 
 (def: #export (write input)
   (-> XML Text)
diff --git a/stdlib/source/lux/data/number.lux b/stdlib/source/lux/data/number.lux
index 4b3b786b4..df3e2d353 100644
--- a/stdlib/source/lux/data/number.lux
+++ b/stdlib/source/lux/data/number.lux
@@ -682,7 +682,7 @@
                                            (~ example-2))))]))
 
     _
-    (#error.Error "Wrong syntax for \"encoding-doc\".")))
+    (#error.Error "Wrong syntax for 'encoding-doc'.")))
 
 (def: (underscore-prefixed? number)
   (-> Text Bit)
diff --git a/stdlib/source/lux/data/text/regex.lux b/stdlib/source/lux/data/text/regex.lux
index e491873dc..bb2c570e3 100644
--- a/stdlib/source/lux/data/text/regex.lux
+++ b/stdlib/source/lux/data/text/regex.lux
@@ -54,7 +54,7 @@
 
 (def: name-char^
   (l.Lexer Text)
-  (l.none-of "[]{}()s\"#.<>"))
+  (l.none-of (format "[]{}()s#.<>" //.double-quote)))
 
 (def: name-part^
   (l.Lexer Text)
@@ -135,7 +135,8 @@
 
 (def: punct^
   (l.Lexer Text)
-  (l.one-of "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"))
+  (l.one-of (format "!#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
+                    //.double-quote)))
 
 (def: graph^
   (l.Lexer Text)
diff --git a/stdlib/source/lux/host.jvm.lux b/stdlib/source/lux/host.jvm.lux
index 9bb839aec..b5a2454e1 100644
--- a/stdlib/source/lux/host.jvm.lux
+++ b/stdlib/source/lux/host.jvm.lux
@@ -1319,10 +1319,10 @@
               "An optional super-class can be specified before the tuple. If not specified, java.lang.Object will be assumed."
               "Fields and methods defined in the class can be used with special syntax."
               "For example:"
-              "::resolved, for accessing the \"resolved\" field."
+              "::resolved, for accessing the 'resolved' field."
               "(:= ::resolved #1) for modifying it."
               "(::new! []) for calling the class's constructor."
-              "(::resolve! container [value]) for calling the \"resolve\" method."
+              "(::resolve! container [value]) for calling the 'resolve' method."
               )}
   (do Monad
     [current-module macro.current-module-name
diff --git a/stdlib/source/lux/interpreter.lux b/stdlib/source/lux/interpreter.lux
index df475475a..6837f24d9 100644
--- a/stdlib/source/lux/interpreter.lux
+++ b/stdlib/source/lux/interpreter.lux
@@ -44,7 +44,7 @@
   Text
   (format "\n"
           "Welcome to the interpreter!" "\n"
-          "Type \"exit\" to leave." "\n"
+          "Type 'exit' to leave." "\n"
           "\n"))
 
 (def: farewell-message
diff --git a/stdlib/source/lux/io.lux b/stdlib/source/lux/io.lux
index 5ec03c749..96503f10e 100644
--- a/stdlib/source/lux/io.lux
+++ b/stdlib/source/lux/io.lux
@@ -16,7 +16,7 @@
 
 (macro: #export (io tokens state)
   {#.doc (doc "Delays the evaluation of an expression, by wrapping it in an IO 'thunk'."
-              "Great for wrapping effectful computations (which will not be performed until the IO is \"run\")."
+              "Great for wrapping effectful computations (which will not be performed until the IO is 'run')."
               (io (exec
                     (log! msg)
                     "Some value...")))}
diff --git a/stdlib/source/lux/macro.lux b/stdlib/source/lux/macro.lux
index 88299a812..10b5d3b41 100644
--- a/stdlib/source/lux/macro.lux
+++ b/stdlib/source/lux/macro.lux
@@ -365,7 +365,7 @@
 
 (def: #export (gensym prefix)
   {#.doc (doc "Generates a unique name as an Code node (ready to be used in code templates)."
-              "A prefix can be given (or just be empty text \"\") to better identify the code for debugging purposes.")}
+              "A prefix can be given (or just be empty text) to better identify the code for debugging purposes.")}
   (-> Text (Meta Code))
   (function (_ compiler)
     (#e.Success [(update@ #.seed inc compiler)
diff --git a/stdlib/source/lux/macro/syntax.lux b/stdlib/source/lux/macro/syntax.lux
index db5e086b6..74901beb9 100644
--- a/stdlib/source/lux/macro/syntax.lux
+++ b/stdlib/source/lux/macro/syntax.lux
@@ -196,7 +196,7 @@
 
 ## [Syntax]
 (macro: #export (syntax: tokens)
-  {#.doc (doc "A more advanced way to define macros than \"macro:\"."
+  {#.doc (doc "A more advanced way to define macros than 'macro:'."
               "The inputs to the macro can be parsed in complex ways through the use of syntax parsers."
               "The macro body is also (implicitly) run in the Monad, to save some typing."
               "Also, the compiler state can be accessed through the *compiler* binding."
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index 5ac8e16da..e24779057 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -29,7 +29,7 @@
   (r.Random Text)
   (do r.Monad
     [#let [digits "0123456789"
-           delimiters "()[]{}#.\""
+           delimiters (format "()[]{}#." &.text-delimiter)
            space " \n"
            invalid-range (format digits delimiters space)
            char-gen (|> r.nat
@@ -129,48 +129,9 @@
   (<| (seed 12137892244981970631)
       ## (times 100)
       (do @
-        [#let [char-gen (|> r.nat (r.filter (function (_ value)
-                                              (not (or (text.space? value)
-                                                       (n/= (char "\"") value))))))]
-         x char-gen
-         y char-gen
-         z char-gen
-         offset-size (|> r.nat (r/map (|>> (n/% 10) (n/max 1))))
-         #let [offset (text.join-with "" (list.repeat offset-size " "))]
-         sample code^
-         comment comment^
-         unbalanced-comment comment-text^]
+        [sample code^
+         comment comment^]
         ($_ seq
-            (test "Will reject invalid multi-line text."
-                  (let [bad-match (format (text.from-code x) "\n"
-                                          (text.from-code y) "\n"
-                                          (text.from-code z))]
-                    (case (&.read "" (dict.new text.Hash)
-                                  [default-cursor 0
-                                   (format "\"" bad-match "\"")])
-                      (#e.Error error)
-                      #1
-
-                      (#e.Success [_ parsed])
-                      #0)))
-            (test "Will accept valid multi-line text"
-                  (let [good-input (format (text.from-code x) "\n"
-                                           offset (text.from-code y) "\n"
-                                           offset (text.from-code z))
-                        good-output (format (text.from-code x) "\n"
-                                            (text.from-code y) "\n"
-                                            (text.from-code z))]
-                    (case (&.read "" (dict.new text.Hash)
-                                  [(|> default-cursor (update@ #.column (n/+ (dec offset-size))))
-                                   0
-                                   (format "\"" good-input "\"")])
-                      (#e.Error error)
-                      #0
-
-                      (#e.Success [_ parsed])
-                      (:: code.Equivalence =
-                          parsed
-                          (code.text good-output)))))
             (test "Can handle comments."
                   (case (&.read "" (dict.new text.Hash)
                                 [default-cursor 0
diff --git a/stdlib/test/test/lux/data/text/format.lux b/stdlib/test/test/lux/data/text/format.lux
index bd66712a8..48cf24306 100644
--- a/stdlib/test/test/lux/data/text/format.lux
+++ b/stdlib/test/test/lux/data/text/format.lux
@@ -16,6 +16,6 @@
                    (&/= "+123" (%i +123))
                    (&/= "+123.456" (%f +123.456))
                    (&/= ".5" (%r .5))
-                   (&/= "\"YOLO\"" (%t "YOLO"))
+                   (&/= (format text.double-quote "YOLO" text.double-quote) (%t "YOLO"))
                    (&/= "User-id: +123 -- Active: #1" (format "User-id: " (%i +123) " -- Active: " (%b #1)))))
         )))
diff --git a/stdlib/test/test/lux/host.jvm.lux b/stdlib/test/test/lux/host.jvm.lux
index 8832bb3f6..835bdd719 100644
--- a/stdlib/test/test/lux/host.jvm.lux
+++ b/stdlib/test/test/lux/host.jvm.lux
@@ -88,7 +88,7 @@
                  (&.instance? Object "")
                  (not (&.instance? Object (&.null)))))
 
-      (test "Can run code in a \"synchronized\" block."
+      (test "Can run code in a 'synchronized' block."
             (&.synchronized "" #1))
 
       (test "Can access Class instances."
diff --git a/stdlib/test/test/lux/macro/code.lux b/stdlib/test/test/lux/macro/code.lux
index 1e0d4a606..be53adfad 100644
--- a/stdlib/test/test/lux/macro/code.lux
+++ b/stdlib/test/test/lux/macro/code.lux
@@ -5,7 +5,7 @@
     [monad (#+ do Monad)]]
    [data
     [number]
-    [text ("text/." Equivalence)
+    ["." text ("text/." Equivalence)
      format]]
    [math ["r" random]]
    [macro ["&" code]]]
@@ -22,7 +22,7 @@
                [(&.bit #0)                                  "#0"]
                [(&.int +123)                                "+123"]
                [(&.frac +123.0)                             "+123.0"]
-               [(&.text "\n")                               "\"\\n\""]
+               [(&.text "1234")                               (format text.double-quote "1234" text.double-quote)]
                [(&.tag ["yolo" "lol"])                      "#yolo.lol"]
                [(&.identifier ["yolo" "lol"])               "yolo.lol"]
                [(&.form (list (&.bit #1) (&.int +123)))     "(#1 +123)"]
-- 
cgit v1.2.3


From bc251026c21590da76085bc0bc9abeaa5ec242b6 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 00:56:59 -0400
Subject: No more escaping of new-line.

---
 stdlib/source/lux.lux                              | 496 +++++++++++----------
 .../source/lux/compiler/default/phase/analysis.lux |   2 +-
 .../compiler/default/phase/analysis/expression.lux |   4 +-
 .../compiler/default/phase/analysis/function.lux   |   2 +-
 .../compiler/default/phase/analysis/inference.lux  |   2 +-
 .../lux/compiler/default/phase/extension.lux       |   2 +-
 .../default/phase/extension/analysis/host.jvm.lux  |  40 +-
 stdlib/source/lux/compiler/default/syntax.lux      |  19 +-
 stdlib/source/lux/control/concatenative.lux        |   2 +-
 stdlib/source/lux/control/exception.lux            |   8 +-
 stdlib/source/lux/control/region.lux               |  12 +-
 stdlib/source/lux/data/format/css.lux              |   2 +-
 stdlib/source/lux/data/format/xml.lux              |  10 +-
 stdlib/source/lux/data/number.lux                  |   4 +-
 stdlib/source/lux/data/text.lux                    |  34 +-
 stdlib/source/lux/data/text/regex.lux              |   2 +-
 stdlib/source/lux/interpreter.lux                  |  12 +-
 stdlib/source/lux/io.lux                           |   4 +-
 stdlib/source/lux/macro.lux                        |  10 +-
 stdlib/source/lux/macro/poly.lux                   |   2 +-
 stdlib/source/lux/macro/syntax.lux                 |   2 +-
 stdlib/source/lux/math/modular.lux                 |  10 +-
 stdlib/source/lux/test.lux                         |  16 +-
 stdlib/source/lux/type.lux                         |   4 +-
 stdlib/source/lux/type/check.lux                   |   6 +-
 stdlib/test/test/lux/compiler/default/syntax.lux   |   6 +-
 stdlib/test/test/lux/macro/syntax.lux              |   4 +-
 27 files changed, 360 insertions(+), 357 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 5e14a9806..0417c9a4d 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -3,6 +3,16 @@
   ("lux int char" +34))
  [["" 0 0] (10 (0))])
 
+("lux def" new-line
+ ("lux check" (0 "#Text" (0))
+  ("lux int char" +10))
+ [["" 0 0] (10 (0))])
+
+("lux def" __paragraph
+ ("lux check" (0 "#Text" (0))
+  ("lux text concat" new-line new-line))
+ [["" 0 0] (10 (0))])
+
 ("lux def" dummy-cursor
  ("lux check" (2 (0 "#Text" (0))
                  (2 (0 "#I64" (1 (0 "#Nat" (0)) (0)))
@@ -25,7 +35,7 @@
              [dummy-cursor (0 #1)]]
             (1 [[dummy-cursor (7 ["lux" "doc"])]
                 [dummy-cursor (5 ("lux text concat"
-                                  "The type of things whose type is irrelevant.\n\n"
+                                  ("lux text concat" "The type of things whose type is irrelevant." __paragraph)
                                   "It can be used to write functions or data-structures that can take, or return, anything."))]]
                (0)))))])
 
@@ -41,7 +51,7 @@
              [dummy-cursor (0 #1)]]
             (1 [[dummy-cursor (7 ["lux" "doc"])]
                 [dummy-cursor (5 ("lux text concat"
-                                  "The type of things whose type is undefined.\n\n"
+                                  ("lux text concat" "The type of things whose type is undefined." __paragraph)
                                   "Useful for expressions that cause errors or other 'extraordinary' conditions."))]]
                (0)))))])
 
@@ -104,7 +114,7 @@
                      [dummy-cursor (0 #1)]]
                     (#Cons [[dummy-cursor (7 ["lux" "doc"])]
                             [dummy-cursor (5 ("lux text concat"
-                                              "Natural numbers (unsigned integers).\n\n"
+                                              ("lux text concat" "Natural numbers (unsigned integers)." __paragraph)
                                               "They start at zero (0) and extend in the positive direction."))]]
                            #Nil))))])
 
@@ -130,7 +140,7 @@
                      [dummy-cursor (0 #1)]]
                     (#Cons [[dummy-cursor (7 ["lux" "doc"])]
                             [dummy-cursor (5 ("lux text concat"
-                                              "Fractional numbers that live in the interval [0,1).\n\n"
+                                              ("lux text concat" "Fractional numbers that live in the interval [0,1)." __paragraph)
                                               "Useful for probability, and other domains that work within that interval."))]]
                            #Nil))))])
 
@@ -167,9 +177,7 @@
              (#Cons [[dummy-cursor (7 ["lux" "export?"])]
                      [dummy-cursor (0 #1)]]
                     (#Cons [[dummy-cursor (7 ["lux" "doc"])]
-                            [dummy-cursor (5 ("lux text concat"
-                                              "A name.\n\n"
-                                              "It is used as part of Lux syntax to represent identifiers and tags."))]]
+                            [dummy-cursor (5 "A name. It is used as part of Lux syntax to represent identifiers and tags.")]]
                            #Nil))))])
 
 ## (type: (Maybe a)
@@ -753,9 +761,9 @@
                                                                                                               #Nil)))))))))))))]
                  (#Cons [(tag$ ["lux" "doc"])
                          (text$ ("lux text concat"
-                                 "Represents the state of the Lux compiler during a run.\n\n"
+                                 ("lux text concat" "Represents the state of the Lux compiler during a run." __paragraph)
                                  ("lux text concat"
-                                  "It is provided to macros during their invocation, so they can access compiler data.\n\n"
+                                  ("lux text concat" "It is provided to macros during their invocation, so they can access compiler data." __paragraph)
                                   "Caveat emptor: Avoid fiddling with it, unless you know what you're doing.")))]
                         default-def-meta-exported))))
 
@@ -769,7 +777,7 @@
                                     (#Apply Text Either)))))
  (record$ (#Cons [(tag$ ["lux" "doc"])
                   (text$ ("lux text concat"
-                          "Computations that can have access to the state of the compiler.\n\n"
+                          ("lux text concat" "Computations that can have access to the state of the compiler." __paragraph)
                           "These computations may fail, or modify the state of the compiler."))]
                  (#Cons [(tag$ ["lux" "type-args"])
                          (tuple$ (#Cons (text$ "a") #Nil))]
@@ -1033,9 +1041,9 @@
 (macro:' #export (comment tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Throws away any code given to it.\n\n"
+                         ("lux text concat" "## Throws away any code given to it." __paragraph)
                          ("lux text concat"
-                          "## Great for commenting-out code, while retaining syntax high-lighting and formatting in your text editor.\n\n"
+                          ("lux text concat" "## Great for commenting-out code, while retaining syntax high-lighting and formatting in your text editor." __paragraph)
                           "(comment +1 +2 +3 +4)")))]
                 #Nil)
          (return #Nil))
@@ -1227,11 +1235,11 @@
 (macro:' #export (All tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Universal quantification.\n\n"
+                         ("lux text concat" "## Universal quantification." __paragraph)
                          ("lux text concat"
-                          "(All [a] (-> a a))\n\n"
+                          ("lux text concat" "(All [a] (-> a a))" __paragraph)
                           ("lux text concat"
-                           "## A name can be provided, to specify a recursive type.\n\n"
+                           ("lux text concat" "## A name can be provided, to specify a recursive type." __paragraph)
                            "(All List [a] (| Any [a (List a)]))"))))]
                 #Nil)
          (let'' [self-name tokens] ({(#Cons [_ (#Identifier "" self-name)] tokens)
@@ -1271,11 +1279,11 @@
 (macro:' #export (Ex tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Existential quantification.\n\n"
+                         ("lux text concat" "## Existential quantification." __paragraph)
                          ("lux text concat"
-                          "(Ex [a] [(Codec Text a) a])\n\n"
+                          ("lux text concat" "(Ex [a] [(Codec Text a) a])" __paragraph)
                           ("lux text concat"
-                           "## A name can be provided, to specify a recursive type.\n\n"
+                           ("lux text concat" "## A name can be provided, to specify a recursive type." __paragraph)
                            "(Ex Self [a] [(Codec Text a) a (List (Self a))])"))))]
                 #Nil)
          (let'' [self-name tokens] ({(#Cons [_ (#Identifier "" self-name)] tokens)
@@ -1323,9 +1331,9 @@
 (macro:' #export (-> tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Function types:\n\n"
+                         ("lux text concat" "## Function types:" __paragraph)
                          ("lux text concat"
-                          "(-> Int Int Int)\n\n"
+                          ("lux text concat" "(-> Int Int Int)" __paragraph)
                           "## This is the type of a function that takes 2 Ints and returns an Int.")))]
                 #Nil)
          ({(#Cons output inputs)
@@ -1342,7 +1350,7 @@
 (macro:' #export (list xs)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## List-construction macro.\n\n"
+                         ("lux text concat" "## List-construction macro." __paragraph)
                          "(list +1 +2 +3)"))]
                 #Nil)
          (return (#Cons (list/fold (function'' [head tail]
@@ -1356,9 +1364,9 @@
 (macro:' #export (list& xs)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## List-construction macro, with the last element being a tail-list.\n\n"
+                         ("lux text concat" "## List-construction macro, with the last element being a tail-list." __paragraph)
                          ("lux text concat"
-                          "## In other words, this macro prepends elements to another list.\n\n"
+                          ("lux text concat" "## In other words, this macro prepends elements to another list." __paragraph)
                           "(list& +1 +2 +3 (list +4 +5 +6))")))]
                 #Nil)
          ({(#Cons last init)
@@ -1375,11 +1383,11 @@
 (macro:' #export (& tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Tuple types:\n\n"
+                         ("lux text concat" "## Tuple types:" __paragraph)
                          ("lux text concat"
-                          "(& Text Int Bit)\n\n"
+                          ("lux text concat" "(& Text Int Bit)" __paragraph)
                           ("lux text concat"
-                           "## Any.\n\n"
+                           ("lux text concat" "## Any." __paragraph)
                            "(&)"))))]
                 #Nil)
          ({#Nil
@@ -1394,11 +1402,11 @@
 (macro:' #export (| tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Variant types:\n\n"
+                         ("lux text concat" "## Variant types:" __paragraph)
                          ("lux text concat"
-                          "(| Text Int Bit)\n\n"
+                          ("lux text concat" "(| Text Int Bit)" __paragraph)
                           ("lux text concat"
-                           "## Nothing.\n\n"
+                           ("lux text concat" "## Nothing." __paragraph)
                            "(|)"))))]
                 #Nil)
          ({#Nil
@@ -1575,12 +1583,12 @@
 (macro:' #export (_$ tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Left-association for the application of binary functions over variadic arguments.\n\n"
+                         ("lux text concat" "## Left-association for the application of binary functions over variadic arguments." ..new-line)
                          ("lux text concat"
-                          "(_$ text/compose ''Hello, '' name ''.\\nHow are you?'')\n\n"
+                          ("lux text concat" "(_$ text/compose ''Hello, '' name ''. How are you?'')" ..new-line)
                           ("lux text concat"
-                           "## =>\n\n"
-                           "(text/compose (text/compose ''Hello, '' name) ''.\\nHow are you?'')"))))]
+                           ("lux text concat" "## =>" ..new-line)
+                           "(text/compose (text/compose ''Hello, '' name) ''. How are you?'')"))))]
                 #Nil)
          ({(#Cons op tokens')
            ({(#Cons first nexts)
@@ -1597,12 +1605,12 @@
 (macro:' #export ($_ tokens)
          (#Cons [(tag$ ["lux" "doc"])
                  (text$ ("lux text concat"
-                         "## Right-association for the application of binary functions over variadic arguments.\n\n"
+                         ("lux text concat" "## Right-association for the application of binary functions over variadic arguments." ..new-line)
                          ("lux text concat"
-                          "($_ text/compose ''Hello, '' name ''.\\nHow are you?'')\n\n"
+                          ("lux text concat" "($_ text/compose ''Hello, '' name ''. How are you?'')" ..new-line)
                           ("lux text concat"
-                           "## =>\n\n"
-                           "(text/compose ''Hello, '' (text/compose name ''.\\nHow are you?''))"))))]
+                           ("lux text concat" "## =>" ..new-line)
+                           "(text/compose ''Hello, '' (text/compose name ''. How are you?''))"))))]
                 #Nil)
          ({(#Cons op tokens')
            ({(#Cons last prevs)
@@ -1731,8 +1739,8 @@
 (macro:' #export (if tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "Picks which expression to evaluate based on a bit test value." "\n\n"
-                           "(if #1 ''Oh, yeah!'' ''Aw hell naw!'')" "\n\n"
+                           "Picks which expression to evaluate based on a bit test value." __paragraph
+                           "(if #1 ''Oh, yeah!'' ''Aw hell naw!'')" __paragraph
                            "=> ''Oh, yeah!''"))])
          ({(#Cons test (#Cons then (#Cons else #Nil)))
            (return (list (form$ (list (record$ (list [(bit$ #1)  then]
@@ -1772,7 +1780,7 @@
 (def:''' #export (log! message)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "Logs message to standard output." "\n\n"
+                           "Logs message to standard output." __paragraph
                            "Useful for debugging."))])
          (-> Text Any)
          ("lux io log" message))
@@ -1979,8 +1987,8 @@
 (macro:' #export (primitive tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Macro to treat define new primitive types." "\n\n"
-                           "(primitive ''java.lang.Object'')" "\n\n"
+                           "## Macro to treat define new primitive types." __paragraph
+                           "(primitive ''java.lang.Object'')" __paragraph
                            "(primitive ''java.util.List'' [(primitive ''java.lang.Long'')])"))])
          ({(#Cons [_ (#Text class-name)] #Nil)
            (return (list (form$ (list (tag$ ["lux" "Primitive"]) (text$ class-name) (tag$ ["lux" "Nil"])))))
@@ -2010,8 +2018,8 @@
 (macro:' #export (` tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Hygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms." "\n\n"
-                           "## All unprefixed macros will receive their parent module's prefix if imported; otherwise will receive the prefix of the module on which the quasi-quote is being used." "\n\n"
+                           "## Hygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms." __paragraph
+                           "## All unprefixed macros will receive their parent module's prefix if imported; otherwise will receive the prefix of the module on which the quasi-quote is being used." __paragraph
                            "(` (def: (~ name) (function ((~' _) (~+ args)) (~ body))))"))])
          ({(#Cons template #Nil)
            (do Monad
@@ -2028,7 +2036,7 @@
 (macro:' #export (`' tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Unhygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms." "\n\n"
+                           "## Unhygienic quasi-quotation as a macro. Unquote (~) and unquote-splice (~+) must also be used as forms." __paragraph
                            "(`' (def: (~ name) (function (_ (~+ args)) (~ body))))"))])
          ({(#Cons template #Nil)
            (do Monad
@@ -2042,7 +2050,7 @@
 (macro:' #export (' tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Quotation as a macro." "\n\n"
+                           "## Quotation as a macro." __paragraph
                            "(' YOLO)"))])
          ({(#Cons template #Nil)
            (do Monad
@@ -2056,9 +2064,9 @@
 (macro:' #export (|> tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Piping macro." "\n\n"
-                           "(|> elems (list/map int/encode) (interpose '' '') (fold text/compose ''''))" "\n\n"
-                           "## =>" "\n\n"
+                           "## Piping macro." __paragraph
+                           "(|> elems (list/map int/encode) (interpose '' '') (fold text/compose ''''))" __paragraph
+                           "## =>" __paragraph
                            "(fold text/compose '''' (interpose '' '' (list/map int/encode elems)))"))])
          ({(#Cons [init apps])
            (return (list (list/fold ("lux check" (-> Code Code Code)
@@ -2082,9 +2090,9 @@
 (macro:' #export (<| tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Reverse piping macro." "\n\n"
-                           "(<| (fold text/compose '''') (interpose '' '') (list/map int/encode) elems)" "\n\n"
-                           "## =>" "\n\n"
+                           "## Reverse piping macro." __paragraph
+                           "(<| (fold text/compose '''') (interpose '' '') (list/map int/encode) elems)" __paragraph
+                           "## =>" __paragraph
                            "(fold text/compose '''' (interpose '' '' (list/map int/encode elems)))"))])
          ({(#Cons [init apps])
            (return (list (list/fold ("lux check" (-> Code Code Code)
@@ -2257,10 +2265,10 @@
 (macro:' #export (do-template tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## By specifying a pattern (with holes), and the input data to fill those holes, repeats the pattern as many times as necessary." "\n\n"
-                           "(do-template [ ]" "\n"
-                           "  " "[(def: #export  (-> Int Int) (i/+ ))]" "\n\n"
-                           "  " "[inc +1]" "\n"
+                           "## By specifying a pattern (with holes), and the input data to fill those holes, repeats the pattern as many times as necessary." __paragraph
+                           "(do-template [ ]" ..new-line
+                           "  " "[(def: #export  (-> Int Int) (i/+ ))]" __paragraph
+                           "  " "[inc +1]" ..new-line
                            "  " "[dec -1]"))])
          ({(#Cons [[_ (#Tuple bindings)] (#Cons [[_ (#Tuple templates)] data])])
            ({[(#Some bindings') (#Some data')]
@@ -2608,8 +2616,8 @@
 (def:''' #export (not x)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Bit negation." "\n\n"
-                           "(not #1) => #0" "\n\n"
+                           "## Bit negation." __paragraph
+                           "(not #1) => #0" __paragraph
                            "(not #0) => #1"))])
          (-> Bit Bit)
          (if x #0 #1))
@@ -2820,7 +2828,7 @@
 (macro:' #export (type tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Takes a type expression and returns it's representation as data-structure." "\n\n"
+                           "## Takes a type expression and returns it's representation as data-structure." __paragraph
                            "(type (All [a] (Maybe (List a))))"))])
          ({(#Cons type #Nil)
            (do Monad
@@ -2839,7 +2847,7 @@
 (macro:' #export (: tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## The type-annotation macro." "\n\n"
+                           "## The type-annotation macro." __paragraph
                            "(: (List Int) (list +1 +2 +3))"))])
          ({(#Cons type (#Cons value #Nil))
            (return (list (` ("lux check" (type (~ type)) (~ value)))))
@@ -2851,7 +2859,7 @@
 (macro:' #export (:coerce tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## The type-coercion macro." "\n\n"
+                           "## The type-coercion macro." __paragraph
                            "(:coerce Dinosaur (list +1 +2 +3))"))])
          ({(#Cons type (#Cons value #Nil))
            (return (list (` ("lux coerce" (type (~ type)) (~ value)))))
@@ -2949,8 +2957,8 @@
 (macro:' #export (Rec tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Parameter-less recursive types." "\n\n"
-                           "## A name has to be given to the whole type, to use it within its body." "\n\n"
+                           "## Parameter-less recursive types." __paragraph
+                           "## A name has to be given to the whole type, to use it within its body." __paragraph
                            "(Rec Self [Int (List Self)])"))])
          ({(#Cons [_ (#Identifier "" name)] (#Cons body #Nil))
            (let' [body' (replace-syntax (list [name (` (#.Apply (~ (make-parameter 1)) (~ (make-parameter 0))))])
@@ -2964,11 +2972,11 @@
 (macro:' #export (exec tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Sequential execution of expressions (great for side-effects)." "\n\n"
-                           "(exec" "\n"
-                           "  " "(log! ''#1'')" "\n"
-                           "  " "(log! ''#2'')" "\n"
-                           "  " "(log! ''#3'')" "\n"
+                           "## Sequential execution of expressions (great for side-effects)." __paragraph
+                           "(exec" ..new-line
+                           "  " "(log! ''#1'')" ..new-line
+                           "  " "(log! ''#2'')" ..new-line
+                           "  " "(log! ''#3'')" ..new-line
                            "''YOLO'')"))])
          ({(#Cons value actions)
            (let' [dummy (identifier$ ["" ""])]
@@ -3122,12 +3130,12 @@
 (macro:' #export (case tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## The pattern-matching macro." "\n"
-                           "## Allows the usage of macros within the patterns to provide custom syntax." "\n"
-                           "(case (: (List Int) (list +1 +2 +3))" "\n"
-                           "  " "(#Cons x (#Cons y (#Cons z #Nil)))" "\n"
-                           "  " "(#Some ($_ i/* x y z))" "\n\n"
-                           "  " "_" "\n"
+                           "## The pattern-matching macro." ..new-line
+                           "## Allows the usage of macros within the patterns to provide custom syntax." ..new-line
+                           "(case (: (List Int) (list +1 +2 +3))" ..new-line
+                           "  " "(#Cons x (#Cons y (#Cons z #Nil)))" ..new-line
+                           "  " "(#Some ($_ i/* x y z))" __paragraph
+                           "  " "_" ..new-line
                            "  " "#None)"))])
          ({(#Cons value branches)
            (do Monad
@@ -3141,13 +3149,13 @@
 (macro:' #export (^ tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Macro-expanding patterns." "\n"
-                           "## It's a special macro meant to be used with 'case'." "\n"
-                           "(case (: (List Int) (list +1 +2 +3))" "\n"
-                           "  (^ (list x y z))" "\n"
+                           "## Macro-expanding patterns." ..new-line
+                           "## It's a special macro meant to be used with 'case'." ..new-line
+                           "(case (: (List Int) (list +1 +2 +3))" ..new-line
+                           "  (^ (list x y z))" ..new-line
                            "  (#Some ($_ i/* x y z))"
-                           "\n\n"
-                           "  _" "\n"
+                           __paragraph
+                           "  _" ..new-line
                            "  #None)"))])
          (case tokens
            (#Cons [_ (#Form (#Cons pattern #Nil))] (#Cons body branches))
@@ -3166,17 +3174,17 @@
 (macro:' #export (^or tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Or-patterns." "\n"
-                           "## It's a special macro meant to be used with 'case'." "\n"
+                           "## Or-patterns." ..new-line
+                           "## It's a special macro meant to be used with 'case'." ..new-line
                            "(type: Weekday #Monday #Tuesday #Wednesday #Thursday #Friday #Saturday #Sunday)"
-                           "\n\n"
-                           "(def: (weekend? day)" "\n"
-                           "  (-> Weekday Bit)" "\n"
-                           "  (case day" "\n"
-                           "    (^or #Saturday #Sunday)" "\n"
+                           __paragraph
+                           "(def: (weekend? day)" ..new-line
+                           "  (-> Weekday Bit)" ..new-line
+                           "  (case day" ..new-line
+                           "    (^or #Saturday #Sunday)" ..new-line
                            "    #1"
-                           "\n\n"
-                           "    _" "\n"
+                           __paragraph
+                           "    _" ..new-line
                            "    #0))"))])
          (case tokens
            (^ (list& [_ (#Form patterns)] body branches))
@@ -3204,10 +3212,10 @@
 (macro:' #export (let tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Creates local bindings." "\n"
-                           "## Can (optionally) use pattern-matching macros when binding." "\n"
-                           "(let [x (foo bar)" "\n"
-                           "      y (baz quux)]" "\n"
+                           "## Creates local bindings." ..new-line
+                           "## Can (optionally) use pattern-matching macros when binding." ..new-line
+                           "(let [x (foo bar)" ..new-line
+                           "      y (baz quux)]" ..new-line
                            "  (op x y))"))])
          (case tokens
            (^ (list [_ (#Tuple bindings)] body))
@@ -3230,12 +3238,12 @@
 (macro:' #export (function tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Syntax for creating functions." "\n"
-                           "## Allows for giving the function itself a name, for the sake of recursion." "\n"
-                           "(: (All [a b] (-> a b a))" "\n"
+                           "## Syntax for creating functions." ..new-line
+                           "## Allows for giving the function itself a name, for the sake of recursion." ..new-line
+                           "(: (All [a b] (-> a b a))" ..new-line
                            "   (function (_ x y) x))"
-                           "\n\n"
-                           "(: (All [a b] (-> a b a))" "\n"
+                           __paragraph
+                           "(: (All [a b] (-> a b a))" ..new-line
                            "   (function (const x y) x))"))])
          (case (: (Maybe [Text Code (List Code) Code])
                   (case tokens
@@ -3349,14 +3357,14 @@
 (macro:' #export (def: tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Defines global constants/functions." "\n"
-                           "(def: (rejoin-pair pair)" "\n"
-                           "  (-> [Code Code] (List Code))" "\n"
-                           "  (let [[left right] pair]" "\n"
+                           "## Defines global constants/functions." ..new-line
+                           "(def: (rejoin-pair pair)" ..new-line
+                           "  (-> [Code Code] (List Code))" ..new-line
+                           "  (let [[left right] pair]" ..new-line
                            "    (list left right)))"
-                           "\n\n"
-                           "(def: branching-exponent" "\n"
-                           "  Int" "\n"
+                           __paragraph
+                           "(def: branching-exponent" ..new-line
+                           "  Int" ..new-line
                            "  +5)"))])
          (let [[export? tokens'] (export^ tokens)
                parts (: (Maybe [Code (List Code) (Maybe Code) Code (List [Code Code])])
@@ -3434,15 +3442,15 @@
 (macro:' #export (macro: tokens)
          (list [(tag$ ["lux" "doc"])
                 (text$ ($_ "lux text concat"
-                           "## Macro-definition macro." "\n"
-                           "(macro: #export (name-of tokens)" "\n"
-                           "  (case tokens" "\n"
-                           "    (^template []" "\n"
-                           "      (^ (list [_ ( [prefix name])]))" "\n"
-                           "      (return (list (` [(~ (text$ prefix)) (~ (text$ name))]))))" "\n"
+                           "## Macro-definition macro." ..new-line
+                           "(macro: #export (name-of tokens)" ..new-line
+                           "  (case tokens" ..new-line
+                           "    (^template []" ..new-line
+                           "      (^ (list [_ ( [prefix name])]))" ..new-line
+                           "      (return (list (` [(~ (text$ prefix)) (~ (text$ name))]))))" ..new-line
                            "    ([#Identifier] [#Tag])"
-                           "\n\n"
-                           "    _" "\n"
+                           __paragraph
+                           "    _" ..new-line
                            "    (fail ''Wrong syntax for name-of'')))"))])
          (let [[exported? tokens] (export^ tokens)
                name+args+meta+body?? (: (Maybe [Name (List Code) Code Code])
@@ -3481,17 +3489,17 @@
 
 (macro: #export (signature: tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Definition of signatures ala ML." "\n"
-                    "(signature: #export (Ord a)" "\n"
-                    "  (: (Equivalence a)" "\n"
-                    "     eq)" "\n"
-                    "  (: (-> a a Bit)" "\n"
-                    "     <)" "\n"
-                    "  (: (-> a a Bit)" "\n"
-                    "     <=)" "\n"
-                    "  (: (-> a a Bit)" "\n"
-                    "     >)" "\n"
-                    "  (: (-> a a Bit)" "\n"
+                    "## Definition of signatures ala ML." ..new-line
+                    "(signature: #export (Ord a)" ..new-line
+                    "  (: (Equivalence a)" ..new-line
+                    "     eq)" ..new-line
+                    "  (: (-> a a Bit)" ..new-line
+                    "     <)" ..new-line
+                    "  (: (-> a a Bit)" ..new-line
+                    "     <=)" ..new-line
+                    "  (: (-> a a Bit)" ..new-line
+                    "     >)" ..new-line
+                    "  (: (-> a a Bit)" ..new-line
                     "     >=))"))}
   (let [[exported? tokens'] (export^ tokens)
         ?parts (: (Maybe [Name (List Code) Code (List Code)])
@@ -3573,8 +3581,8 @@
        _
        (fail )))]
 
-  [and (if (~ pre) (~ post) #0) "'and' requires >=1 clauses." "Short-circuiting 'and'.\n(and #1 #0 #1) ## => #0"]
-  [or  (if (~ pre) #1 (~ post))  "'or' requires >=1 clauses."  "Short-circuiting 'or'.\n(or #1 #0 #1) ## => #1"])
+  [and (if (~ pre) (~ post) #0) "'and' requires >=1 clauses." "Short-circuiting 'and': (and #1 #0 #1) ## => #0"]
+  [or  (if (~ pre) #1 (~ post)) "'or' requires >=1 clauses."  "Short-circuiting 'or': (or #1 #0 #1) ## => #1"])
 
 (def: (index-of part text)
   (-> Text Text (Maybe Nat))
@@ -3608,18 +3616,18 @@
 
 (def: #export (error! message)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Causes an error, with the given error message." "\n"
+                    "## Causes an error, with the given error message." ..new-line
                     "(error! ''OH NO!'')"))}
   (-> Text Nothing)
   ("lux io error" message))
 
 (macro: (default tokens state)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Allows you to provide a default value that will be used" "\n"
+                    "## Allows you to provide a default value that will be used" ..new-line
                     "## if a (Maybe x) value turns out to be #.None."
-                    "\n\n"
+                    __paragraph
                     "(default +20 (#.Some +10)) ## => +10"
-                    "\n\n"
+                    __paragraph
                     "(default +20 #.None) ## => +20"))}
   (case tokens
     (^ (list else maybe))
@@ -3894,18 +3902,18 @@
 
 (macro: #export (structure: tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Definition of structures ala ML." "\n"
-                    "(structure: #export Ord (Ord Int)" "\n"
-                    "  (def: eq Equivalence)" "\n"
-                    "  (def: (< test subject)" "\n"
-                    "    (lux.i/< test subject))" "\n"
-                    "  (def: (<= test subject)" "\n"
-                    "    (or (lux.i/< test subject)" "\n"
-                    "        (lux.i/= test subject)))" "\n"
-                    "  (def: (> test subject)" "\n"
-                    "    (lux.i/> test subject))" "\n"
-                    "  (def: (>= test subject)" "\n"
-                    "    (or (lux.i/> test subject)" "\n"
+                    "## Definition of structures ala ML." ..new-line
+                    "(structure: #export Ord (Ord Int)" ..new-line
+                    "  (def: eq Equivalence)" ..new-line
+                    "  (def: (< test subject)" ..new-line
+                    "    (lux.i/< test subject))" ..new-line
+                    "  (def: (<= test subject)" ..new-line
+                    "    (or (lux.i/< test subject)" ..new-line
+                    "        (lux.i/= test subject)))" ..new-line
+                    "  (def: (> test subject)" ..new-line
+                    "    (lux.i/> test subject))" ..new-line
+                    "  (def: (>= test subject)" ..new-line
+                    "    (or (lux.i/> test subject)" ..new-line
                     "        (lux.i/= test subject))))"))}
   (let [[exported? tokens'] (export^ tokens)
         ?parts (: (Maybe [Code (List Code) Code Code (List Code)])
@@ -3978,7 +3986,7 @@
 
 (macro: #export (type: tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## The type-definition macro." "\n"
+                    "## The type-definition macro." ..new-line
                     "(type: (List a) #Nil (#Cons a (List a)))"))}
   (let [[exported? tokens'] (export^ tokens)
         [rec? tokens'] (case tokens'
@@ -4211,9 +4219,9 @@
                        _ ($_ text/compose prefix "/" clean))]
           (return output))
         (fail ($_ "lux text concat"
-                  "Cannot climb the module hierarchy...\n"
-                  "Importing module: " module "\n"
-                  "   Relative Root: " relative-root "\n"))))))
+                  "Cannot climb the module hierarchy..." ..new-line
+                  "Importing module: " module ..new-line
+                  "   Relative Root: " relative-root ..new-line))))))
 
 (def: (parse-imports nested? relative-root imports)
   (-> Bit Text (List Code) (Meta (List Importation)))
@@ -4497,10 +4505,10 @@
 
 (macro: #export (^open tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Same as the 'open' macro, but meant to be used as a pattern-matching macro for generating local bindings." "\n"
-                    "## Takes an 'alias' text for the generated local bindings." "\n"
-                    "(def: #export (range (^open ''.'') from to)" "\n"
-                    "  (All [a] (-> (Enum a) a a (List a)))" "\n"
+                    "## Same as the 'open' macro, but meant to be used as a pattern-matching macro for generating local bindings." ..new-line
+                    "## Takes an 'alias' text for the generated local bindings." ..new-line
+                    "(def: #export (range (^open ''.'') from to)" ..new-line
+                    "  (All [a] (-> (Enum a) a a (List a)))" ..new-line
                     "  (range' <= succ from to))"))}
   (case tokens
     (^ (list& [_ (#Form (list [_ (#Text alias)]))] body branches))
@@ -4548,11 +4556,11 @@
 
 (macro: #export (cond tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Branching structures with multiple test conditions." "\n"
-                    "(cond (n/even? num) ''even''" "\n"
+                    "## Branching structures with multiple test conditions." ..new-line
+                    "(cond (n/even? num) ''even''" ..new-line
                     "      (n/odd? num) ''odd''"
-                    "\n\n"
-                    "      ## else-branch" "\n"
+                    __paragraph
+                    "      ## else-branch" ..new-line
                     "      ''???'')"))}
   (if (n/= 0 (n/% 2 (list/size tokens)))
     (fail "cond requires an uneven number of arguments.")
@@ -4583,14 +4591,14 @@
 
 (macro: #export (get@ tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Accesses the value of a record at a given tag." "\n"
+                    "## Accesses the value of a record at a given tag." ..new-line
                     "(get@ #field my-record)"
-                    "\n\n"
-                    "## Can also work with multiple levels of nesting:" "\n"
+                    __paragraph
+                    "## Can also work with multiple levels of nesting:" ..new-line
                     "(get@ [#foo #bar #baz] my-record)"
-                    "\n\n"
-                    "## And, if only the slot/path is given, generates an accessor function:" "\n"
-                    "(let [getter (get@ [#foo #bar #baz])]" "\n"
+                    __paragraph
+                    "## And, if only the slot/path is given, generates an accessor function:" ..new-line
+                    "(let [getter (get@ [#foo #bar #baz])]" ..new-line
                     "  (getter my-record))"))}
   (case tokens
     (^ (list [_ (#Tag slot')] record))
@@ -4652,14 +4660,14 @@
 (macro: #export (open: tokens)
   {#.doc (text$ ($_ "lux text concat"
                     "## Opens a structure and generates a definition for each of its members (including nested members)."
-                    "\n\n"
-                    "## For example:" "\n"
+                    __paragraph
+                    "## For example:" ..new-line
                     "(open: ''i:.'' Number)"
-                    "\n\n"
-                    "## Will generate:" "\n"
-                    "(def: i:+ (:: Number +))" "\n"
-                    "(def: i:- (:: Number -))" "\n"
-                    "(def: i:* (:: Number *))" "\n"
+                    __paragraph
+                    "## Will generate:" ..new-line
+                    "(def: i:+ (:: Number +))" ..new-line
+                    "(def: i:- (:: Number -))" ..new-line
+                    "(def: i:* (:: Number *))" ..new-line
                     "..."))}
   (case tokens
     (^ (list [_ (#Text alias)] struct))
@@ -4693,9 +4701,9 @@
 
 (macro: #export (|>> tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." "\n"
-                    "(|>> (list/map int/encode) (interpose '' '') (fold text/compose ''''))" "\n"
-                    "## =>" "\n"
+                    "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." ..new-line
+                    "(|>> (list/map int/encode) (interpose '' '') (fold text/compose ''''))" ..new-line
+                    "## =>" ..new-line
                     "(function (_ ) (fold text/compose '''' (interpose '' '' (list/map int/encode ))))"))}
   (do Monad
     [g!_ (gensym "_")
@@ -4704,9 +4712,9 @@
 
 (macro: #export (<<| tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." "\n"
-                    "(<<| (fold text/compose '''') (interpose '' '') (list/map int/encode))" "\n"
-                    "## =>" "\n"
+                    "## Similar to the piping macro, but rather than taking an initial object to work on, creates a function for taking it." ..new-line
+                    "(<<| (fold text/compose '''') (interpose '' '') (list/map int/encode))" ..new-line
+                    "## =>" ..new-line
                     "(function (_ ) (fold text/compose '''' (interpose '' '' (list/map int/encode ))))"))}
   (do Monad
     [g!_ (gensym "_")
@@ -4744,10 +4752,10 @@
 
       _
       (fail ($_ text/compose "Wrong syntax for refer @ " current-module
-                "\n" (|> options
-                         (list/map code-to-text)
-                         (interpose " ")
-                         (list/fold text/compose "")))))))
+                ..new-line (|> options
+                               (list/map code-to-text)
+                               (interpose " ")
+                               (list/fold text/compose "")))))))
 
 (def: (write-refer module-name [r-defs r-opens])
   (-> Text Refer (Meta (List Code)))
@@ -4833,20 +4841,20 @@
 (macro: #export (module: tokens)
   {#.doc (text$ ($_ "lux text concat"
                     "## Module-definition macro."
-                    "\n\n"
+                    __paragraph
                     "## Can take optional annotations and allows the specification of modules to import."
-                    "\n\n"
-                    "## Example" "\n"
-                    "(.module: {#.doc ''Some documentation...''}" "\n"
-                    "  [lux #*" "\n"
-                    "   [control" "\n"
-                    "    [''M'' monad #*]]" "\n"
-                    "   [data" "\n"
-                    "    maybe" "\n"
-                    "    [''.'' name (''name/.'' Codec)]]" "\n"
-                    "   [macro" "\n"
-                    "    code]]" "\n"
-                    "  [//" "\n"
+                    __paragraph
+                    "## Example" ..new-line
+                    "(.module: {#.doc ''Some documentation...''}" ..new-line
+                    "  [lux #*" ..new-line
+                    "   [control" ..new-line
+                    "    [''M'' monad #*]]" ..new-line
+                    "   [data" ..new-line
+                    "    maybe" ..new-line
+                    "    [''.'' name (''name/.'' Codec)]]" ..new-line
+                    "   [macro" ..new-line
+                    "    code]]" ..new-line
+                    "  [//" ..new-line
                     "   [type (''.'' Equivalence)]])"))}
   (do Monad
     [#let [[_meta _imports] (: [(List [Code Code]) (List Code)]
@@ -4874,10 +4882,10 @@
 
 (macro: #export (:: tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Allows accessing the value of a structure's member." "\n"
+                    "## Allows accessing the value of a structure's member." ..new-line
                     "(:: Codec encode)"
-                    "\n\n"
-                    "## Also allows using that value as a function." "\n"
+                    __paragraph
+                    "## Also allows using that value as a function." ..new-line
                     "(:: Codec encode +123)"))}
   (case tokens
     (^ (list struct [_ (#Identifier member)]))
@@ -4891,14 +4899,14 @@
 
 (macro: #export (set@ tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Sets the value of a record at a given tag." "\n"
+                    "## Sets the value of a record at a given tag." ..new-line
                     "(set@ #name ''Lux'' lang)"
-                    "\n\n"
-                    "## Can also work with multiple levels of nesting:" "\n"
+                    __paragraph
+                    "## Can also work with multiple levels of nesting:" ..new-line
                     "(set@ [#foo #bar #baz] value my-record)"
-                    "\n\n"
-                    "## And, if only the slot/path and (optionally) the value are given, generates a mutator function:" "\n"
-                    "(let [setter (set@ [#foo #bar #baz] value)] (setter my-record))" "\n"
+                    __paragraph
+                    "## And, if only the slot/path and (optionally) the value are given, generates a mutator function:" ..new-line
+                    "(let [setter (set@ [#foo #bar #baz] value)] (setter my-record))" ..new-line
                     "(let [setter (set@ [#foo #bar #baz])] (setter value my-record))"))}
   (case tokens
     (^ (list [_ (#Tag slot')] value record))
@@ -4978,14 +4986,14 @@
 
 (macro: #export (update@ tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## Modifies the value of a record at a given tag, based on some function." "\n"
+                    "## Modifies the value of a record at a given tag, based on some function." ..new-line
                     "(update@ #age inc person)"
-                    "\n\n"
-                    "## Can also work with multiple levels of nesting:" "\n"
+                    __paragraph
+                    "## Can also work with multiple levels of nesting:" ..new-line
                     "(update@ [#foo #bar #baz] func my-record)"
-                    "\n\n"
-                    "## And, if only the slot/path and (optionally) the value are given, generates a mutator function:" "\n"
-                    "(let [updater (update@ [#foo #bar #baz] func)] (updater my-record))" "\n"
+                    __paragraph
+                    "## And, if only the slot/path and (optionally) the value are given, generates a mutator function:" ..new-line
+                    "(let [updater (update@ [#foo #bar #baz] func)] (updater my-record))" ..new-line
                     "(let [updater (update@ [#foo #bar #baz])] (updater func my-record))"))}
   (case tokens
     (^ (list [_ (#Tag slot')] fun record))
@@ -5051,38 +5059,38 @@
 
 (macro: #export (^template tokens)
   {#.doc (text$ ($_ "lux text concat"
-                    "## It's similar to do-template, but meant to be used during pattern-matching." "\n"
-                    "(def: (beta-reduce env type)" "\n"
-                    "  (-> (List Type) Type Type)" "\n"
-                    "  (case type" "\n"
-                    "    (#.Primitive name params)" "\n"
+                    "## It's similar to do-template, but meant to be used during pattern-matching." ..new-line
+                    "(def: (beta-reduce env type)" ..new-line
+                    "  (-> (List Type) Type Type)" ..new-line
+                    "  (case type" ..new-line
+                    "    (#.Primitive name params)" ..new-line
                     "    (#.Primitive name (list/map (beta-reduce env) params))"
-                    "\n\n"
-                    "    (^template []" "\n"
-                    "      ( left right)" "\n"
-                    "      ( (beta-reduce env left) (beta-reduce env right)))" "\n"
+                    __paragraph
+                    "    (^template []" ..new-line
+                    "      ( left right)" ..new-line
+                    "      ( (beta-reduce env left) (beta-reduce env right)))" ..new-line
                     "    ([#.Sum] [#.Product])"
-                    "\n\n"
-                    "    (^template []" "\n"
-                    "      ( left right)" "\n"
-                    "      ( (beta-reduce env left) (beta-reduce env right)))" "\n"
+                    __paragraph
+                    "    (^template []" ..new-line
+                    "      ( left right)" ..new-line
+                    "      ( (beta-reduce env left) (beta-reduce env right)))" ..new-line
                     "    ([#.Function] [#.Apply])"
-                    "\n\n"
-                    "    (^template []" "\n"
-                    "      ( old-env def)" "\n"
-                    "      (case old-env" "\n"
-                    "        #.Nil" "\n"
+                    __paragraph
+                    "    (^template []" ..new-line
+                    "      ( old-env def)" ..new-line
+                    "      (case old-env" ..new-line
+                    "        #.Nil" ..new-line
                     "        ( env def)"
-                    "\n\n"
-                    "        _" "\n"
-                    "        type))" "\n"
+                    __paragraph
+                    "        _" ..new-line
+                    "        type))" ..new-line
                     "    ([#.UnivQ] [#.ExQ])"
-                    "\n\n"
-                    "    (#.Parameter idx)" "\n"
+                    __paragraph
+                    "    (#.Parameter idx)" ..new-line
                     "    (default type (list.nth idx env))"
-                    "\n\n"
-                    "    _" "\n"
-                    "    type" "\n"
+                    __paragraph
+                    "    _" ..new-line
+                    "    type" ..new-line
                     "  ))"))}
   (case tokens
     (^ (list& [_ (#Form (list& [_ (#Tuple bindings)] templates))]
@@ -5196,7 +5204,7 @@
   (-> Nat Cursor Cursor Text)
   (if (n/= old-line new-line)
     (text/join (repeat (.int (n/- old-column new-column)) " "))
-    (let [extra-lines (text/join (repeat (.int (n/- old-line new-line)) "\n"))
+    (let [extra-lines (text/join (repeat (.int (n/- old-line new-line)) ..new-line))
           space-padding (text/join (repeat (.int (n/- baseline new-column)) " "))]
       (text/compose extra-lines space-padding))))
 
@@ -5262,27 +5270,27 @@
   (case fragment
     (#Doc-Comment comment)
     (|> comment
-        (text/split "\n")
-        (list/map (function (_ line) ($_ text/compose "## " line "\n")))
+        (text/split ..new-line)
+        (list/map (function (_ line) ($_ text/compose "## " line ..new-line)))
         text/join)
 
     (#Doc-Example example)
     (let [baseline (find-baseline-column example)
           [cursor _] example
           [_ text] (doc-example->Text (with-baseline baseline cursor) baseline example)]
-      (text/compose text "\n\n"))))
+      (text/compose text __paragraph))))
 
 (macro: #export (doc tokens)
   {#.doc (text$ ($_ "lux text concat"
                     "## Creates code documentation, embedding text as comments and properly formatting the forms it's being given."
-                    "\n\n"
-                    "## For Example:" "\n"
-                    "(doc ''Allows arbitrary looping, using the \\''recur\\'' form to re-start the loop.''" "\n"
-                    "     ''Can be used in monadic code to create monadic loops.''" "\n"
-                    "     (loop [count +0" "\n"
-                    "            x init]" "\n"
-                    "       (if (< +10 count)" "\n"
-                    "         (recur (inc count) (f x))" "\n"
+                    __paragraph
+                    "## For Example:" ..new-line
+                    "(doc ''Allows arbitrary looping, using the \\''recur\\'' form to re-start the loop.''" ..new-line
+                    "     ''Can be used in monadic code to create monadic loops.''" ..new-line
+                    "     (loop [count +0" ..new-line
+                    "            x init]" ..new-line
+                    "       (if (< +10 count)" ..new-line
+                    "         (recur (inc count) (f x))" ..new-line
                     "         x)))"))}
   (return (list (` [(~ cursor-code)
                     (#.Text (~ (|> tokens
@@ -5489,7 +5497,7 @@
                              [(bit #0)                              "#0"         [_ (#.Bit #0)]]
                              [(int +123)                            "+123"       [_ (#.Int +123)]]
                              [(frac +123.0)                         "+123.0"     [_ (#.Frac +123.0)]]
-                             [(text "\n")                           "'\\n'"      [_ (#.Text "\n")]]
+                             [(text "123")                           "'123'"     [_ (#.Text "123")]]
                              [(tag ["yolo" "lol"])                  "#yolo.lol"  [_ (#.Tag ["yolo" "lol"])]]
                              [(identifier ["yolo" "lol"])           "yolo.lol"   [_ (#.Identifier ["yolo" "lol"])]]
                              [(form (list (bit #1) (int +123)))     "(#1 +123)"  (^ [_ (#.Form (list [_ (#.Bit #1)] [_ (#.Int +123)]))])]
diff --git a/stdlib/source/lux/compiler/default/phase/analysis.lux b/stdlib/source/lux/compiler/default/phase/analysis.lux
index e26cd3516..615075800 100644
--- a/stdlib/source/lux/compiler/default/phase/analysis.lux
+++ b/stdlib/source/lux/compiler/default/phase/analysis.lux
@@ -236,7 +236,7 @@
                            output])
 
           (#error.Error error)
-          (#error.Error (format "@ " (%cursor cursor) "\n"
+          (#error.Error (format "@ " (%cursor cursor) text.new-line
                                 error)))))))
 
 (do-template [   ]
diff --git a/stdlib/source/lux/compiler/default/phase/analysis/expression.lux b/stdlib/source/lux/compiler/default/phase/analysis/expression.lux
index 073cc9950..317f86a6f 100644
--- a/stdlib/source/lux/compiler/default/phase/analysis/expression.lux
+++ b/stdlib/source/lux/compiler/default/phase/analysis/expression.lux
@@ -26,14 +26,14 @@
 (exception: #export (macro-expansion-failed {macro Name} {inputs (List Code)} {error Text})
   (ex.report ["Macro" (%name macro)]
              ["Inputs" (|> inputs
-                           (list/map (|>> %code (format "\n" text.tab)))
+                           (list/map (|>> %code (format text.new-line text.tab)))
                            (text.join-with ""))]
              ["Error" error]))
 
 (exception: #export (macro-call-must-have-single-expansion {macro Name} {inputs (List Code)})
   (ex.report ["Macro" (%name macro)]
              ["Inputs" (|> inputs
-                           (list/map (|>> %code (format "\n" text.tab)))
+                           (list/map (|>> %code (format text.new-line text.tab)))
                            (text.join-with ""))]))
 
 (exception: #export (unrecognized-syntax {code Code})
diff --git a/stdlib/source/lux/compiler/default/phase/analysis/function.lux b/stdlib/source/lux/compiler/default/phase/analysis/function.lux
index 1f0e4c8f9..a996457d9 100644
--- a/stdlib/source/lux/compiler/default/phase/analysis/function.lux
+++ b/stdlib/source/lux/compiler/default/phase/analysis/function.lux
@@ -30,7 +30,7 @@
              ["Arguments" (|> arguments
                               list.enumerate
                               (list/map (.function (_ [idx argC])
-                                          (format "\n  " (%n idx) " " (%code argC))))
+                                          (format text.new-line "  " (%n idx) " " (%code argC))))
                               (text.join-with ""))]))
 
 (def: #export (function analyse function-name arg-name body)
diff --git a/stdlib/source/lux/compiler/default/phase/analysis/inference.lux b/stdlib/source/lux/compiler/default/phase/analysis/inference.lux
index c96d0457c..010bdc437 100644
--- a/stdlib/source/lux/compiler/default/phase/analysis/inference.lux
+++ b/stdlib/source/lux/compiler/default/phase/analysis/inference.lux
@@ -27,7 +27,7 @@
              ["Arguments" (|> args
                               list.enumerate
                               (list/map (function (_ [idx argC])
-                                          (format "\n  " (%n idx) " " (%code argC))))
+                                          (format text.new-line "  " (%n idx) " " (%code argC))))
                               (text.join-with ""))]))
 
 (exception: #export (cannot-infer-argument {inferred Type} {argument Code})
diff --git a/stdlib/source/lux/compiler/default/phase/extension.lux b/stdlib/source/lux/compiler/default/phase/extension.lux
index c7a2048a8..c87d8d54c 100644
--- a/stdlib/source/lux/compiler/default/phase/extension.lux
+++ b/stdlib/source/lux/compiler/default/phase/extension.lux
@@ -49,7 +49,7 @@
              ["Available" (|> bundle
                               dictionary.keys
                               (list.sort text/<)
-                              (list/map (|>> %t (format "\n" text.tab)))
+                              (list/map (|>> %t (format text.new-line text.tab)))
                               (text.join-with ""))]))
 
 (exception: #export (incorrect-arity {name Text} {arity Nat} {args Nat})
diff --git a/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux b/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux
index 31f4b33ff..64edb791b 100644
--- a/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux
+++ b/stdlib/source/lux/compiler/default/phase/extension/analysis/host.jvm.lux
@@ -95,7 +95,7 @@
      (ex.report ["Class" class]
                 ["Method" method]
                 ["Hints" (|> hints
-                             (list/map (|>> product.left %type (format "\n" text.tab)))
+                             (list/map (|>> product.left %type (format text.new-line text.tab)))
                              (text.join-with ""))]))]
 
   [no-candidates]
@@ -643,14 +643,14 @@
           num-type-params (list.size params)]
       (cond (not (text/= class-name name))
             (////.throw cannot-correspond-type-with-a-class
-                        (format "Class = " class-name "\n"
+                        (format "Class = " class-name text.new-line
                                 "Type = " (%type type)))
 
             (not (n/= num-class-params num-type-params))
             (////.throw type-parameter-mismatch
-                        (format "Expected: " (%i (.int num-class-params)) "\n"
-                                "  Actual: " (%i (.int num-type-params)) "\n"
-                                "   Class: " class-name "\n"
+                        (format "Expected: " (%i (.int num-class-params)) text.new-line
+                                "  Actual: " (%i (.int num-type-params)) text.new-line
+                                "   Class: " class-name text.new-line
                                 "    Type: " (%type type)))
 
             ## else
@@ -704,9 +704,9 @@
                                 (wrap #1))
                               (do @
                                 [current-class (load-class current-name)
-                                 _ (////.assert cannot-cast (format "From class/primitive: " current-name "\n"
-                                                                    "  To class/primitive: " to-name "\n"
-                                                                    "           For value: " (%code valueC) "\n")
+                                 _ (////.assert cannot-cast (format "From class/primitive: " current-name text.new-line
+                                                                    "  To class/primitive: " to-name text.new-line
+                                                                    "           For value: " (%code valueC) text.new-line)
                                                 (Class::isAssignableFrom [current-class] to-class))
                                  candiate-parents (monad.map @
                                                              (function (_ java-type)
@@ -726,17 +726,17 @@
                                     (recur [next-name nextT]))
 
                                   #.Nil
-                                  (////.throw cannot-cast (format "From class/primitive: " from-name "\n"
-                                                                  "  To class/primitive: " to-name "\n"
-                                                                  "           For value: " (%code valueC) "\n")))
+                                  (////.throw cannot-cast (format "From class/primitive: " from-name text.new-line
+                                                                  "  To class/primitive: " to-name text.new-line
+                                                                  "           For value: " (%code valueC) text.new-line)))
                                 ))))))]
         (if can-cast?
           (wrap (#analysis.Extension extension-name (list (analysis.text from-name)
                                                           (analysis.text to-name)
                                                           valueA)))
-          (////.throw cannot-cast (format "From class/primitive: " from-name "\n"
-                                          "  To class/primitive: " to-name "\n"
-                                          "           For value: " (%code valueC) "\n"))))
+          (////.throw cannot-cast (format "From class/primitive: " from-name text.new-line
+                                          "  To class/primitive: " to-name text.new-line
+                                          "           For value: " (%code valueC) text.new-line))))
 
       _
       (////.throw ///.invalid-syntax extension-name))))
@@ -764,9 +764,9 @@
         (if (is? owner class)
           (wrap [class field])
           (////.throw mistaken-field-owner
-                      (format "       Field: " field-name "\n"
-                              " Owner Class: " (Class::getName [] owner) "\n"
-                              "Target Class: " class-name "\n"))))
+                      (format "       Field: " field-name text.new-line
+                              " Owner Class: " (Class::getName [] owner) text.new-line
+                              "Target Class: " class-name text.new-line))))
 
       (#e.Error _)
       (////.throw unknown-field (format class-name "#" field-name)))))
@@ -802,9 +802,9 @@
                          [#let [num-params (list.size _class-params)
                                 num-vars (list.size var-names)]
                           _ (////.assert type-parameter-mismatch
-                                         (format "Expected: " (%i (.int num-params)) "\n"
-                                                 "  Actual: " (%i (.int num-vars)) "\n"
-                                                 "   Class: " _class-name "\n"
+                                         (format "Expected: " (%i (.int num-params)) text.new-line
+                                                 "  Actual: " (%i (.int num-vars)) text.new-line
+                                                 "   Class: " _class-name text.new-line
                                                  "    Type: " (%type objectT))
                                          (n/= num-params num-vars))]
                          (wrap (|> (list.zip2 var-names _class-params)
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index faa072d88..92f223940 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -59,7 +59,6 @@
 (def: digits+ (format "_" ..digits))
 
 (def: white-space " ")
-(def: new-line "\n")
 ## (def: new-line^ (l.this new-line))
 
 (def: #export text-delimiter text.double-quote)
@@ -128,7 +127,7 @@
 ##       (:: p.Monad wrap where)))
 
 ## Escaped character sequences follow the usual syntax of
-## back-slash followed by a letter (e.g. \n).
+## back-slash followed by a letter.
 ## Escaped characters may show up in Char and Text literals.
 (def: escaped-char^
   (Lexer [Nat Text])
@@ -137,7 +136,6 @@
              [code l.any]
              (case code
                ## Handle special cases.
-               "n" (wrap [2 ..new-line])
                (^ (static ..escape)) (wrap [2 ..escape])
 
                _
@@ -255,7 +253,7 @@
 ##                                          ($_ p.either
 ##                                              ## Normal text characters.
 ##                                              (do @
-##                                                [normal (l.slice (l.many! (l.none-of! (format ..escape ..text-delimiter ..new-line))))]
+##                                                [normal (l.slice (l.many! (l.none-of! (format ..escape ..text-delimiter text.new-line))))]
 ##                                                (recur (format text-read normal)
 ##                                                       (update@ #.column (n/+ (text.size normal)) where)
 ##                                                       #0))
@@ -373,7 +371,7 @@
 ##                            ..sigil
 ##                            ..text-delimiter
 ##                            ..name-separator)
-##         space (format ..white-space ..new-line)
+##         space (format ..white-space text.new-line)
 ##         head (l.none-of! (format ..digits delimiters space))
 ##         tail (l.some! (l.none-of! (format delimiters space)))]
 ##     (l.slice (l.and! head tail))))
@@ -585,7 +583,7 @@
         (#error.Success [("lux text size" source-code) (!inc end) ])))))
 
 (template: (!guarantee-no-new-lines content body)
-  (case ("lux text index" content (static ..new-line) 0)
+  (case ("lux text index" content (static text.new-line) 0)
     (#.Some g!_)
     (ex.throw ..text-cannot-contain-new-lines content)
 
@@ -604,8 +602,7 @@
             (^template [ ]
               (^ (char ))
               (!find-next-escape 2 next-escape end source-code total ))
-            (["n" (static ..new-line)]
-             [(~~ (static ..escape)) (static ..escape)])
+            ([(~~ (static ..escape)) (static ..escape)])
 
             _
             (ex.throw invalid-escape-syntax []))))))
@@ -666,7 +663,7 @@
 
 (`` (template: (!strict-name-char? char)
       (not (or ("lux i64 =" (.char (~~ (static ..white-space))) char)
-               ("lux i64 =" (.char (~~ (static ..new-line))) char)
+               ("lux i64 =" (.char (~~ (static text.new-line))) char)
 
                ("lux i64 =" (.char (~~ (static ..name-separator))) char)
 
@@ -836,7 +833,7 @@
                   ([(~~ (static ..white-space))     #.column]
                    [(~~ (static text.carriage-return)) #.column])
 
-                  (^ (char (~~ (static ..new-line))))
+                  (^ (char (~~ (static text.new-line))))
                   (recur tracker [(!new-line where) (!inc offset) source-code])
 
                   ## Form
@@ -868,7 +865,7 @@
 
                           ## Single-line comment
                           (^ (char (~~ (static ..sigil))))
-                          (case ("lux text index" source-code (static ..new-line) offset')
+                          (case ("lux text index" source-code (static text.new-line) offset')
                             (#.Some end)
                             (recur tracker [(!new-line where) (!inc end) source-code])
                             
diff --git a/stdlib/source/lux/control/concatenative.lux b/stdlib/source/lux/control/concatenative.lux
index 0011c8956..80fa1b40e 100644
--- a/stdlib/source/lux/control/concatenative.lux
+++ b/stdlib/source/lux/control/concatenative.lux
@@ -63,7 +63,7 @@
       (wrap singleton)
 
       _
-      (macro.fail (format "Cannot expand to more than a single AST/Code node:\n"
+      (macro.fail (format "Cannot expand to more than a single AST/Code node:" text.new-line
                           (|> expansion (list/map %code) (text.join-with " ")))))))
 
 (syntax: #export (=> {aliases aliases^}
diff --git a/stdlib/source/lux/control/exception.lux b/stdlib/source/lux/control/exception.lux
index 085269e54..a906c97aa 100644
--- a/stdlib/source/lux/control/exception.lux
+++ b/stdlib/source/lux/control/exception.lux
@@ -98,7 +98,7 @@
   (macro.with-gensyms [g!descriptor]
     (do @
       [current-module macro.current-module-name
-       #let [descriptor ($_ text/compose "{" current-module "." name "}" "\n")
+       #let [descriptor ($_ text/compose "{" current-module "." name "}" text.new-line)
              g!self (code.local-identifier name)]]
       (wrap (list (` (def: (~+ (csw.export export))
                        (~ g!self)
@@ -122,7 +122,7 @@
                                       (list.repeat (n/- (text.size header)
                                                         largest-header-size))
                                       (text.join-with ""))]
-                      ($_ text/compose padding header ": " message "\n"))))
+                      ($_ text/compose padding header ": " message text.new-line))))
         (text.join-with ""))))
 
 (syntax: #export (report {entries (p.many (s.tuple (p.and s.any s.any)))})
@@ -132,9 +132,9 @@
 
 (def: separator
   ($_ "lux text concat"
-      "\n\n"
+      text.new-line text.new-line
       "-----------------------------------------"
-      "\n\n"))
+      text.new-line text.new-line))
 
 (def: #export (with-stack exception message computation)
   (All [e a] (-> (Exception e) e (Error a) (Error a)))
diff --git a/stdlib/source/lux/control/region.lux b/stdlib/source/lux/control/region.lux
index 7bd43bd09..cfd074f6b 100644
--- a/stdlib/source/lux/control/region.lux
+++ b/stdlib/source/lux/control/region.lux
@@ -7,7 +7,7 @@
     ["ex" exception (#+ Exception exception:)]]
    [data
     ["e" error (#+ Error)]
-    [text
+    ["." text
      format]
     [collection
      [list ("list/." Fold)]]]])
@@ -22,11 +22,11 @@
 
 (def: separator
   Text
-  (format "\n"
-          "-----------------------------------------\n"
-          "-----------------------------------------\n"
-          "-----------------------------------------\n"
-          "\n"))
+  (format text.new-line
+          "-----------------------------------------" text.new-line
+          "-----------------------------------------" text.new-line
+          "-----------------------------------------" text.new-line
+          text.new-line))
 
 (exception: #export [a] (clean-up-error {error Text}
                                         {output (Error a)})
diff --git a/stdlib/source/lux/data/format/css.lux b/stdlib/source/lux/data/format/css.lux
index 083195972..fbdad1885 100644
--- a/stdlib/source/lux/data/format/css.lux
+++ b/stdlib/source/lux/data/format/css.lux
@@ -37,7 +37,7 @@
                   (if (list.empty? style)
                     ""
                     (format selector "{" (inline style) "}"))))
-      (text.join-with "\n")))
+      (text.join-with text.new-line)))
 
 (def: #export (rgb color)
   (-> Color Value)
diff --git a/stdlib/source/lux/data/format/xml.lux b/stdlib/source/lux/data/format/xml.lux
index a5cb39ab5..0ed744b46 100644
--- a/stdlib/source/lux/data/format/xml.lux
+++ b/stdlib/source/lux/data/format/xml.lux
@@ -110,9 +110,9 @@
                 spaced^
                 (p.after (l.this "/"))
                 (l.enclosed ["<" ">"]))]
-    (p.assert ($_ text/compose "Close tag does not match open tag.\n"
-                  "Expected: " (name/encode expected) "\n"
-                  "  Actual: " (name/encode actual) "\n")
+    (p.assert ($_ text/compose "Close tag does not match open tag." text.new-line
+                  "Expected: " (name/encode expected) text.new-line
+                  "  Actual: " (name/encode actual) text.new-line)
               (name/= expected actual))))
 
 (def: comment^
@@ -254,10 +254,12 @@
 (exception: #export (wrong-tag {tag Name})
   (name/encode tag))
 
+(def: blank-line ($_ text/compose text.new-line text.new-line))
+
 (exception: #export (unconsumed-inputs {inputs (List XML)})
   (|> inputs
       (list/map (:: Codec encode))
-      (text.join-with "\n\n")))
+      (text.join-with blank-line)))
 
 (def: #export text
   (Reader Text)
diff --git a/stdlib/source/lux/data/number.lux b/stdlib/source/lux/data/number.lux
index df3e2d353..e45c4ff1c 100644
--- a/stdlib/source/lux/data/number.lux
+++ b/stdlib/source/lux/data/number.lux
@@ -674,9 +674,7 @@
                        encoding
                        " number, generates a Nat, an Int, a Rev or a Frac.")
           underscore "Allows for the presence of underscore in the numbers."
-          description [cursor (#.Text ($_ "lux text concat"
-                                          encoding "\n"
-                                          underscore))]]
+          description [cursor (#.Text ($_ "lux text concat" encoding " " underscore))]]
       (#error.Success [state (list (` (doc (~ description)
                                            (~ example-1)
                                            (~ example-2))))]))
diff --git a/stdlib/source/lux/data/text.lux b/stdlib/source/lux/data/text.lux
index 0c6a5ea45..3807275c1 100644
--- a/stdlib/source/lux/data/text.lux
+++ b/stdlib/source/lux/data/text.lux
@@ -16,6 +16,22 @@
    [compiler
     ["." host]]])
 
+(def: #export from-code
+  (-> Nat Text)
+  (|>> (:coerce Int) "lux int char"))
+
+(do-template [ ]
+  [(def: #export  (from-code ))]
+
+  [back-space 8]
+  [tab 9]
+  [new-line 10]
+  [vertical-tab 11]
+  [form-feed 12]
+  [carriage-return 13]
+  [double-quote 34]
+  )
+
 (def: #export (size x)
   (-> Text Nat)
   ("lux text size" x))
@@ -122,7 +138,7 @@
     (#.Cons sample #.Nil)))
 
 (def: #export split-lines
-  (..split-all-with "\n"))
+  (..split-all-with ..new-line))
 
 (def: #export (replace-once pattern value template)
   (-> Text Text Text Text)
@@ -216,22 +232,6 @@
   (-> Text Text Text)
   (enclose [boundary boundary] content))
 
-(def: #export from-code
-  (-> Nat Text)
-  (|>> (:coerce Int) "lux int char"))
-
-(do-template [ ]
-  [(def: #export  (from-code ))]
-
-  [back-space 8]
-  [tab 9]
-  [new-line 10]
-  [vertical-tab 11]
-  [form-feed 12]
-  [carriage-return 13]
-  [double-quote 34]
-  )
-
 (def: #export encode
   (-> Text Text)
   (..enclose' ..double-quote))
diff --git a/stdlib/source/lux/data/text/regex.lux b/stdlib/source/lux/data/text/regex.lux
index bb2c570e3..ec11c9259 100644
--- a/stdlib/source/lux/data/text/regex.lux
+++ b/stdlib/source/lux/data/text/regex.lux
@@ -465,7 +465,7 @@
               (p.before l.end)
               (l.run pattern))
       (#e.Error error)
-      (macro.fail (format "Error while parsing regular-expression:\n"
+      (macro.fail (format "Error while parsing regular-expression:" //.new-line
                           error))
 
       (#e.Success regex)
diff --git a/stdlib/source/lux/interpreter.lux b/stdlib/source/lux/interpreter.lux
index 6837f24d9..75389db21 100644
--- a/stdlib/source/lux/interpreter.lux
+++ b/stdlib/source/lux/interpreter.lux
@@ -5,7 +5,7 @@
     ["ex" exception (#+ exception:)]]
    [data
     ["." error (#+ Error)]
-    [text ("text/." Equivalence)
+    ["." text ("text/." Equivalence)
      format]]
    [type (#+ :share)
     ["." check]]
@@ -36,16 +36,16 @@
 
 (def: (add-line line [where offset input])
   (-> Text Source Source)
-  [where offset (format input "\n" line)])
+  [where offset (format input text.new-line line)])
 
 (def: exit-command Text "exit")
 
 (def: welcome-message
   Text
-  (format "\n"
-          "Welcome to the interpreter!" "\n"
-          "Type 'exit' to leave." "\n"
-          "\n"))
+  (format text.new-line
+          "Welcome to the interpreter!" text.new-line
+          "Type 'exit' to leave." text.new-line
+          text.new-line))
 
 (def: farewell-message
   Text
diff --git a/stdlib/source/lux/io.lux b/stdlib/source/lux/io.lux
index 96503f10e..c054c5347 100644
--- a/stdlib/source/lux/io.lux
+++ b/stdlib/source/lux/io.lux
@@ -6,9 +6,7 @@
     [monad (#+ do Monad)]
     ["ex" exception (#+ Exception)]]
    [data
-    ["." error (#+ Error)]
-    [collection
-     [list]]]])
+    ["." error (#+ Error)]]])
 
 (type: #export (IO a)
   {#.doc "A type that represents synchronous, effectful computations that may interact with the outside world."}
diff --git a/stdlib/source/lux/macro.lux b/stdlib/source/lux/macro.lux
index 10b5d3b41..5d5c8f0cf 100644
--- a/stdlib/source/lux/macro.lux
+++ b/stdlib/source/lux/macro.lux
@@ -507,17 +507,17 @@
         _
         (let [current-module (|> compiler (get@ #.current-module) (maybe.default "???"))]
           (#e.Error ($_ text/compose
-                        "Unknown definition: " (name/encode name) "\n"
-                        "    Current module: " current-module "\n"
+                        "Unknown definition: " (name/encode name) text.new-line
+                        "    Current module: " current-module text.new-line
                         (case (get current-module (get@ #.modules compiler))
                           (#.Some this-module)
                           ($_ text/compose
-                              "           Imports: " (|> this-module (get@ #.imports) (text.join-with ", ")) "\n"
-                              "           Aliases: " (|> this-module (get@ #.module-aliases) (list/map (function (_ [alias real]) ($_ text/compose alias " => " real))) (text.join-with ", ")) "\n")
+                              "           Imports: " (|> this-module (get@ #.imports) (text.join-with ", ")) text.new-line
+                              "           Aliases: " (|> this-module (get@ #.module-aliases) (list/map (function (_ [alias real]) ($_ text/compose alias " => " real))) (text.join-with ", ")) text.new-line)
 
                           _
                           "")
-                        " All Known modules: " (|> compiler (get@ #.modules) (list/map product.left) (text.join-with ", ")) "\n")))))))
+                        " All Known modules: " (|> compiler (get@ #.modules) (list/map product.left) (text.join-with ", ")) text.new-line)))))))
 
 (def: #export (find-def-type name)
   {#.doc "Looks-up a definition's type in the available modules (including the current one)."}
diff --git a/stdlib/source/lux/macro/poly.lux b/stdlib/source/lux/macro/poly.lux
index 7b3bc49a2..51f7a4885 100644
--- a/stdlib/source/lux/macro/poly.lux
+++ b/stdlib/source/lux/macro/poly.lux
@@ -56,7 +56,7 @@
 
 (exception: #export (unconsumed {remaining (List Type)})
   (ex.report ["Types" (|> remaining
-                          (list/map (|>> %type (format "\n* ")))
+                          (list/map (|>> %type (format text.new-line "* ")))
                           (text.join-with ""))]))
 
 (type: #export Env (Dictionary Nat [Type Code]))
diff --git a/stdlib/source/lux/macro/syntax.lux b/stdlib/source/lux/macro/syntax.lux
index 74901beb9..83137cef0 100644
--- a/stdlib/source/lux/macro/syntax.lux
+++ b/stdlib/source/lux/macro/syntax.lux
@@ -31,7 +31,7 @@
 ## [Utils]
 (def: (remaining-inputs asts)
   (-> (List Code) Text)
-  ($_ text/compose "\nRemaining input: "
+  ($_ text/compose text.new-line "Remaining input: "
       (|> asts (list/map code.to-text) (list.interpose " ") (text.join-with ""))))
 
 ## [Syntaxs]
diff --git a/stdlib/source/lux/math/modular.lux b/stdlib/source/lux/math/modular.lux
index 883febecb..ac141a3c9 100644
--- a/stdlib/source/lux/math/modular.lux
+++ b/stdlib/source/lux/math/modular.lux
@@ -37,15 +37,13 @@
 
 (exception: #export [m] (incorrect-modulus {modulus (Modulus m)}
                                            {parsed Int})
-  ($_ text/compose
-      "Expected: " (int/encode (to-int modulus)) "\n"
-      "  Actual: " (int/encode parsed) "\n"))
+  (ex.report ["Expected" (int/encode (to-int modulus))]
+             ["Actual" (int/encode parsed)]))
 
 (exception: #export [rm sm] (cannot-equalize-moduli {reference (Modulus rm)}
                                                     {sample (Modulus sm)})
-  ($_ text/compose
-      "Reference: " (int/encode (to-int reference)) "\n"
-      "   Sample: " (int/encode (to-int sample)) "\n"))
+  (ex.report ["Reference" (int/encode (to-int reference))]
+             ["Sample" (int/encode (to-int sample))]))
 
 (def: #export (congruent? modulus reference sample)
   (All [m] (-> (Modulus m) Int Int Bit))
diff --git a/stdlib/source/lux/test.lux b/stdlib/source/lux/test.lux
index 5b214579d..b928b1860 100644
--- a/stdlib/source/lux/test.lux
+++ b/stdlib/source/lux/test.lux
@@ -79,9 +79,9 @@
                                      #let [post (io.run instant.now)
                                            _ (log! (format "@ " module " "
                                                            "(" (%duration (instant.span pre post)) ")"
-                                                           "\n"
-                                                           description "\n"
-                                                           "\n" documentation "\n"))]]
+                                                           text.new-line
+                                                           description text.new-line
+                                                           text.new-line documentation text.new-line))]]
                                     (wrap counters)))))
                    (monad.seq @))]
     (wrap (list/fold add-counters start test-runs))))
@@ -99,7 +99,7 @@
 
 (def: (times-failure seed documentation)
   (-> (I64 Any) Text Text)
-  (format "Failed with this seed: " (%n (.nat seed)) "\n"
+  (format "Failed with this seed: " (%n (.nat seed)) text.new-line
           documentation))
 
 (def: #export (times amount test)
@@ -217,9 +217,9 @@
 
 (def: (success-message successes failures)
   (-> Nat Nat Text)
-  (format "Test-suite finished." "\n"
-          (%n successes) " out of " (%n (n/+ failures successes)) " tests passed." "\n"
-          (%n failures) " tests failed." "\n"))
+  (format "Test-suite finished." text.new-line
+          (%n successes) " out of " (%n (n/+ failures successes)) " tests passed." text.new-line
+          (%n failures) " tests failed." text.new-line))
 
 (syntax: #export (run)
   {#.doc (doc "Runs all the tests defined on the current module, and in all imported modules."
@@ -264,4 +264,4 @@
             [[l-counter l-documentation] left
              [r-counter r-documentation] right]
             (wrap [(add-counters l-counter r-counter)
-                   (format l-documentation "\n" r-documentation)])))))
+                   (format l-documentation text.new-line r-documentation)])))))
diff --git a/stdlib/source/lux/type.lux b/stdlib/source/lux/type.lux
index be3b54eed..ff614a328 100644
--- a/stdlib/source/lux/type.lux
+++ b/stdlib/source/lux/type.lux
@@ -345,8 +345,8 @@
       [cursor macro.cursor
        valueT (macro.find-type valueN)
        #let [_ (log! ($_ text/compose
-                         ":log!" " @ " (.cursor-description cursor) "\n"
-                         (name/encode valueN) " : " (..to-text valueT) "\n"))]]
+                         ":log!" " @ " (.cursor-description cursor) text.new-line
+                         (name/encode valueN) " : " (..to-text valueT) text.new-line))]]
       (wrap (list (' []))))
 
     (#.Right valueC)
diff --git a/stdlib/source/lux/type/check.lux b/stdlib/source/lux/type/check.lux
index ce5ce652a..97ccc0626 100644
--- a/stdlib/source/lux/type/check.lux
+++ b/stdlib/source/lux/type/check.lux
@@ -10,7 +10,7 @@
     ["." product]
     ["." error (#+ Error)]
     ["." number ("nat/." Codec)]
-    [text ("text/." Monoid Equivalence)]
+    ["." text ("text/." Monoid Equivalence)]
     [collection
      ["." list]
      ["." set (#+ Set)]]]]
@@ -460,7 +460,9 @@
                       _
                       ($_ text/compose
                           (on-error [])
-                          "\n\n-----------------------------------------\n\n"
+                          text.new-line text.new-line
+                          "-----------------------------------------"
+                          text.new-line text.new-line
                           error)))
 
       output
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index e24779057..829199aa8 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -30,7 +30,7 @@
   (do r.Monad
     [#let [digits "0123456789"
            delimiters (format "()[]{}#." &.text-delimiter)
-           space " \n"
+           space (format " " text.new-line)
            invalid-range (format digits delimiters space)
            char-gen (|> r.nat
                         (:: @ map (|>> (n/% 256) (n/max 1)))
@@ -114,7 +114,7 @@
 
 (def: comment-text^
   (r.Random Text)
-  (let [char-gen (|> r.nat (r.filter (|>> (n/= (char "\n")) not)))]
+  (let [char-gen (|> r.nat (r.filter (|>> (n/= (`` (char (~~ (static text.new-line))))) not)))]
     (do r.Monad
       [size (|> r.nat (r/map (n/% 20)))]
       (r.text char-gen size))))
@@ -123,7 +123,7 @@
   (r.Random Text)
   (do r.Monad
     [comment comment-text^]
-    (wrap (format "## " comment "\n"))))
+    (wrap (format "## " comment text.new-line))))
 
 (context: "Multi-line text & comments."
   (<| (seed 12137892244981970631)
diff --git a/stdlib/test/test/lux/macro/syntax.lux b/stdlib/test/test/lux/macro/syntax.lux
index b1e2f445b..0bf7b8804 100644
--- a/stdlib/test/test/lux/macro/syntax.lux
+++ b/stdlib/test/test/lux/macro/syntax.lux
@@ -75,9 +75,9 @@
                       ["Can parse Bit syntax."        #1             code.bit        bit.Equivalence    s.bit]
                       ["Can parse Nat syntax."        123           code.nat        number.Equivalence  s.nat]
                       ["Can parse Int syntax."        +123            code.int        number.Equivalence  s.int]
-                      ["Can parse Rev syntax."       .123            code.rev        number.Equivalence  s.rev]
+                      ["Can parse Rev syntax."       .123             code.rev        number.Equivalence  s.rev]
                       ["Can parse Frac syntax."       +123.0          code.frac       number.Equivalence s.frac]
-                      ["Can parse Text syntax."       "\n"           code.text       text.Equivalence   s.text]
+                      ["Can parse Text syntax."       text.new-line   code.text       text.Equivalence   s.text]
                       ["Can parse Identifier syntax." ["yolo" "lol"] code.identifier name.Equivalence   s.identifier]
                       ["Can parse Tag syntax."        ["yolo" "lol"] code.tag        name.Equivalence   s.tag]
                       )]
-- 
cgit v1.2.3


From 7e312258b13c5fc9c80079fede0e41d479a8a327 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 01:24:29 -0400
Subject: No more escaping of back-slash.

---
 stdlib/source/lux.lux                         |   2 +-
 stdlib/source/lux/compiler/default/name.lux   |   2 +-
 stdlib/source/lux/compiler/default/syntax.lux |   2 +-
 stdlib/source/lux/data/format/json.lux        |  20 ++---
 stdlib/source/lux/data/text/regex.lux         |  74 +++++++++----------
 stdlib/test/test/lux/data/text/regex.lux      | 102 +++++++++++++-------------
 6 files changed, 101 insertions(+), 101 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 0417c9a4d..bfbfe0678 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -5285,7 +5285,7 @@
                     "## Creates code documentation, embedding text as comments and properly formatting the forms it's being given."
                     __paragraph
                     "## For Example:" ..new-line
-                    "(doc ''Allows arbitrary looping, using the \\''recur\\'' form to re-start the loop.''" ..new-line
+                    "(doc ''Allows arbitrary looping, using the 'recur' form to re-start the loop.''" ..new-line
                     "     ''Can be used in monadic code to create monadic loops.''" ..new-line
                     "     (loop [count +0" ..new-line
                     "            x init]" ..new-line
diff --git a/stdlib/source/lux/compiler/default/name.lux b/stdlib/source/lux/compiler/default/name.lux
index ddbf9ee8f..925b0585d 100644
--- a/stdlib/source/lux/compiler/default/name.lux
+++ b/stdlib/source/lux/compiler/default/name.lux
@@ -12,7 +12,7 @@
     (^ (char "+")) "_PLUS_"
     (^ (char "-")) "_DASH_"
     (^ (char "/")) "_SLASH_"
-    (^ (char "\\")) "_BSLASH_"
+    (^ (char "\")) "_BSLASH_"
     (^ (char "_")) "_UNDERS_"
     (^ (char "%")) "_PERCENT_"
     (^ (char "$")) "_DOLLAR_"
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 92f223940..778588959 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -73,7 +73,7 @@
 (def: #export open-record "{")
 (def: #export close-record "}")
 
-(def: escape "\\")
+(def: escape "\")
 
 (def: #export sigil "#")
 
diff --git a/stdlib/source/lux/data/format/json.lux b/stdlib/source/lux/data/format/json.lux
index 9189b375f..20f059503 100644
--- a/stdlib/source/lux/data/format/json.lux
+++ b/stdlib/source/lux/data/format/json.lux
@@ -452,29 +452,29 @@
 (def: escaped~
   (l.Lexer Text)
   ($_ p.either
-      (p.after (l.this "\\t")
+      (p.after (l.this "\t")
                (parser/wrap text.tab))
-      (p.after (l.this "\\b")
+      (p.after (l.this "\b")
                (parser/wrap text.back-space))
-      (p.after (l.this "\\n")
+      (p.after (l.this "\n")
                (parser/wrap text.new-line))
-      (p.after (l.this "\\r")
+      (p.after (l.this "\r")
                (parser/wrap text.carriage-return))
-      (p.after (l.this "\\f")
+      (p.after (l.this "\f")
                (parser/wrap text.form-feed))
-      (p.after (l.this (text/compose "\\" text.double-quote))
+      (p.after (l.this (text/compose "\" text.double-quote))
                (parser/wrap text.double-quote))
-      (p.after (l.this "\\\\")
-               (parser/wrap "\\"))))
+      (p.after (l.this "\\")
+               (parser/wrap "\"))))
 
 (def: string~
   (l.Lexer String)
   (<| (l.enclosed [text.double-quote text.double-quote])
       (loop [_ []])
       (do p.Monad
-        [chars (l.some (l.none-of (text/compose "\\" text.double-quote)))
+        [chars (l.some (l.none-of (text/compose "\" text.double-quote)))
          stop l.peek])
-      (if (text/= "\\" stop)
+      (if (text/= "\" stop)
         (do @
           [escaped escaped~
            next-chars (recur [])]
diff --git a/stdlib/source/lux/data/text/regex.lux b/stdlib/source/lux/data/text/regex.lux
index ec11c9259..ba0128b7b 100644
--- a/stdlib/source/lux/data/text/regex.lux
+++ b/stdlib/source/lux/data/text/regex.lux
@@ -20,12 +20,12 @@
 ## [Utils]
 (def: regex-char^
   (l.Lexer Text)
-  (l.none-of "\\.|&()[]{}"))
+  (l.none-of "\.|&()[]{}"))
 
 (def: escaped-char^
   (l.Lexer Text)
   (do p.Monad
-    [? (l.this? "\\")]
+    [? (l.this? "\")]
     (if ?
       l.any
       regex-char^)))
@@ -75,7 +75,7 @@
 (def: (re-var^ current-module)
   (-> Text (l.Lexer Code))
   (do p.Monad
-    [name (l.enclosed ["\\@<" ">"] (name^ current-module))]
+    [name (l.enclosed ["\@<" ">"] (name^ current-module))]
     (wrap (` (: (l.Lexer Text) (~ (code.identifier name)))))))
 
 (def: re-range^
@@ -135,7 +135,7 @@
 
 (def: punct^
   (l.Lexer Text)
-  (l.one-of (format "!#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
+  (l.one-of (format "!#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
                     //.double-quote)))
 
 (def: graph^
@@ -153,27 +153,27 @@
     []
     ($_ p.either
         (p.after (l.this ".") (wrap (` l.any)))
-        (p.after (l.this "\\d") (wrap (` l.decimal)))
-        (p.after (l.this "\\D") (wrap (` (l.not l.decimal))))
-        (p.after (l.this "\\s") (wrap (` l.space)))
-        (p.after (l.this "\\S") (wrap (` (l.not l.space))))
-        (p.after (l.this "\\w") (wrap (` (~! word^))))
-        (p.after (l.this "\\W") (wrap (` (l.not (~! word^)))))
-
-        (p.after (l.this "\\p{Lower}") (wrap (` l.lower)))
-        (p.after (l.this "\\p{Upper}") (wrap (` l.upper)))
-        (p.after (l.this "\\p{Alpha}") (wrap (` l.alpha)))
-        (p.after (l.this "\\p{Digit}") (wrap (` l.decimal)))
-        (p.after (l.this "\\p{Alnum}") (wrap (` l.alpha-num)))
-        (p.after (l.this "\\p{Space}") (wrap (` l.space)))
-        (p.after (l.this "\\p{HexDigit}") (wrap (` l.hexadecimal)))
-        (p.after (l.this "\\p{OctDigit}") (wrap (` l.octal)))
-        (p.after (l.this "\\p{Blank}") (wrap (` (~! blank^))))
-        (p.after (l.this "\\p{ASCII}") (wrap (` (~! ascii^))))
-        (p.after (l.this "\\p{Contrl}") (wrap (` (~! control^))))
-        (p.after (l.this "\\p{Punct}") (wrap (` (~! punct^))))
-        (p.after (l.this "\\p{Graph}") (wrap (` (~! graph^))))
-        (p.after (l.this "\\p{Print}") (wrap (` (~! print^))))
+        (p.after (l.this "\d") (wrap (` l.decimal)))
+        (p.after (l.this "\D") (wrap (` (l.not l.decimal))))
+        (p.after (l.this "\s") (wrap (` l.space)))
+        (p.after (l.this "\S") (wrap (` (l.not l.space))))
+        (p.after (l.this "\w") (wrap (` (~! word^))))
+        (p.after (l.this "\W") (wrap (` (l.not (~! word^)))))
+
+        (p.after (l.this "\p{Lower}") (wrap (` l.lower)))
+        (p.after (l.this "\p{Upper}") (wrap (` l.upper)))
+        (p.after (l.this "\p{Alpha}") (wrap (` l.alpha)))
+        (p.after (l.this "\p{Digit}") (wrap (` l.decimal)))
+        (p.after (l.this "\p{Alnum}") (wrap (` l.alpha-num)))
+        (p.after (l.this "\p{Space}") (wrap (` l.space)))
+        (p.after (l.this "\p{HexDigit}") (wrap (` l.hexadecimal)))
+        (p.after (l.this "\p{OctDigit}") (wrap (` l.octal)))
+        (p.after (l.this "\p{Blank}") (wrap (` (~! blank^))))
+        (p.after (l.this "\p{ASCII}") (wrap (` (~! ascii^))))
+        (p.after (l.this "\p{Contrl}") (wrap (` (~! control^))))
+        (p.after (l.this "\p{Punct}") (wrap (` (~! punct^))))
+        (p.after (l.this "\p{Graph}") (wrap (` (~! graph^))))
+        (p.after (l.this "\p{Print}") (wrap (` (~! print^))))
         )))
 
 (def: re-class^
@@ -189,11 +189,11 @@
 (def: re-back-reference^
   (l.Lexer Code)
   (p.either (do p.Monad
-              [_ (l.this "\\")
+              [_ (l.this "\")
                id number^]
               (wrap (` ((~! ..copy) (~ (code.identifier ["" (int/encode (.int id))]))))))
             (do p.Monad
-              [_ (l.this "\\k<")
+              [_ (l.this "\k<")
                captured-name name-part^
                _ (l.this ">")]
               (wrap (` ((~! ..copy) (~ (code.identifier ["" captured-name]))))))))
@@ -411,11 +411,11 @@
               (regex ".")
               
               "Escaping"
-              (regex "\\.")
+              (regex "\.")
               
               "Character classes"
-              (regex "\\d")
-              (regex "\\p{Lower}")
+              (regex "\d")
+              (regex "\p{Lower}")
               (regex "[abc]")
               (regex "[a-z]")
               (regex "[a-zA-Z]")
@@ -449,11 +449,11 @@
               "Groups"
               (regex "a(.)c")
               (regex "a(b+)c")
-              (regex "(\\d{3})-(\\d{3})-(\\d{4})")
-              (regex "(\\d{3})-(?:\\d{3})-(\\d{4})")
-              (regex "(?\\d{3})-\\k-(\\d{4})")
-              (regex "(?\\d{3})-\\k-(\\d{4})-\\0")
-              (regex "(\\d{3})-((\\d{3})-(\\d{4}))")
+              (regex "(\d{3})-(\d{3})-(\d{4})")
+              (regex "(\d{3})-(?:\d{3})-(\d{4})")
+              (regex "(?\d{3})-\k-(\d{4})")
+              (regex "(?\d{3})-\k-(\d{4})-\0")
+              (regex "(\d{3})-((\d{3})-(\d{4}))")
               
               "Alternation"
               (regex "a|b")
@@ -477,11 +477,11 @@
                          {branches (p.many s.any)})
   {#.doc (doc "Allows you to test text against regular expressions."
               (case some-text
-                (^regex "(\\d{3})-(\\d{3})-(\\d{4})"
+                (^regex "(\d{3})-(\d{3})-(\d{4})"
                         [_ country-code area-code place-code])
                 do-some-thing-when-number
 
-                (^regex "\\w+")
+                (^regex "\w+")
                 do-some-thing-when-word
 
                 _
diff --git a/stdlib/test/test/lux/data/text/regex.lux b/stdlib/test/test/lux/data/text/regex.lux
index 7c54d8385..3398f4685 100644
--- a/stdlib/test/test/lux/data/text/regex.lux
+++ b/stdlib/test/test/lux/data/text/regex.lux
@@ -53,8 +53,8 @@
   (test "Can parse character literals."
         (and (should-pass (&.regex "a") "a")
              (should-fail (&.regex "a") ".")
-             (should-pass (&.regex "\\.") ".")
-             (should-fail (&.regex "\\.") "a"))))
+             (should-pass (&.regex "\.") ".")
+             (should-fail (&.regex "\.") "a"))))
 
 (context: "Regular Expressions [System character classes]"
   ($_ seq
@@ -62,79 +62,79 @@
             (should-pass (&.regex ".") "a"))
 
       (test "Can parse digits."
-            (and (should-pass (&.regex "\\d") "0")
-                 (should-fail (&.regex "\\d") "m")))
+            (and (should-pass (&.regex "\d") "0")
+                 (should-fail (&.regex "\d") "m")))
 
       (test "Can parse non digits."
-            (and (should-pass (&.regex "\\D") "m")
-                 (should-fail (&.regex "\\D") "0")))
+            (and (should-pass (&.regex "\D") "m")
+                 (should-fail (&.regex "\D") "0")))
 
       (test "Can parse white-space."
-            (and (should-pass (&.regex "\\s") " ")
-                 (should-fail (&.regex "\\s") "m")))
+            (and (should-pass (&.regex "\s") " ")
+                 (should-fail (&.regex "\s") "m")))
 
       (test "Can parse non white-space."
-            (and (should-pass (&.regex "\\S") "m")
-                 (should-fail (&.regex "\\S") " ")))
+            (and (should-pass (&.regex "\S") "m")
+                 (should-fail (&.regex "\S") " ")))
 
       (test "Can parse word characters."
-            (and (should-pass (&.regex "\\w") "_")
-                 (should-fail (&.regex "\\w") "^")))
+            (and (should-pass (&.regex "\w") "_")
+                 (should-fail (&.regex "\w") "^")))
 
       (test "Can parse non word characters."
-            (and (should-pass (&.regex "\\W") ".")
-                 (should-fail (&.regex "\\W") "a")))
+            (and (should-pass (&.regex "\W") ".")
+                 (should-fail (&.regex "\W") "a")))
       ))
 
 (context: "Regular Expressions [Special system character classes : Part 1]"
   ($_ seq
       (test "Can parse using special character classes."
-            (and (and (should-pass (&.regex "\\p{Lower}") "m")
-                      (should-fail (&.regex "\\p{Lower}") "M"))
+            (and (and (should-pass (&.regex "\p{Lower}") "m")
+                      (should-fail (&.regex "\p{Lower}") "M"))
 
-                 (and (should-pass (&.regex "\\p{Upper}") "M")
-                      (should-fail (&.regex "\\p{Upper}") "m"))
+                 (and (should-pass (&.regex "\p{Upper}") "M")
+                      (should-fail (&.regex "\p{Upper}") "m"))
 
-                 (and (should-pass (&.regex "\\p{Alpha}") "M")
-                      (should-fail (&.regex "\\p{Alpha}") "0"))
+                 (and (should-pass (&.regex "\p{Alpha}") "M")
+                      (should-fail (&.regex "\p{Alpha}") "0"))
 
-                 (and (should-pass (&.regex "\\p{Digit}") "1")
-                      (should-fail (&.regex "\\p{Digit}") "n"))
+                 (and (should-pass (&.regex "\p{Digit}") "1")
+                      (should-fail (&.regex "\p{Digit}") "n"))
 
-                 (and (should-pass (&.regex "\\p{Alnum}") "1")
-                      (should-fail (&.regex "\\p{Alnum}") "."))
+                 (and (should-pass (&.regex "\p{Alnum}") "1")
+                      (should-fail (&.regex "\p{Alnum}") "."))
 
-                 (and (should-pass (&.regex "\\p{Space}") " ")
-                      (should-fail (&.regex "\\p{Space}") "."))
+                 (and (should-pass (&.regex "\p{Space}") " ")
+                      (should-fail (&.regex "\p{Space}") "."))
                  ))
       ))
 
 (context: "Regular Expressions [Special system character classes : Part 2]"
   ($_ seq
       (test "Can parse using special character classes."
-            (and (and (should-pass (&.regex "\\p{HexDigit}") "a")
-                      (should-fail (&.regex "\\p{HexDigit}") "."))
+            (and (and (should-pass (&.regex "\p{HexDigit}") "a")
+                      (should-fail (&.regex "\p{HexDigit}") "."))
 
-                 (and (should-pass (&.regex "\\p{OctDigit}") "6")
-                      (should-fail (&.regex "\\p{OctDigit}") "."))
+                 (and (should-pass (&.regex "\p{OctDigit}") "6")
+                      (should-fail (&.regex "\p{OctDigit}") "."))
 
-                 (and (should-pass (&.regex "\\p{Blank}") text.tab)
-                      (should-fail (&.regex "\\p{Blank}") "."))
+                 (and (should-pass (&.regex "\p{Blank}") text.tab)
+                      (should-fail (&.regex "\p{Blank}") "."))
 
-                 (and (should-pass (&.regex "\\p{ASCII}") text.tab)
-                      (should-fail (&.regex "\\p{ASCII}") (text.from-code (hex "1234"))))
+                 (and (should-pass (&.regex "\p{ASCII}") text.tab)
+                      (should-fail (&.regex "\p{ASCII}") (text.from-code (hex "1234"))))
 
-                 (and (should-pass (&.regex "\\p{Contrl}") (text.from-code (hex "12")))
-                      (should-fail (&.regex "\\p{Contrl}") "a"))
+                 (and (should-pass (&.regex "\p{Contrl}") (text.from-code (hex "12")))
+                      (should-fail (&.regex "\p{Contrl}") "a"))
 
-                 (and (should-pass (&.regex "\\p{Punct}") "@")
-                      (should-fail (&.regex "\\p{Punct}") "a"))
+                 (and (should-pass (&.regex "\p{Punct}") "@")
+                      (should-fail (&.regex "\p{Punct}") "a"))
 
-                 (and (should-pass (&.regex "\\p{Graph}") "@")
-                      (should-fail (&.regex "\\p{Graph}") " "))
+                 (and (should-pass (&.regex "\p{Graph}") "@")
+                      (should-fail (&.regex "\p{Graph}") " "))
 
-                 (and (should-pass (&.regex "\\p{Print}") (text.from-code (hex "20")))
-                      (should-fail (&.regex "\\p{Print}") (text.from-code (hex "1234"))))
+                 (and (should-pass (&.regex "\p{Print}") (text.from-code (hex "20")))
+                      (should-fail (&.regex "\p{Print}") (text.from-code (hex "1234"))))
                  ))
       ))
 
@@ -191,9 +191,9 @@
       ))
 
 (context: "Regular Expressions [Reference]"
-  (let [number (&.regex "\\d+")]
+  (let [number (&.regex "\d+")]
     (test "Can build complex regexs by combining simpler ones."
-          (should-check ["809-345-6789" "809" "345" "6789"] (&.regex "(\\@)-(\\@)-(\\@)") "809-345-6789"))))
+          (should-check ["809-345-6789" "809" "345" "6789"] (&.regex "(\@)-(\@)-(\@)") "809-345-6789"))))
 
 (context: "Regular Expressions [Fuzzy Quantifiers]"
   ($_ seq
@@ -240,14 +240,14 @@
       (test "Can extract groups of sub-matches specified in a pattern."
             (and (should-check ["abc" "b"] (&.regex "a(.)c") "abc")
                  (should-check ["abbbbbc" "bbbbb"] (&.regex "a(b+)c") "abbbbbc")
-                 (should-check ["809-345-6789" "809" "345" "6789"] (&.regex "(\\d{3})-(\\d{3})-(\\d{4})") "809-345-6789")
-                 (should-check ["809-345-6789" "809" "6789"] (&.regex "(\\d{3})-(?:\\d{3})-(\\d{4})") "809-345-6789")
-                 (should-check ["809-809-6789" "809" "6789"] (&.regex "(\\d{3})-\\0-(\\d{4})") "809-809-6789")
-                 (should-check ["809-809-6789" "809" "6789"] (&.regex "(?\\d{3})-\\k-(\\d{4})") "809-809-6789")
-                 (should-check ["809-809-6789-6789" "809" "6789"] (&.regex "(?\\d{3})-\\k-(\\d{4})-\\0") "809-809-6789-6789")))
+                 (should-check ["809-345-6789" "809" "345" "6789"] (&.regex "(\d{3})-(\d{3})-(\d{4})") "809-345-6789")
+                 (should-check ["809-345-6789" "809" "6789"] (&.regex "(\d{3})-(?:\d{3})-(\d{4})") "809-345-6789")
+                 (should-check ["809-809-6789" "809" "6789"] (&.regex "(\d{3})-\0-(\d{4})") "809-809-6789")
+                 (should-check ["809-809-6789" "809" "6789"] (&.regex "(?\d{3})-\k-(\d{4})") "809-809-6789")
+                 (should-check ["809-809-6789-6789" "809" "6789"] (&.regex "(?\d{3})-\k-(\d{4})-\0") "809-809-6789-6789")))
 
       (test "Can specify groups within groups."
-            (should-check ["809-345-6789" "809" ["345-6789" "345" "6789"]] (&.regex "(\\d{3})-((\\d{3})-(\\d{4}))") "809-345-6789"))
+            (should-check ["809-345-6789" "809" ["345-6789" "345" "6789"]] (&.regex "(\d{3})-((\d{3})-(\d{4}))") "809-345-6789"))
       ))
 
 (context: "Regular Expressions [Alternation]"
@@ -263,7 +263,7 @@
                  (should-fail (&.regex "a(.)(.)|b(.)(.)") "cde")
 
                  (should-check ["809-345-6789" (0 ["809" "345-6789" "345" "6789"])]
-                               (&.regex "(\\d{3})-((\\d{3})-(\\d{4}))|b(.)d")
+                               (&.regex "(\d{3})-((\d{3})-(\d{4}))|b(.)d")
                                "809-345-6789")))
       ))
 
-- 
cgit v1.2.3


From 60d8431a5f3f0a549009a4cc91d958dc20eb67c0 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 06:44:41 -0400
Subject: No more escape-tracking.

---
 stdlib/source/lux/compiler/default/syntax.lux | 181 ++++++--------------------
 1 file changed, 42 insertions(+), 139 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 778588959..759faed1a 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -73,8 +73,6 @@
 (def: #export open-record "{")
 (def: #export close-record "}")
 
-(def: escape "\")
-
 (def: #export sigil "#")
 
 (def: #export digit-separator "_")
@@ -126,21 +124,6 @@
 ##         (left-padding^ where))
 ##       (:: p.Monad wrap where)))
 
-## Escaped character sequences follow the usual syntax of
-## back-slash followed by a letter.
-## Escaped characters may show up in Char and Text literals.
-(def: escaped-char^
-  (Lexer [Nat Text])
-  (p.after (l.this ..escape)
-           (do p.Monad
-             [code l.any]
-             (case code
-               ## Handle special cases.
-               (^ (static ..escape)) (wrap [2 ..escape])
-
-               _
-               (p.fail (format "Invalid escaping syntax: " (%t code)))))))
-
 ## These are very simple parsers that just cut chunks of text in
 ## specific shapes and then use decoders already present in the
 ## standard library to actually produce the values from the literals.
@@ -493,15 +476,8 @@
               (p.fail (ex.construct unrecognized-input where))))
           ))))
 
-(type: Tracker
-  {#next-escape Offset})
-
-(def: fresh-tracker
-  Tracker
-  {#next-escape 0})
-
 (type: (Simple a)
-  (-> Tracker Source (Error [Tracker Source a])))
+  (-> Source (Error [Source a])))
 
 (type: (Reader a)
   (-> Text Aliases (Simple a)))
@@ -516,14 +492,13 @@
   )
 
 (do-template [  ]
-  [(def: ( read-code tracker source)
+  [(def: ( read-code source)
      (-> (Simple Code) (Simple Code))
-     (loop [tracker tracker
-            source source
+     (loop [source source
             stack (: (List Code) #.Nil)]
-       (case (read-code tracker source)
-         (#error.Success [tracker' source' top])
-         (recur tracker' source' (#.Cons top stack))
+       (case (read-code source)
+         (#error.Success [source' top])
+         (recur source' (#.Cons top stack))
          
          (#error.Error error)
          (let [[where offset source-code] source]
@@ -531,8 +506,7 @@
              (#.Some char)
              (`` (case char
                    (^ (char (~~ (static ))))
-                   (#error.Success [tracker
-                                    [(update@ #.column inc where)
+                   (#error.Success [[(update@ #.column inc where)
                                      (!inc offset)
                                      source-code]
                                     [where ( (list.reverse stack))]])
@@ -565,23 +539,6 @@
   [!n/- "lux i64 -"]
   )
 
-(with-expansions [ ($_ "lux text concat" total output (!clip g!post-escape end source-code))]
-  (template: (!find-next-escape diff current-escape end source-code total output)
-    (let [g!post-escape (!n/+ diff current-escape)]
-      (case ("lux text index" source-code (static ..escape) g!post-escape)
-        ## More escaping work needs to be done
-        (#.Some g!next-escape)
-        (if (!i/< (:coerce Int end)
-                  (:coerce Int g!next-escape))
-          ## For the current text.
-          (recur end g!next-escape ($_ "lux text concat" total output (!clip g!post-escape g!next-escape source-code)))
-          ## For another text.
-          (#error.Success [g!next-escape (!inc end) ]))
-
-        ## No more escaping... ever!
-        _
-        (#error.Success [("lux text size" source-code) (!inc end) ])))))
-
 (template: (!guarantee-no-new-lines content body)
   (case ("lux text index" content (static text.new-line) 0)
     (#.Some g!_)
@@ -590,65 +547,20 @@
     g!_
     body))
 
-(def: (read-escaped-text next-escape end offset source-code)
-  (-> Offset Offset Offset Text (Error [Offset Offset Text]))
-  (with-expansions [ (!n/+ 1 next-escape)
-                     (!n/+ 5 next-escape)]
-    (loop [end end
-           next-escape next-escape
-           total (!clip offset next-escape source-code)]
-      ## TODO: Optimize-away "maybe.assume"
-      (`` (case (maybe.assume ("lux text char" source-code ))
-            (^template [ ]
-              (^ (char ))
-              (!find-next-escape 2 next-escape end source-code total ))
-            ([(~~ (static ..escape)) (static ..escape)])
-
-            _
-            (ex.throw invalid-escape-syntax []))))))
-
-(def: (read-text next-escape (^@ source [where offset source-code]))
+(def: (read-text (^@ source [where offset source-code]))
   (Simple Code)
-  (if (!i/< (:coerce Int offset)
-            (:coerce Int next-escape))
-    ## Must update next-escape.
-    (case ("lux text index" source-code (static ..escape) offset)
-      ## There is a escape further down the road.
-      (#.Some next-escape')
-      (read-text next-escape' source)
-
-      ## There are no escapes left.
-      _
-      (read-text ("lux text size" source-code) source))
-    (case ("lux text index" source-code (static ..text-delimiter) offset)
-      (#.Some end)
-      (if (!i/< (:coerce Int end)
-                (:coerce Int next-escape))
-        ## Must handle escape
-        (case (read-escaped-text next-escape end offset source-code)
-          (#error.Error error)
-          (#error.Error error)
-
-          (#error.Success [next-escape' offset' content])
-          (<| (!guarantee-no-new-lines content)
-              (#error.Success [next-escape'
-                               [(update@ #.column (n/+ (!n/- offset offset')) where)
-                                offset'
-                                source-code]
-                               [where
-                                (#.Text content)]])))
-        ## No escape to handle at the moment.
-        (let [content (!clip offset end source-code)]
-          (<| (!guarantee-no-new-lines content)
-              (#error.Success [next-escape
-                               [(update@ #.column (n/+ (!n/- offset end)) where)
-                                (!inc end)
-                                source-code]
-                               [where
-                                (#.Text content)]]))))
-      
-      _
-      (ex.throw unrecognized-input where))))
+  (case ("lux text index" source-code (static ..text-delimiter) offset)
+    (#.Some end)
+    (let [content (!clip offset end source-code)]
+      (<| (!guarantee-no-new-lines content)
+          (#error.Success [[(update@ #.column (n/+ (!n/- offset end)) where)
+                            (!inc end)
+                            source-code]
+                           [where
+                            (#.Text content)]])))
+    
+    _
+    (ex.throw unrecognized-input where)))
 
 (def: digit-bottom Nat (!dec (char "0")))
 (def: digit-top Nat (!inc (char "9")))
@@ -689,15 +601,14 @@
 
 (with-expansions [ (case (:: number.Codec decode (!clip start end source-code))
                              (#error.Success output)
-                             (#error.Success [tracker
-                                              [(update@ #.column (n/+ (!n/- start end)) where)
+                             (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
                                                end
                                                source-code]
                                               [where (#.Nat output)]])
 
                              (#error.Error error)
                              (#error.Error error))]
-  (def: (read-nat start tracker [where offset source-code])
+  (def: (read-nat start [where offset source-code])
     (-> Offset (Simple Code))
     (loop [end offset]
       (case ("lux text char" source-code end)
@@ -773,10 +684,10 @@
               _
               (!read-half-name offset/0 offset/1 char/0 ..prelude)))))
 
-  (template: (!read-short-name @current-module @tracker @source @where @tag)
+  (template: (!read-short-name @current-module @source @where @tag)
     (case (..read-short-name @current-module @source)
       (#error.Success [source' name])
-      (#error.Success [@tracker source' [@where (@tag name)]])
+      (#error.Success [source' [@where (@tag name)]])
       
       (#error.Error error)
       (#error.Error error)))
@@ -808,45 +719,43 @@
             (#error.Error error)
             (#error.Error error)))))
 
-  (template: (!read-full-name @offset @tracker @source @where @tag)
+  (template: (!read-full-name @offset @source @where @tag)
     (case (..read-full-name @offset @source)
       (#error.Success [source' full-name])
-      (#error.Success [@tracker source' [@where (@tag full-name)]])
+      (#error.Success [source' [@where (@tag full-name)]])
       
       (#error.Error error)
       (#error.Error error)))
   
-  (def: (read-code current-module aliases tracker source)
+  (def: (read-code current-module aliases source)
     (Reader Code)
     (let [read-code' (read-code current-module aliases)]
-      (loop [tracker tracker
-             [where offset source-code] source]
+      (loop [[where offset source-code] source]
         (<| (!with-char source-code offset char/0)
             (`` (case char/0
                   ## White-space
                   (^template [ ]
                     (^ (char ))
-                    (recur tracker
-                           [(update@  inc where)
+                    (recur [(update@  inc where)
                             (!inc offset)
                             source-code]))
                   ([(~~ (static ..white-space))     #.column]
                    [(~~ (static text.carriage-return)) #.column])
 
                   (^ (char (~~ (static text.new-line))))
-                  (recur tracker [(!new-line where) (!inc offset) source-code])
+                  (recur [(!new-line where) (!inc offset) source-code])
 
                   ## Form
                   (^ (char (~~ (static ..open-form))))
-                  (read-form read-code' tracker )
+                  (read-form read-code' )
 
                   ## Tuple
                   (^ (char (~~ (static ..open-tuple))))
-                  (read-tuple read-code' tracker )
+                  (read-tuple read-code' )
 
                   ## Text
                   (^ (char (~~ (static ..text-delimiter))))
-                  (read-text tracker )
+                  (read-text )
 
                   ## Special code
                   (^ (char (~~ (static ..sigil))))
@@ -855,8 +764,7 @@
                         (case char/1
                           (^template [ ]
                             (^ (char ))
-                            (#error.Success [tracker
-                                             [(update@ #.column (|>> !leap-bit) where)
+                            (#error.Success [[(update@ #.column (|>> !leap-bit) where)
                                               (!leap-bit offset)
                                               source-code]
                                              [where (#.Bit )]]))
@@ -867,44 +775,39 @@
                           (^ (char (~~ (static ..sigil))))
                           (case ("lux text index" source-code (static text.new-line) offset')
                             (#.Some end)
-                            (recur tracker [(!new-line where) (!inc end) source-code])
+                            (recur [(!new-line where) (!inc end) source-code])
                             
                             _
                             )
 
                           (^ (char (~~ (static ..name-separator))))
-                          (!read-short-name current-module tracker  where #.Identifier)
+                          (!read-short-name current-module  where #.Identifier)
 
                           _
                           (cond (!name-char?|head char/1) ## Tag
-                                (!read-full-name offset tracker  where #.Tag)
+                                (!read-full-name offset  where #.Tag)
 
                                 ## else
                                 ))))
 
                   (^ (char (~~ (static ..name-separator))))
-                  (!read-short-name current-module tracker  where #.Identifier)
+                  (!read-short-name current-module  where #.Identifier)
 
                   _
                   (cond (!digit? char/0) ## Natural number
-                        (read-nat offset tracker )
+                        (read-nat offset )
 
                         ## Identifier
                         (!name-char?|head char/0)
-                        (!read-full-name offset tracker  where #.Identifier)
+                        (!read-full-name offset  where #.Identifier)
                         
                         ## else
                         ))))))))
 
 ## [where offset source-code]
-(def: #export (read current-module aliases source)
+(def: #export read
   (-> Text Aliases Source (Error [Source Code]))
-  (case (read-code current-module aliases fresh-tracker source)
-    (#error.Error error)
-    (#error.Error error)
-
-    (#error.Success [tracker' source' output])
-    (#error.Success [source' output])))
+  ..read-code)
 
 ## (def: #export (read current-module aliases source)
 ##   (-> Text Aliases Source (Error [Source Code]))
-- 
cgit v1.2.3


From c85ed3cd81ccf294441ee56d86f85e9f9e85ccea Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 07:10:17 -0400
Subject: Added Int parsing.

---
 stdlib/source/lux/compiler/default/syntax.lux | 334 ++++++--------------------
 1 file changed, 74 insertions(+), 260 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 759faed1a..bb5f9922e 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -77,6 +77,9 @@
 
 (def: #export digit-separator "_")
 
+(def: #export positive-sign "+")
+(def: #export negative-sign "-")
+
 ## (def: comment-marker (format ..sigil ..sigil))
 
 ## ## This is the parser for white-space.
@@ -162,18 +165,6 @@
    number.Codec]
   )
 
-## (def: #export (nat where)
-##   Syntax
-##   (do p.Monad
-##     [chunk rich-digits^]
-##     (case (:: number.Codec decode chunk)
-##       (#.Left error)
-##       (p.fail error)
-
-##       (#.Right value)
-##       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
-##              [where (#.Nat value)]]))))
-
 (def: #export (frac where)
   Syntax
   (do p.Monad
@@ -195,79 +186,6 @@
       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
              [where (#.Frac value)]]))))
 
-## ## This parser looks so complex because text in Lux can be multi-line
-## ## and there are rules regarding how this is handled.
-## (def: #export (text where)
-##   Syntax
-##   (do p.Monad
-##     [## Lux text "is delimited by double-quotes", as usual in most
-##      ## programming languages.
-##      _ ..text-delimiter^
-##      ## I must know what column the text body starts at (which is
-##      ## always 1 column after the left-delimiting quote).
-##      ## This is important because, when procesing subsequent lines,
-##      ## they must all start at the same column, being left-padded with
-##      ## as many spaces as necessary to be column-aligned.
-##      ## This helps ensure that the formatting on the text in the
-##      ## source-code matches the formatting of the Text value.
-##      #let [offset ("lux i64 +" 1 (get@ #.column where))]
-##      [where' text-read] (: (Lexer [Cursor Text])
-##                            ## I must keep track of how much of the
-##                            ## text body has been read, how far the
-##                            ## cursor has progressed, and whether I'm
-##                            ## processing a subsequent line, or just
-##                            ## processing normal text body.
-##                            (loop [text-read ""
-##                                   where (|> where
-##                                             (update@ #.column inc))
-##                                   must-have-offset? #0]
-##                              (p.either (if must-have-offset?
-##                                          ## If I'm at the start of a
-##                                          ## new line, I must ensure the
-##                                          ## space-offset is at least
-##                                          ## as great as the column of
-##                                          ## the text's body's column,
-##                                          ## to ensure they are aligned.
-##                                          (do @
-##                                            [_ (p.exactly offset (l.this ..white-space))]
-##                                            (recur text-read
-##                                                   (update@ #.column (n/+ offset) where)
-##                                                   #0))
-##                                          ($_ p.either
-##                                              ## Normal text characters.
-##                                              (do @
-##                                                [normal (l.slice (l.many! (l.none-of! (format ..escape ..text-delimiter text.new-line))))]
-##                                                (recur (format text-read normal)
-##                                                       (update@ #.column (n/+ (text.size normal)) where)
-##                                                       #0))
-##                                              ## Must handle escaped
-##                                              ## chars separately.
-##                                              (do @
-##                                                [[chars-consumed char] escaped-char^]
-##                                                (recur (format text-read char)
-##                                                       (update@ #.column (n/+ chars-consumed) where)
-##                                                       #0))
-##                                              ## The text ends when it
-##                                              ## reaches the right-delimiter.
-##                                              (do @
-##                                                [_ ..text-delimiter^]
-##                                                (wrap [(update@ #.column inc where)
-##                                                       text-read]))))
-##                                        ## If a new-line is
-##                                        ## encountered, it gets
-##                                        ## appended to the value and
-##                                        ## the loop is alerted that the
-##                                        ## next line must have an offset.
-##                                        (do @
-##                                          [_ ..new-line^]
-##                                          (recur (format text-read new-line)
-##                                                 (|> where
-##                                                     (update@ #.line inc)
-##                                                     (set@ #.column 0))
-##                                                 #1)))))]
-##     (wrap [where'
-##            [where (#.Text text-read)]])))
-
 (def: (composite open close element)
   (All [a]
     (-> Text Text
@@ -294,16 +212,6 @@
                       (wrap [(update@ #.column inc where)
                              #.Nil]))))))))
 
-## (do-template [   ]
-##   [(def: ( ast where)
-##      (-> Syntax Syntax)
-##      (<| (parser/map (product.both id (|>>  [where])))
-##          (composite   ast where)))]
-
-##   [form  #.Form  ..open-form  ..close-form]
-##   [tuple #.Tuple ..open-tuple ..close-tuple]
-##   )
-
 ## Records are almost (syntactically) the same as forms and tuples,
 ## with the exception that their elements must come in pairs (as in
 ## key-value pairs).
@@ -333,110 +241,6 @@
 ## encoded on the parser.
 (def: name-separator ".")
 
-## ## A Lux name is a pair of chunks of text, where the first-part
-## ## refers to the module that gives context to the name, and the
-## ## second part corresponds to the short of the name itself.
-## ## The module part may be absent (by being the empty text ""), but the
-## ## name part must always be present.
-## ## The rules for which characters you may use are specified in terms
-## ## of which characters you must avoid (to keep things as open-ended as
-## ## possible).
-## ## In particular, no white-space can be used, and neither can other
-## ## characters which are already used by Lux as delimiters for other
-## ## Code nodes (thereby reducing ambiguity while parsing).
-## ## Additionally, the first character in an name's part cannot be
-## ## a digit, to avoid confusion with regards to numbers.
-## (def: name-part^
-##   (Lexer Text)
-##   (let [delimiters (format ..open-form ..close-form
-##                            ..open-tuple ..close-tuple
-##                            ..open-record ..close-record
-##                            ..sigil
-##                            ..text-delimiter
-##                            ..name-separator)
-##         space (format ..white-space text.new-line)
-##         head (l.none-of! (format ..digits delimiters space))
-##         tail (l.some! (l.none-of! (format delimiters space)))]
-##     (l.slice (l.and! head tail))))
-
-## (def: current-module-mark Text (format ..name-separator ..name-separator))
-
-## (def: (name^ current-module aliases)
-##   (-> Text Aliases (Lexer [Name Nat]))
-##   ($_ p.either
-##       ## When an name starts with 2 marks, its module is
-##       ## taken to be the current-module being compiled at the moment.
-##       ## This can be useful when mentioning names and tags
-##       ## inside quoted/templated code in macros.
-##       (do p.Monad
-##         [_ (l.this current-module-mark)
-##          def-name name-part^]
-##         (wrap [[current-module def-name]
-##                ("lux i64 +" 2 (text.size def-name))]))
-##       ## If the name is prefixed by the mark, but no module
-##       ## part, the module is assumed to be "lux" (otherwise known as
-##       ## the 'prelude').
-##       ## This makes it easy to refer to definitions in that module,
-##       ## since it is the most fundamental module in the entire
-##       ## standard library.
-##       (do p.Monad
-##         [_ (l.this name-separator)
-##          def-name name-part^]
-##         (wrap [["lux" def-name]
-##                ("lux i64 +" 1 (text.size def-name))]))
-##       ## Not all names must be specified with a module part.
-##       ## If that part is not provided, the name will be created
-##       ## with the empty "" text as the module.
-##       ## During program analysis, such names tend to be treated
-##       ## as if their context is the current-module, but this only
-##       ## applies to names for tags and module definitions.
-##       ## Function arguments and local-variables may not be referred-to
-##       ## using names with module parts, so being able to specify
-##       ## names with empty modules helps with those use-cases.
-##       (do p.Monad
-##         [first-part name-part^]
-##         (p.either (do @
-##                     [_ (l.this name-separator)
-##                      second-part name-part^]
-##                     (wrap [[(|> aliases (dictionary.get first-part) (maybe.default first-part))
-##                             second-part]
-##                            ($_ "lux i64 +"
-##                                (text.size first-part)
-##                                1
-##                                (text.size second-part))]))
-##                   (wrap [["" first-part]
-##                          (text.size first-part)])))))
-
-## (do-template [ 
  ]
-##   [(def: #export ( current-module aliases)
-##      (-> Text Aliases Syntax)
-##      (function (_ where)
-##        (do p.Monad
-##          [[value length] (<| 
-##                              (name^ current-module aliases))]
-##          (wrap [(update@ #.column (n/+ ) where)
-##                 [where ( value)]]))))]
-
-##   [tag        (p.after (l.this ..sigil)) #.Tag        ("lux i64 +" 1 length)]
-##   [identifier (|>)                       #.Identifier length]
-##   )
-
-## (do-template [ ]
-##   [(def: 
-##      (Lexer Bit)
-##      (parser/map (function.constant ) (l.this (%b ))))]
-
-##   [false #0]
-##   [true  #1]
-##   )
-
-## (def: #export (bit where)
-##   Syntax
-##   (do p.Monad
-##     [value (p.either ..false ..true)]
-##     (wrap [(update@ #.column (n/+ 2) where)
-##            [where (#.Bit value)]])))
-
 (exception: #export (end-of-file {module Text})
   (ex.report ["Module" (%t module)]))
 
@@ -462,7 +266,7 @@
           ## (..nat where)
           (..frac where)
           (..rev where)
-          (..int where)
+          ## (..int where)
           ## (..text where)
           ## (..identifier current-module aliases where)
           ## (..tag current-module aliases where)
@@ -492,11 +296,11 @@
   )
 
 (do-template [  ]
-  [(def: ( read-code source)
+  [(def: ( read source)
      (-> (Simple Code) (Simple Code))
      (loop [source source
             stack (: (List Code) #.Nil)]
-       (case (read-code source)
+       (case (read source)
          (#error.Success [source' top])
          (recur source' (#.Cons top stack))
          
@@ -547,21 +351,6 @@
     g!_
     body))
 
-(def: (read-text (^@ source [where offset source-code]))
-  (Simple Code)
-  (case ("lux text index" source-code (static ..text-delimiter) offset)
-    (#.Some end)
-    (let [content (!clip offset end source-code)]
-      (<| (!guarantee-no-new-lines content)
-          (#error.Success [[(update@ #.column (n/+ (!n/- offset end)) where)
-                            (!inc end)
-                            source-code]
-                           [where
-                            (#.Text content)]])))
-    
-    _
-    (ex.throw unrecognized-input where)))
-
 (def: digit-bottom Nat (!dec (char "0")))
 (def: digit-top Nat (!inc (char "9")))
 
@@ -599,26 +388,47 @@
   (or (!strict-name-char? char)
       (!digit? char)))
 
-(with-expansions [ (case (:: number.Codec decode (!clip start end source-code))
-                             (#error.Success output)
-                             (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
-                                               end
-                                               source-code]
-                                              [where (#.Nat output)]])
-
-                             (#error.Error error)
-                             (#error.Error error))]
-  (def: (read-nat start [where offset source-code])
-    (-> Offset (Simple Code))
-    (loop [end offset]
-      (case ("lux text char" source-code end)
-        (#.Some char)
-        (if (!digit?+ char)
-          (recur (!inc end))
-          )
-        
-        _
-        ))))
+(template: (!discrete-output  )
+  (case (::  decode (!clip start end source-code))
+    (#error.Success output)
+    (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
+                      end
+                      source-code]
+                     [where ( output)]])
+
+    (#error.Error error)
+    (#error.Error error)))
+
+(def: (read-nat start [where offset source-code])
+  (-> Offset (Simple Code))
+  (loop [end offset]
+    (case ("lux text char" source-code end)
+      (#.Some char)
+      (if (!digit?+ char)
+        (recur (!inc end))
+        (!discrete-output number.Codec #.Nat))
+      
+      _
+      (!discrete-output number.Codec #.Nat))))
+
+(def: (read-int start [where offset source-code])
+  (-> Offset (Simple Code))
+  (loop [end offset]
+    (case ("lux text char" source-code end)
+      (#.Some char)
+      (if (!digit?+ char)
+        (recur (!inc end))
+        (!discrete-output number.Codec #.Int))
+      
+      _
+      (!discrete-output number.Codec #.Int))))
+
+(template: (!read-int offset where source-code)
+  (let [g!offset/1 (!inc offset)]
+    (<| (!with-char source-code g!offset/1 g!char/1)
+        (if (!digit? g!char/1)
+          (read-int offset [where (!inc/2 offset) source-code])
+          (!read-full-name offset [where (!inc offset) source-code] where #.Identifier)))))
 
 (with-expansions [ (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
                                              end
@@ -727,9 +537,9 @@
       (#error.Error error)
       (#error.Error error)))
   
-  (def: (read-code current-module aliases source)
-    (Reader Code)
-    (let [read-code' (read-code current-module aliases)]
+  (def: #export (read current-module aliases source)
+    (-> Text Aliases Source (Error [Source Code]))
+    (let [read' (read current-module aliases)]
       (loop [[where offset source-code] source]
         (<| (!with-char source-code offset char/0)
             (`` (case char/0
@@ -747,20 +557,32 @@
 
                   ## Form
                   (^ (char (~~ (static ..open-form))))
-                  (read-form read-code' )
+                  (read-form read' )
 
                   ## Tuple
                   (^ (char (~~ (static ..open-tuple))))
-                  (read-tuple read-code' )
+                  (read-tuple read' )
 
                   ## Text
                   (^ (char (~~ (static ..text-delimiter))))
-                  (read-text )
+                  (let [offset/1 (!inc offset)]
+                    (case ("lux text index" source-code (static ..text-delimiter) offset/1)
+                      (#.Some end)
+                      (let [content (!clip offset/1 end source-code)]
+                        (<| (!guarantee-no-new-lines content)
+                            (#error.Success [[(update@ #.column (n/+ (!n/- offset/1 end)) where)
+                                              (!inc end)
+                                              source-code]
+                                             [where
+                                              (#.Text content)]])))
+                      
+                      _
+                      (ex.throw unrecognized-input where)))
 
                   ## Special code
                   (^ (char (~~ (static ..sigil))))
-                  (let [offset' (!inc offset)]
-                    (<| (!with-char source-code offset' char/1)
+                  (let [offset/1 (!inc offset)]
+                    (<| (!with-char source-code offset/1 char/1)
                         (case char/1
                           (^template [ ]
                             (^ (char ))
@@ -773,7 +595,7 @@
 
                           ## Single-line comment
                           (^ (char (~~ (static ..sigil))))
-                          (case ("lux text index" source-code (static text.new-line) offset')
+                          (case ("lux text index" source-code (static text.new-line) offset/1)
                             (#.Some end)
                             (recur [(!new-line where) (!inc end) source-code])
                             
@@ -793,6 +615,12 @@
                   (^ (char (~~ (static ..name-separator))))
                   (!read-short-name current-module  where #.Identifier)
 
+                  (^template []
+                    (^ (char ))
+                    (!read-int offset where source-code))
+                  ([(~~ (static ..positive-sign))]
+                   [(~~ (static ..negative-sign))])
+
                   _
                   (cond (!digit? char/0) ## Natural number
                         (read-nat offset )
@@ -803,17 +631,3 @@
                         
                         ## else
                         ))))))))
-
-## [where offset source-code]
-(def: #export read
-  (-> Text Aliases Source (Error [Source Code]))
-  ..read-code)
-
-## (def: #export (read current-module aliases source)
-##   (-> Text Aliases Source (Error [Source Code]))
-##   (case (p.run [offset source-code] (ast current-module aliases where))
-##     (#error.Error error)
-##     (#error.Error error)
-
-##     (#error.Success [[offset' remaining] [where' output]])
-##     (#error.Success [[where' offset' remaining] output])))
-- 
cgit v1.2.3


From cfcd6df48edb96262eab3f0cdffc718b2ec4db9a Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 07:28:53 -0400
Subject: Added record parsing.

---
 stdlib/source/lux/compiler/default.lux        |   2 +-
 stdlib/source/lux/compiler/default/syntax.lux | 248 +++++++++-----------------
 stdlib/source/lux/interpreter.lux             |   2 +-
 3 files changed, 82 insertions(+), 170 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default.lux b/stdlib/source/lux/compiler/default.lux
index e9678c87c..1744b1143 100644
--- a/stdlib/source/lux/compiler/default.lux
+++ b/stdlib/source/lux/compiler/default.lux
@@ -39,7 +39,7 @@
 (def: (read current-module aliases)
   (-> Text Aliases (analysis.Operation Code))
   (function (_ [bundle compiler])
-    (case (syntax.read current-module aliases (get@ #.source compiler))
+    (case (syntax.parse current-module aliases (get@ #.source compiler))
       (#error.Error error)
       (#error.Error error)
 
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index bb5f9922e..c2d2bff29 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -22,10 +22,10 @@
 ## updated cursor pointing to the end position, after the parser was run.
 
 ## Lux Code nodes/tokens are annotated with cursor meta-data
-## (file-name, line, column) to keep track of their provenance and
+## [file-name, line, column] to keep track of their provenance and
 ## location, which is helpful for documentation and debugging.
 (.module:
-  [lux (#- nat int rev true false)
+  [lux (#- int rev)
    [control
     monad
     ["p" parser ("parser/." Monad)]
@@ -33,19 +33,13 @@
    [data
     ["." error (#+ Error)]
     ["." number]
-    ["." product]
     ["." maybe]
     ["." text
      ["l" lexer (#+ Offset Lexer)]
      format]
     [collection
      ["." list]
-     ["." dictionary (#+ Dictionary)]]]
-   ["." function]
-   ["." io]
-   [time
-    ["." instant]
-    ["." duration]]])
+     ["." dictionary (#+ Dictionary)]]]])
 
 (type: #export Syntax
   (-> Cursor (Lexer [Cursor Code])))
@@ -53,16 +47,11 @@
 (type: #export Aliases (Dictionary Text Text))
 (def: #export no-aliases Aliases (dictionary.new text.Hash))
 
-(def: #export prelude Text "lux")
+(def: #export prelude "lux")
 
-(def: digits "0123456789")
-(def: digits+ (format "_" ..digits))
-
-(def: white-space " ")
-## (def: new-line^ (l.this new-line))
+(def: #export space " ")
 
 (def: #export text-delimiter text.double-quote)
-## (def: text-delimiter^ (l.this text-delimiter))
 
 (def: #export open-form "(")
 (def: #export close-form ")")
@@ -80,53 +69,6 @@
 (def: #export positive-sign "+")
 (def: #export negative-sign "-")
 
-## (def: comment-marker (format ..sigil ..sigil))
-
-## ## This is the parser for white-space.
-## ## Whenever a new-line is encountered, the column gets reset to 0, and
-## ## the line gets incremented.
-## ## It operates recursively in order to produce the longest continuous
-## ## chunk of white-space.
-## (def: (space^ where)
-##   (-> Cursor (Lexer Cursor))
-##   (p.either (do p.Monad
-##               [content (l.many! (l.one-of! white-space))]
-##               (wrap (update@ #.column (n/+ (get@ #l.distance content)) where)))
-##             ## New-lines must be handled as a separate case to ensure line
-##             ## information is handled properly.
-##             (do p.Monad
-##               [content (l.many! (l.one-of! new-line))]
-##               (wrap (|> where
-##                         (update@ #.line (n/+ (get@ #l.distance content)))
-##                         (set@ #.column 0))))))
-
-## ## Single-line comments can start anywhere, but only go up to the
-## ## next new-line.
-## (def: (comment^ where)
-##   (-> Cursor (Lexer Cursor))
-##   (do p.Monad
-##     [_ (l.this ..comment-marker)
-##      _ (l.some! (l.none-of! new-line))
-##      _ ..new-line^]
-##     (wrap (|> where
-##               (update@ #.line inc)
-##               (set@ #.column 0)))))
-
-## ## To simplify parsing, I remove any left-padding that a Code token
-## ## may have prior to parsing the token itself.
-## ## Left-padding is assumed to be either white-space or a comment.
-## ## The cursor gets updated, but the padding gets ignored.
-## (def: (left-padding^ where)
-##   (-> Cursor (Lexer Cursor))
-##   ($_ p.either
-##       (do p.Monad
-##         [where (comment^ where)]
-##         (left-padding^ where))
-##       (do p.Monad
-##         [where (space^ where)]
-##         (left-padding^ where))
-##       (:: p.Monad wrap where)))
-
 ## These are very simple parsers that just cut chunks of text in
 ## specific shapes and then use decoders already present in the
 ## standard library to actually produce the values from the literals.
@@ -186,52 +128,6 @@
       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
              [where (#.Frac value)]]))))
 
-(def: (composite open close element)
-  (All [a]
-    (-> Text Text
-        (-> Cursor (Lexer [Cursor a]))
-        (-> Cursor (Lexer [Cursor (List a)]))))
-  (let [open^ (l.this open)
-        close^ (l.this close)]
-    (function (_ where)
-      (do p.Monad
-        [_ open^]
-        (loop [where (update@ #.column inc where)]
-          (p.either (do @
-                      [## Must update the cursor as I
-                       ## go along, to keep things accurate.
-                       [where' head] (element where)]
-                      (parser/map (product.both id (|>> (#.Cons head)))
-                                  (recur where')))
-                    (do @
-                      [## Must take into account any
-                       ## padding present before the
-                       ## end-delimiter.
-                       ## where (left-padding^ where)
-                       _ close^]
-                      (wrap [(update@ #.column inc where)
-                             #.Nil]))))))))
-
-## Records are almost (syntactically) the same as forms and tuples,
-## with the exception that their elements must come in pairs (as in
-## key-value pairs).
-## Semantically, though, records and tuples are just 2 different
-## representations for the same thing (a tuple).
-## In normal Lux syntax, the key position in the pair will be a tag
-## Code node, however, record Code nodes allow any Code node to occupy
-## this position, since it may be useful when processing Code syntax in
-## macros.
-(def: (record ast where)
-  (-> Syntax Syntax)
-  (<| (parser/map (product.both id (|>> #.Record [where])))
-      (composite ..open-record ..close-record
-                 (function (_ where')
-                   (do p.Monad
-                     [[where' key] (ast where')
-                      [where' val] (ast where')]
-                     (wrap [where' [key val]])))
-                 where)))
-
 ## The parts of an name are separated by a single mark.
 ## E.g. module.short.
 ## Only one such mark may be used in an name, since there
@@ -258,32 +154,15 @@
 (def: (ast current-module aliases)
   (-> Text Aliases Syntax)
   (function (ast' where)
-    (do p.Monad
-      [## where (left-padding^ where)
-       ]
-      ($_ p.either
-          ## (..bit where)
-          ## (..nat where)
-          (..frac where)
-          (..rev where)
-          ## (..int where)
-          ## (..text where)
-          ## (..identifier current-module aliases where)
-          ## (..tag current-module aliases where)
-          ## (..form ast' where)
-          ## (..tuple ast' where)
-          (..record ast' where)
-          (do @
-            [end? l.end?]
-            (if end?
-              (p.fail (ex.construct end-of-file current-module))
-              (p.fail (ex.construct unrecognized-input where))))
-          ))))
+    ($_ p.either
+        (..frac where)
+        (..rev where)
+        )))
 
 (type: (Simple a)
   (-> Source (Error [Source a])))
 
-(type: (Reader a)
+(type: (Parser a)
   (-> Text Aliases (Simple a)))
 
 (do-template [  ]
@@ -296,11 +175,11 @@
   )
 
 (do-template [  ]
-  [(def: ( read source)
+  [(def: ( parse source)
      (-> (Simple Code) (Simple Code))
      (loop [source source
             stack (: (List Code) #.Nil)]
-       (case (read source)
+       (case (parse source)
          (#error.Success [source' top])
          (recur source' (#.Cons top stack))
          
@@ -324,10 +203,40 @@
   ## Form and tuple syntax is mostly the same, differing only in the
   ## delimiters involved.
   ## They may have an arbitrary number of arbitrary Code nodes as elements.
-  [read-form  ..close-form  #.Form]
-  [read-tuple ..close-tuple #.Tuple]
+  [parse-form  ..close-form  #.Form]
+  [parse-tuple ..close-tuple #.Tuple]
   )
 
+(def: (parse-record parse source)
+  (-> (Simple Code) (Simple Code))
+  (loop [source source
+         stack (: (List [Code Code]) #.Nil)]
+    (case (parse source)
+      (#error.Success [sourceF field])
+      (case (parse sourceF)
+        (#error.Success [sourceFV value])
+        (recur sourceFV (#.Cons [field value] stack))
+
+        (#error.Error error)
+        (let [[where offset source-code] source]
+          (case ("lux text char" source-code offset)
+            (#.Some char)
+            (`` (case char
+                  (^ (char (~~ (static ..close-record))))
+                  (#error.Success [[(update@ #.column inc where)
+                                    (!inc offset)
+                                    source-code]
+                                   [where (#.Record (list.reverse stack))]])
+
+                  _
+                  (ex.throw unrecognized-input where)))
+            
+            _
+            (#error.Error error))))
+
+      (#error.Error error)
+      (#error.Error error))))
+
 (template: (!clip from to text)
   ## TODO: Optimize-away "maybe.assume"
   (maybe.assume ("lux text clip" text from to)))
@@ -363,7 +272,7 @@
           ("lux i64 =" (.char (~~ (static ..digit-separator))) char))))
 
 (`` (template: (!strict-name-char? char)
-      (not (or ("lux i64 =" (.char (~~ (static ..white-space))) char)
+      (not (or ("lux i64 =" (.char (~~ (static ..space))) char)
                ("lux i64 =" (.char (~~ (static text.new-line))) char)
 
                ("lux i64 =" (.char (~~ (static ..name-separator))) char)
@@ -399,7 +308,7 @@
     (#error.Error error)
     (#error.Error error)))
 
-(def: (read-nat start [where offset source-code])
+(def: (parse-nat start [where offset source-code])
   (-> Offset (Simple Code))
   (loop [end offset]
     (case ("lux text char" source-code end)
@@ -411,7 +320,7 @@
       _
       (!discrete-output number.Codec #.Nat))))
 
-(def: (read-int start [where offset source-code])
+(def: (parse-int start [where offset source-code])
   (-> Offset (Simple Code))
   (loop [end offset]
     (case ("lux text char" source-code end)
@@ -423,18 +332,18 @@
       _
       (!discrete-output number.Codec #.Int))))
 
-(template: (!read-int offset where source-code)
+(template: (!parse-int offset where source-code)
   (let [g!offset/1 (!inc offset)]
     (<| (!with-char source-code g!offset/1 g!char/1)
         (if (!digit? g!char/1)
-          (read-int offset [where (!inc/2 offset) source-code])
-          (!read-full-name offset [where (!inc offset) source-code] where #.Identifier)))))
+          (parse-int offset [where (!inc/2 offset) source-code])
+          (!parse-full-name offset [where (!inc offset) source-code] where #.Identifier)))))
 
 (with-expansions [ (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
                                              end
                                              source-code]
                                             (!clip start end source-code)])]
-  (def: (read-name-part start [where offset source-code])
+  (def: (parse-name-part start [where offset source-code])
     (-> Offset Source (Error [Source Text]))
     (loop [end offset]
       (case ("lux text char" source-code end)
@@ -457,9 +366,8 @@
 
 (with-expansions [ (ex.throw end-of-file current-module)
                    (ex.throw unrecognized-input where)
-                   (as-is [where ("lux i64 +" offset 1) source-code])
-                   (as-is [where ("lux i64 +" offset 2) source-code])
-                   (as-is [where ("lux i64 +" offset 3) source-code])]
+                   (as-is [where (!inc offset) source-code])
+                   (as-is [where (!inc/2 offset) source-code])]
 
   (template: (!with-char @source-code @offset @char @body)
     (case ("lux text char" @source-code @offset)
@@ -469,10 +377,10 @@
       _
       ))
 
-  (template: (!read-half-name @offset//pre @offset//post @char @module)
+  (template: (!parse-half-name @offset//pre @offset//post @char @module)
     (let [@offset//post (!inc @offset//pre)]
       (cond (!name-char?|head @char)
-            (case (..read-name-part @offset//post [where @offset//post source-code])
+            (case (..parse-name-part @offset//post [where @offset//post source-code])
               (#error.Success [source' name])
               (#error.Success [source' [@module name]])
               
@@ -482,20 +390,20 @@
             ## else
             )))
 
-  (`` (def: (read-short-name current-module [where offset/0 source-code])
+  (`` (def: (parse-short-name current-module [where offset/0 source-code])
         (-> Text Source (Error [Source Name]))
         (<| (!with-char source-code offset/0 char/0)
             (case char/0
               (^ (char (~~ (static ..name-separator))))
               (let [offset/1 (!inc offset/0)]
                 (<| (!with-char source-code offset/1 char/1)
-                    (!read-half-name offset/1 offset/2 char/1 current-module)))
+                    (!parse-half-name offset/1 offset/2 char/1 current-module)))
 
               _
-              (!read-half-name offset/0 offset/1 char/0 ..prelude)))))
+              (!parse-half-name offset/0 offset/1 char/0 ..prelude)))))
 
-  (template: (!read-short-name @current-module @source @where @tag)
-    (case (..read-short-name @current-module @source)
+  (template: (!parse-short-name @current-module @source @where @tag)
+    (case (..parse-short-name @current-module @source)
       (#error.Success [source' name])
       (#error.Success [source' [@where (@tag name)]])
       
@@ -503,9 +411,9 @@
       (#error.Error error)))
 
   (with-expansions [ (as-is (#error.Success [source' ["" simple]]))]
-    (`` (def: (read-full-name start source)
+    (`` (def: (parse-full-name start source)
           (-> Offset Source (Error [Source Name]))
-          (case (..read-name-part start source)
+          (case (..parse-name-part start source)
             (#error.Success [source' simple])
             (let [[where' offset' source-code'] source']
               (case ("lux text char" source-code' offset')
@@ -513,7 +421,7 @@
                 (case char/separator
                   (^ (char (~~ (static ..name-separator))))
                   (let [offset'' (!inc offset')]
-                    (case (..read-name-part offset'' [where' offset'' source-code'])
+                    (case (..parse-name-part offset'' [where' offset'' source-code'])
                       (#error.Success [source'' complex])
                       (#error.Success [source'' [simple complex]])
                       
@@ -529,17 +437,17 @@
             (#error.Error error)
             (#error.Error error)))))
 
-  (template: (!read-full-name @offset @source @where @tag)
-    (case (..read-full-name @offset @source)
+  (template: (!parse-full-name @offset @source @where @tag)
+    (case (..parse-full-name @offset @source)
       (#error.Success [source' full-name])
       (#error.Success [source' [@where (@tag full-name)]])
       
       (#error.Error error)
       (#error.Error error)))
   
-  (def: #export (read current-module aliases source)
+  (def: #export (parse current-module aliases source)
     (-> Text Aliases Source (Error [Source Code]))
-    (let [read' (read current-module aliases)]
+    (let [parse' (parse current-module aliases)]
       (loop [[where offset source-code] source]
         (<| (!with-char source-code offset char/0)
             (`` (case char/0
@@ -549,7 +457,7 @@
                     (recur [(update@  inc where)
                             (!inc offset)
                             source-code]))
-                  ([(~~ (static ..white-space))     #.column]
+                  ([(~~ (static ..space))              #.column]
                    [(~~ (static text.carriage-return)) #.column])
 
                   (^ (char (~~ (static text.new-line))))
@@ -557,11 +465,15 @@
 
                   ## Form
                   (^ (char (~~ (static ..open-form))))
-                  (read-form read' )
+                  (parse-form parse' )
 
                   ## Tuple
                   (^ (char (~~ (static ..open-tuple))))
-                  (read-tuple read' )
+                  (parse-tuple parse' )
+
+                  ## Record
+                  (^ (char (~~ (static ..open-record))))
+                  (parse-record parse' )
 
                   ## Text
                   (^ (char (~~ (static ..text-delimiter))))
@@ -603,31 +515,31 @@
                             )
 
                           (^ (char (~~ (static ..name-separator))))
-                          (!read-short-name current-module  where #.Identifier)
+                          (!parse-short-name current-module  where #.Identifier)
 
                           _
                           (cond (!name-char?|head char/1) ## Tag
-                                (!read-full-name offset  where #.Tag)
+                                (!parse-full-name offset  where #.Tag)
 
                                 ## else
                                 ))))
 
                   (^ (char (~~ (static ..name-separator))))
-                  (!read-short-name current-module  where #.Identifier)
+                  (!parse-short-name current-module  where #.Identifier)
 
                   (^template []
                     (^ (char ))
-                    (!read-int offset where source-code))
+                    (!parse-int offset where source-code))
                   ([(~~ (static ..positive-sign))]
                    [(~~ (static ..negative-sign))])
 
                   _
                   (cond (!digit? char/0) ## Natural number
-                        (read-nat offset )
+                        (parse-nat offset )
 
                         ## Identifier
                         (!name-char?|head char/0)
-                        (!read-full-name offset  where #.Identifier)
+                        (!parse-full-name offset  where #.Identifier)
                         
                         ## else
                         ))))))))
diff --git a/stdlib/source/lux/interpreter.lux b/stdlib/source/lux/interpreter.lux
index 75389db21..41edcb708 100644
--- a/stdlib/source/lux/interpreter.lux
+++ b/stdlib/source/lux/interpreter.lux
@@ -164,7 +164,7 @@
     (All [anchor expression statement]
       (->  (Error [ Text])))
     (do error.Monad
-      [[source' input] (syntax.read ..module syntax.no-aliases (get@ #source context))
+      [[source' input] (syntax.parse ..module syntax.no-aliases (get@ #source context))
        [state' representation] (let [## TODO: Simplify ASAP
                                      state (:share [anchor expression statement]
                                                    {
-- 
cgit v1.2.3


From 27eed2a94ff9446014564958439fc5381584568b Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 07:45:16 -0400
Subject: Added Rev parsing.

---
 stdlib/source/lux/compiler/default/syntax.lux | 71 +++++++++++++--------------
 1 file changed, 33 insertions(+), 38 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index c2d2bff29..7dc992471 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -84,29 +84,6 @@
 
 (def: sign^ (l.one-of "+-"))
 
-(do-template [   ]
-  [(def: #export ( where)
-     Syntax
-     (do p.Monad
-       [chunk ]
-       (case (::  decode chunk)
-         (#.Left error)
-         (p.fail error)
-
-         (#.Right value)
-         (wrap [(update@ #.column (n/+ (text.size chunk)) where)
-                [where ( value)]]))))]
-
-  [int #.Int
-   (l.and sign^ rich-digits^)
-   number.Codec]
-  
-  [rev #.Rev
-   (l.and (l.one-of ".")
-          rich-digits^)
-   number.Codec]
-  )
-
 (def: #export (frac where)
   Syntax
   (do p.Monad
@@ -156,7 +133,6 @@
   (function (ast' where)
     ($_ p.either
         (..frac where)
-        (..rev where)
         )))
 
 (type: (Simple a)
@@ -260,6 +236,21 @@
     g!_
     body))
 
+(def: (read-text [where offset source-code])
+  (Simple Code)
+  (case ("lux text index" source-code (static ..text-delimiter) offset)
+    (#.Some end)
+    (let [content (!clip offset end source-code)]
+      (<| (!guarantee-no-new-lines content)
+          (#error.Success [[(update@ #.column (n/+ (!n/- offset end)) where)
+                            (!inc end)
+                            source-code]
+                           [where
+                            (#.Text content)]])))
+    
+    _
+    (ex.throw unrecognized-input where)))
+
 (def: digit-bottom Nat (!dec (char "0")))
 (def: digit-top Nat (!inc (char "9")))
 
@@ -332,6 +323,18 @@
       _
       (!discrete-output number.Codec #.Int))))
 
+(def: (parse-rev start [where offset source-code])
+  (-> Offset (Simple Code))
+  (loop [end offset]
+    (case ("lux text char" source-code end)
+      (#.Some char)
+      (if (!digit?+ char)
+        (recur (!inc end))
+        (!discrete-output number.Codec #.Rev))
+      
+      _
+      (!discrete-output number.Codec #.Rev))))
+
 (template: (!parse-int offset where source-code)
   (let [g!offset/1 (!inc offset)]
     (<| (!with-char source-code g!offset/1 g!char/1)
@@ -477,19 +480,7 @@
 
                   ## Text
                   (^ (char (~~ (static ..text-delimiter))))
-                  (let [offset/1 (!inc offset)]
-                    (case ("lux text index" source-code (static ..text-delimiter) offset/1)
-                      (#.Some end)
-                      (let [content (!clip offset/1 end source-code)]
-                        (<| (!guarantee-no-new-lines content)
-                            (#error.Success [[(update@ #.column (n/+ (!n/- offset/1 end)) where)
-                                              (!inc end)
-                                              source-code]
-                                             [where
-                                              (#.Text content)]])))
-                      
-                      _
-                      (ex.throw unrecognized-input where)))
+                  (read-text )
 
                   ## Special code
                   (^ (char (~~ (static ..sigil))))
@@ -525,7 +516,11 @@
                                 ))))
 
                   (^ (char (~~ (static ..name-separator))))
-                  (!parse-short-name current-module  where #.Identifier)
+                  (let [offset/1 (!inc offset)]
+                    (<| (!with-char source-code offset/1 char/1)
+                        (if (!digit? char/1)
+                          (parse-rev offset [where (!inc offset/1) source-code])
+                          (!parse-short-name current-module  where #.Identifier))))
 
                   (^template []
                     (^ (char ))
-- 
cgit v1.2.3


From d9965e587905cd715ecd4c7150236d660321a02c Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 17:18:30 -0400
Subject: Optimized text clipping.

---
 stdlib/source/lux.lux                              | 36 +++++-----
 .../default/phase/extension/analysis/common.lux    |  2 +-
 stdlib/source/lux/compiler/default/syntax.lux      | 56 +++++++--------
 stdlib/source/lux/data/number.lux                  | 84 ++++++++++------------
 stdlib/source/lux/data/text.lux                    | 10 ++-
 .../default/phase/analysis/procedure/common.lux    |  2 +-
 stdlib/test/test/lux/compiler/default/syntax.lux   | 20 +++---
 7 files changed, 101 insertions(+), 109 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index bfbfe0678..5abcab3dc 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -1,23 +1,17 @@
 ("lux def" double-quote
- ("lux check" (0 "#Text" (0))
-  ("lux int char" +34))
+ ("lux int char" +34)
  [["" 0 0] (10 (0))])
 
 ("lux def" new-line
- ("lux check" (0 "#Text" (0))
-  ("lux int char" +10))
+ ("lux int char" +10)
  [["" 0 0] (10 (0))])
 
 ("lux def" __paragraph
- ("lux check" (0 "#Text" (0))
-  ("lux text concat" new-line new-line))
+ ("lux text concat" new-line new-line)
  [["" 0 0] (10 (0))])
 
 ("lux def" dummy-cursor
- ("lux check" (2 (0 "#Text" (0))
-                 (2 (0 "#I64" (1 (0 "#Nat" (0)) (0)))
-                    (0 "#I64" (1 (0 "#Nat" (0)) (0)))))
-  ["" 0 0])
+ ["" 0 0]
  [["" 0 0]
   (10 (1 [[["" 0 0] (7 ["lux" "export?"])]
           [["" 0 0] (0 #1)]]
@@ -3606,13 +3600,19 @@
     #None
     #None))
 
-(def: (clip1 from text)
+(def: (clip/1 from text)
   (-> Nat Text (Maybe Text))
-  ("lux text clip" text from ("lux text size" text)))
+  (let [size ("lux text size" text)]
+    (if (n/<= size from)
+      (#.Some ("lux text clip" text from size))
+      #.None)))
 
-(def: (clip2 from to text)
+(def: (clip/2 from to text)
   (-> Nat Nat Text (Maybe Text))
-  ("lux text clip" text from to))
+  (if (and (n/<= to from)
+           (n/<= ("lux text size" text) to))
+    (#.Some ("lux text clip" text from to))
+    #.None))
 
 (def: #export (error! message)
   {#.doc (text$ ($_ "lux text concat"
@@ -3651,10 +3651,10 @@
 
     (#Some idx)
     (list& (default (error! "UNDEFINED")
-                    (clip2 0 idx input))
+                    (clip/2 0 idx input))
            (text/split splitter
                        (default (error! "UNDEFINED")
-                                (clip1 (n/+ 1 idx) input))))))
+                                (clip/1 (n/+ 1 idx) input))))))
 
 (def: (nth idx xs)
   (All [a]
@@ -4146,7 +4146,7 @@
 
 (def: (split at x)
   (-> Nat Text (Maybe [Text Text]))
-  (case [(..clip2 0 at x) (..clip1 at x)]
+  (case [(..clip/2 0 at x) (..clip/1 at x)]
     [(#.Some pre) (#.Some post)]
     (#.Some [pre post])
 
@@ -4213,7 +4213,7 @@
                          list/reverse
                          (interpose "/")
                          text/join)
-              clean (|> module (clip1 ups) (default (error! "UNDEFINED")))
+              clean ("lux text clip" module ups ("lux text size" module))
               output (case ("lux text size" clean)
                        0 prefix
                        _ ($_ text/compose prefix "/" clean))]
diff --git a/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux b/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux
index 690a4accb..c654d9a00 100644
--- a/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux
+++ b/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux
@@ -202,7 +202,7 @@
           (bundle.install "index" (trinary Text Text Nat (type (Maybe Nat))))
           (bundle.install "size" (unary Text Nat))
           (bundle.install "char" (binary Text Nat (type (Maybe Nat))))
-          (bundle.install "clip" (trinary Text Nat Nat (type (Maybe Text))))
+          (bundle.install "clip" (trinary Text Nat Nat Text))
           )))
 
 (def: #export (bundle eval)
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 7dc992471..69d214371 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -33,7 +33,6 @@
    [data
     ["." error (#+ Error)]
     ["." number]
-    ["." maybe]
     ["." text
      ["l" lexer (#+ Offset Lexer)]
      format]
@@ -135,11 +134,8 @@
         (..frac where)
         )))
 
-(type: (Simple a)
-  (-> Source (Error [Source a])))
-
-(type: (Parser a)
-  (-> Text Aliases (Simple a)))
+(type: Parser
+  (-> Source (Error [Source Code])))
 
 (do-template [  ]
   [(template: ( value)
@@ -152,7 +148,7 @@
 
 (do-template [  ]
   [(def: ( parse source)
-     (-> (Simple Code) (Simple Code))
+     (-> Parser Parser)
      (loop [source source
             stack (: (List Code) #.Nil)]
        (case (parse source)
@@ -184,7 +180,7 @@
   )
 
 (def: (parse-record parse source)
-  (-> (Simple Code) (Simple Code))
+  (-> Parser Parser)
   (loop [source source
          stack (: (List [Code Code]) #.Nil)]
     (case (parse source)
@@ -214,8 +210,7 @@
       (#error.Error error))))
 
 (template: (!clip from to text)
-  ## TODO: Optimize-away "maybe.assume"
-  (maybe.assume ("lux text clip" text from to)))
+  ("lux text clip" text from to))
 
 (template: (!i/< reference subject)
   ("lux int <" subject reference))
@@ -237,7 +232,7 @@
     body))
 
 (def: (read-text [where offset source-code])
-  (Simple Code)
+  Parser
   (case ("lux text index" source-code (static ..text-delimiter) offset)
     (#.Some end)
     (let [content (!clip offset end source-code)]
@@ -300,7 +295,7 @@
     (#error.Error error)))
 
 (def: (parse-nat start [where offset source-code])
-  (-> Offset (Simple Code))
+  (-> Offset Parser)
   (loop [end offset]
     (case ("lux text char" source-code end)
       (#.Some char)
@@ -312,7 +307,7 @@
       (!discrete-output number.Codec #.Nat))))
 
 (def: (parse-int start [where offset source-code])
-  (-> Offset (Simple Code))
+  (-> Offset Parser)
   (loop [end offset]
     (case ("lux text char" source-code end)
       (#.Some char)
@@ -324,7 +319,7 @@
       (!discrete-output number.Codec #.Int))))
 
 (def: (parse-rev start [where offset source-code])
-  (-> Offset (Simple Code))
+  (-> Offset Parser)
   (loop [end offset]
     (case ("lux text char" source-code end)
       (#.Some char)
@@ -360,17 +355,14 @@
         _
         ))))
 
-(template: (!leap-bit value)
-  ("lux i64 +" value 2))
-
 (template: (!new-line where)
   (let [[where::file where::line where::column] where]
     [where::file (!inc where::line) 0]))
 
 (with-expansions [ (ex.throw end-of-file current-module)
                    (ex.throw unrecognized-input where)
-                   (as-is [where (!inc offset) source-code])
-                   (as-is [where (!inc/2 offset) source-code])]
+                   (as-is [where (!inc offset/0) source-code])
+                   (as-is [where (!inc/2 offset/0) source-code])]
 
   (template: (!with-char @source-code @offset @char @body)
     (case ("lux text char" @source-code @offset)
@@ -451,20 +443,20 @@
   (def: #export (parse current-module aliases source)
     (-> Text Aliases Source (Error [Source Code]))
     (let [parse' (parse current-module aliases)]
-      (loop [[where offset source-code] source]
-        (<| (!with-char source-code offset char/0)
+      (loop [[where offset/0 source-code] source]
+        (<| (!with-char source-code offset/0 char/0)
             (`` (case char/0
                   ## White-space
                   (^template [ ]
                     (^ (char ))
                     (recur [(update@  inc where)
-                            (!inc offset)
+                            (!inc offset/0)
                             source-code]))
                   ([(~~ (static ..space))              #.column]
                    [(~~ (static text.carriage-return)) #.column])
 
                   (^ (char (~~ (static text.new-line))))
-                  (recur [(!new-line where) (!inc offset) source-code])
+                  (recur [(!new-line where) (!inc offset/0) source-code])
 
                   ## Form
                   (^ (char (~~ (static ..open-form))))
@@ -484,13 +476,13 @@
 
                   ## Special code
                   (^ (char (~~ (static ..sigil))))
-                  (let [offset/1 (!inc offset)]
+                  (let [offset/1 (!inc offset/0)]
                     (<| (!with-char source-code offset/1 char/1)
                         (case char/1
                           (^template [ ]
                             (^ (char ))
-                            (#error.Success [[(update@ #.column (|>> !leap-bit) where)
-                                              (!leap-bit offset)
+                            (#error.Success [[(update@ #.column (|>> !inc/2) where)
+                                              (!inc offset/1)
                                               source-code]
                                              [where (#.Bit )]]))
                           (["0" #0]
@@ -510,31 +502,31 @@
 
                           _
                           (cond (!name-char?|head char/1) ## Tag
-                                (!parse-full-name offset  where #.Tag)
+                                (!parse-full-name offset/1  where #.Tag)
 
                                 ## else
                                 ))))
 
                   (^ (char (~~ (static ..name-separator))))
-                  (let [offset/1 (!inc offset)]
+                  (let [offset/1 (!inc offset/0)]
                     (<| (!with-char source-code offset/1 char/1)
                         (if (!digit? char/1)
-                          (parse-rev offset [where (!inc offset/1) source-code])
+                          (parse-rev offset/0 [where (!inc offset/1) source-code])
                           (!parse-short-name current-module  where #.Identifier))))
 
                   (^template []
                     (^ (char ))
-                    (!parse-int offset where source-code))
+                    (!parse-int offset/0 where source-code))
                   ([(~~ (static ..positive-sign))]
                    [(~~ (static ..negative-sign))])
 
                   _
                   (cond (!digit? char/0) ## Natural number
-                        (parse-nat offset )
+                        (parse-nat offset/0 )
 
                         ## Identifier
                         (!name-char?|head char/0)
-                        (!parse-full-name offset  where #.Identifier)
+                        (!parse-full-name offset/0  where #.Identifier)
                         
                         ## else
                         ))))))))
diff --git a/stdlib/source/lux/data/number.lux b/stdlib/source/lux/data/number.lux
index e45c4ff1c..f2845f48c 100644
--- a/stdlib/source/lux/data/number.lux
+++ b/stdlib/source/lux/data/number.lux
@@ -178,9 +178,9 @@
   )
 
 ## [Values & Syntax]
-(def: (get-char full idx)
-  (-> Text Nat (Maybe Text))
-  ("lux text clip" full idx (inc idx)))
+(def: (get-char! full idx)
+  (-> Text Nat Text)
+  ("lux text clip" full idx ("lux i64 +" 1 idx)))
 
 (def: (binary-character value)
   (-> Nat (Maybe Text))
@@ -312,14 +312,13 @@
            (loop [idx 0
                   output 0]
              (if (n/< input-size idx)
-               (let [digit (maybe.assume (get-char repr idx))]
-                 (case ( digit)
-                   #.None
-                   (#error.Error ("lux text concat"  repr))
-
-                   (#.Some digit-value)
-                   (recur (inc idx)
-                          (|> output (n/* ) (n/+ digit-value)))))
+               (case ( (get-char! repr idx))
+                 #.None
+                 (#error.Error ("lux text concat"  repr))
+
+                 (#.Some digit-value)
+                 (recur (inc idx)
+                        (|> output (n/* ) (n/+ digit-value))))
                (#error.Success output)))
            (#error.Error ("lux text concat"  repr))))))]
 
@@ -337,11 +336,11 @@
 
 (def: (int/sign?? representation)
   (-> Text (Maybe Int))
-  (case (get-char representation 0)
-    (^ (#.Some "-"))
+  (case (get-char! representation 0)
+    "-"
     (#.Some -1)
 
-    (^ (#.Some "+"))
+    "+"
     (#.Some +1)
 
     _
@@ -352,14 +351,13 @@
   (loop [idx 1
          output +0]
     (if (n/< input-size idx)
-      (let [digit (maybe.assume (get-char repr idx))]
-        (case ( digit)
-          #.None
-          (#error.Error )
+      (case ( (get-char! repr idx))
+        #.None
+        (#error.Error )
 
-          (#.Some digit-value)
-          (recur (inc idx)
-                 (|> output (i/* ) (i/+ (.int digit-value))))))
+        (#.Some digit-value)
+        (recur (inc idx)
+               (|> output (i/* ) (i/+ (.int digit-value)))))
       (#error.Success (i/* sign output)))))
 
 (do-template [    ]
@@ -396,7 +394,7 @@
 
 (def: (de-prefix input)
   (-> Text Text)
-  (maybe.assume ("lux text clip" input 1 ("lux text size" input))))
+  ("lux text clip" input 1 ("lux text size" input)))
 
 (do-template [   ]
   [(structure: #export  (Codec Text Rev)
@@ -444,8 +442,7 @@
                               (if (f/= +0.0 dec-left)
                                 ("lux text concat" "." output)
                                 (let [shifted (f/*  dec-left)
-                                      digit (|> shifted (f/% ) frac-to-int .nat
-                                                (get-char ) maybe.assume)]
+                                      digit (|> shifted (f/% ) frac-to-int .nat (get-char! ))]
                                   (recur (f/% +1.0 shifted)
                                          ("lux text concat" output digit))))))]
          ("lux text concat" whole-part decimal-part)))
@@ -453,8 +450,8 @@
      (def: (decode repr)
        (case ("lux text index" repr "." 0)
          (#.Some split-index)
-         (let [whole-part (maybe.assume ("lux text clip" repr 0 split-index))
-               decimal-part (maybe.assume ("lux text clip" repr (inc split-index) ("lux text size" repr)))]
+         (let [whole-part ("lux text clip" repr 0 split-index)
+               decimal-part ("lux text clip" repr (inc split-index) ("lux text size" repr))]
            (case [(::  decode whole-part)
                   (::  decode decimal-part)]
              (^multi [(#error.Success whole) (#error.Success decimal)]
@@ -498,8 +495,8 @@
       (if (n/<= chunk-size num-digits)
         (list digits)
         (let [boundary (n/- chunk-size num-digits)
-              chunk (maybe.assume ("lux text clip" digits boundary num-digits))
-              remaining (maybe.assume ("lux text clip" digits 0 boundary))]
+              chunk ("lux text clip" digits boundary num-digits)
+              remaining ("lux text clip" digits 0 boundary)]
           (list& chunk (segment-digits chunk-size remaining)))))))
 
 (def: (bin-segment-to-hex input)
@@ -627,10 +624,10 @@
        (let [sign (:: Number signum value)
              raw-bin (:: Binary@Codec encode value)
              dot-idx (maybe.assume ("lux text index" raw-bin "." 0))
-             whole-part (maybe.assume ("lux text clip" raw-bin
-                                       (if (f/= -1.0 sign) 1 0)
-                                       dot-idx))
-             decimal-part (maybe.assume ("lux text clip" raw-bin (inc dot-idx) ("lux text size" raw-bin)))
+             whole-part ("lux text clip" raw-bin
+                         (if (f/= -1.0 sign) 1 0)
+                         dot-idx)
+             decimal-part ("lux text clip" raw-bin (inc dot-idx) ("lux text size" raw-bin))
              hex-output (|> ( #0 decimal-part)
                             ("lux text concat" ".")
                             ("lux text concat" ( #1 whole-part))
@@ -646,8 +643,8 @@
                     +1.0)]
          (case ("lux text index" repr "." 0)
            (#.Some split-index)
-           (let [whole-part (maybe.assume ("lux text clip" repr 1 split-index))
-                 decimal-part (maybe.assume ("lux text clip" repr (inc split-index) ("lux text size" repr)))
+           (let [whole-part ("lux text clip" repr 1 split-index)
+                 decimal-part ("lux text clip" repr (inc split-index) ("lux text size" repr))
                  as-binary (|> ( decimal-part)
                                ("lux text concat" ".")
                                ("lux text concat" ( whole-part))
@@ -829,14 +826,13 @@
       (loop [idx 0
              output (make-digits [])]
         (if (n/< length idx)
-          (let [char (maybe.assume (get-char input idx))]
-            (case ("lux text index" "+0123456789" char 0)
-              #.None
-              #.None
-
-              (#.Some digit)
-              (recur (inc idx)
-                     (digits-put idx digit output))))
+          (case ("lux text index" "+0123456789" (get-char! input idx) 0)
+            #.None
+            #.None
+
+            (#.Some digit)
+            (recur (inc idx)
+                   (digits-put idx digit output)))
           (#.Some output)))
       #.None)))
 
@@ -900,9 +896,7 @@
                     #0)]
       (if (and dotted?
                (n/<= (inc i64.width) length))
-        (case (|> ("lux text clip" input 1 length)
-                  maybe.assume
-                  text-to-digits)
+        (case (text-to-digits ("lux text clip" input 1 length))
           (#.Some digits)
           (loop [digits digits
                  idx 0
diff --git a/stdlib/source/lux/data/text.lux b/stdlib/source/lux/data/text.lux
index 3807275c1..c33ab03a3 100644
--- a/stdlib/source/lux/data/text.lux
+++ b/stdlib/source/lux/data/text.lux
@@ -105,11 +105,17 @@
 
 (def: #export (clip from to input)
   (-> Nat Nat Text (Maybe Text))
-  ("lux text clip" input from to))
+  (if (and (n/<= to from)
+           (n/<= ("lux text size" input) to))
+    (#.Some ("lux text clip" input from to))
+    #.None))
 
 (def: #export (clip' from input)
   (-> Nat Text (Maybe Text))
-  ("lux text clip" input from (size input)))
+  (let [size ("lux text size" input)]
+    (if (n/<= size from)
+      (#.Some ("lux text clip" input from size))
+      #.None)))
 
 (def: #export (split at x)
   (-> Nat Text (Maybe [Text Text]))
diff --git a/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux b/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux
index fc082155a..cfc164df9 100644
--- a/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux
+++ b/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux
@@ -167,7 +167,7 @@
             (test "Can obtain the character code of a text at a given index."
                   (check-success+ "lux text char" (list subjectC fromC) (type (Maybe Nat))))
             (test "Can clip a piece of text between 2 indices."
-                  (check-success+ "lux text clip" (list subjectC fromC toC) (type (Maybe Text))))
+                  (check-success+ "lux text clip" (list subjectC fromC toC) Text))
             ))))
 
 (context: "IO procedures"
diff --git a/stdlib/test/test/lux/compiler/default/syntax.lux b/stdlib/test/test/lux/compiler/default/syntax.lux
index 829199aa8..887765cbd 100644
--- a/stdlib/test/test/lux/compiler/default/syntax.lux
+++ b/stdlib/test/test/lux/compiler/default/syntax.lux
@@ -87,23 +87,23 @@
          other code^]
         ($_ seq
             (test "Can parse Lux code."
-                  (case (&.read "" (dict.new text.Hash)
-                                [default-cursor 0 (code.to-text sample)])
+                  (case (&.parse "" (dict.new text.Hash)
+                                 [default-cursor 0 (code.to-text sample)])
                     (#e.Error error)
                     #0
 
                     (#e.Success [_ parsed])
                     (:: code.Equivalence = parsed sample)))
             (test "Can parse Lux multiple code nodes."
-                  (case (&.read "" (dict.new text.Hash)
-                                [default-cursor 0 (format (code.to-text sample) " "
-                                                          (code.to-text other))])
+                  (case (&.parse "" (dict.new text.Hash)
+                                 [default-cursor 0 (format (code.to-text sample) " "
+                                                           (code.to-text other))])
                     (#e.Error error)
                     #0
 
                     (#e.Success [remaining =sample])
-                    (case (&.read "" (dict.new text.Hash)
-                                  remaining)
+                    (case (&.parse "" (dict.new text.Hash)
+                                   remaining)
                       (#e.Error error)
                       #0
 
@@ -133,9 +133,9 @@
          comment comment^]
         ($_ seq
             (test "Can handle comments."
-                  (case (&.read "" (dict.new text.Hash)
-                                [default-cursor 0
-                                 (format comment (code.to-text sample))])
+                  (case (&.parse "" (dict.new text.Hash)
+                                 [default-cursor 0
+                                  (format comment (code.to-text sample))])
                     (#e.Error error)
                     #0
 
-- 
cgit v1.2.3


From 312cc7dc5f0be0ef0a48ea8470d8ee64b929bc7b Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 19:02:47 -0400
Subject: "lux text char" is now unsafe/optimized.

---
 stdlib/source/lux.lux                              |  25 +--
 stdlib/source/lux/compiler/default/syntax.lux      | 197 +++++++++------------
 stdlib/source/lux/data/number.lux                  | 154 ++++++++--------
 stdlib/source/lux/data/text.lux                    |  15 +-
 .../default/phase/analysis/procedure/common.lux    |   2 +-
 5 files changed, 177 insertions(+), 216 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 5abcab3dc..916b77797 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -3650,11 +3650,9 @@
     (list input)
 
     (#Some idx)
-    (list& (default (error! "UNDEFINED")
-                    (clip/2 0 idx input))
+    (list& ("lux text clip" input 0 idx)
            (text/split splitter
-                       (default (error! "UNDEFINED")
-                                (clip/1 (n/+ 1 idx) input))))))
+                       ("lux text clip" input (n/+ 1 idx) ("lux text size" input))))))
 
 (def: (nth idx xs)
   (All [a]
@@ -4144,23 +4142,17 @@
     _
     (return [#.Nil parts])))
 
-(def: (split at x)
-  (-> Nat Text (Maybe [Text Text]))
-  (case [(..clip/2 0 at x) (..clip/1 at x)]
-    [(#.Some pre) (#.Some post)]
-    (#.Some [pre post])
-
-    _
-    #.None))
+(def: (split! at x)
+  (-> Nat Text [Text Text])
+  [("lux text clip" x 0 at)
+   ("lux text clip" x at ("lux text size" x))])
 
 (def: (split-with token sample)
   (-> Text Text (Maybe [Text Text]))
   (do ..Monad
     [index (..index-of token sample)
-     pre+post' (split index sample)
-     #let [[pre post'] pre+post']
-     _+post (split ("lux text size" token) post')
-     #let [[_ post] _+post]]
+     #let [[pre post'] (split! index sample)
+           [_ post] (split! ("lux text size" token) post')]]
     (wrap [pre post])))
 
 (def: (replace-all pattern value template)
@@ -5961,7 +5953,6 @@
     (^multi (^ (list [_ (#Text input)]))
             (n/= 1 ("lux text size" input)))
     (|> ("lux text char" input 0)
-        (default (undefined))
         nat$ list
         [compiler] #Right)
 
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 69d214371..af7c7ae90 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -146,6 +146,29 @@
   [!dec   "lux i64 -" 1]
   )
 
+(template: (!clip from to text)
+  ("lux text clip" text from to))
+
+(template: (!i/< reference subject)
+  ("lux int <" subject reference))
+
+(do-template [ ]
+  [(template: ( param subject)
+     ( subject param))]
+
+  [!n/+ "lux i64 +"]
+  [!n/- "lux i64 -"]
+  )
+
+(template: (!with-char @source-code @offset @char @else @body)
+  (if (!i/< (:coerce Int ("lux text size" @source-code))
+            ## TODO: Get rid of the above "lux text size" call.
+            ## The size should be calculated only once and re-used constantly.
+            (:coerce Int @offset))
+    (let [@char ("lux text char" @source-code @offset)]
+      @body)
+    @else))
+
 (do-template [  ]
   [(def: ( parse source)
      (-> Parser Parser)
@@ -157,20 +180,16 @@
          
          (#error.Error error)
          (let [[where offset source-code] source]
-           (case ("lux text char" source-code offset)
-             (#.Some char)
-             (`` (case char
-                   (^ (char (~~ (static ))))
-                   (#error.Success [[(update@ #.column inc where)
-                                     (!inc offset)
-                                     source-code]
-                                    [where ( (list.reverse stack))]])
-
-                   _
-                   (ex.throw unrecognized-input where)))
-             
-             _
-             (#error.Error error))))))]
+           (<| (!with-char source-code offset char (#error.Error error))
+               (`` (case char
+                     (^ (char (~~ (static ))))
+                     (#error.Success [[(update@ #.column inc where)
+                                       (!inc offset)
+                                       source-code]
+                                      [where ( (list.reverse stack))]])
+
+                     _
+                     (ex.throw unrecognized-input where))))))))]
 
   ## Form and tuple syntax is mostly the same, differing only in the
   ## delimiters involved.
@@ -191,38 +210,20 @@
 
         (#error.Error error)
         (let [[where offset source-code] source]
-          (case ("lux text char" source-code offset)
-            (#.Some char)
-            (`` (case char
-                  (^ (char (~~ (static ..close-record))))
-                  (#error.Success [[(update@ #.column inc where)
-                                    (!inc offset)
-                                    source-code]
-                                   [where (#.Record (list.reverse stack))]])
+          (<| (!with-char source-code offset char (#error.Error error))
+              (`` (case char
+                    (^ (char (~~ (static ..close-record))))
+                    (#error.Success [[(update@ #.column inc where)
+                                      (!inc offset)
+                                      source-code]
+                                     [where (#.Record (list.reverse stack))]])
 
-                  _
-                  (ex.throw unrecognized-input where)))
-            
-            _
-            (#error.Error error))))
+                    _
+                    (ex.throw unrecognized-input where))))))
 
       (#error.Error error)
       (#error.Error error))))
 
-(template: (!clip from to text)
-  ("lux text clip" text from to))
-
-(template: (!i/< reference subject)
-  ("lux int <" subject reference))
-
-(do-template [ ]
-  [(template: ( param subject)
-     ( subject param))]
-
-  [!n/+ "lux i64 +"]
-  [!n/- "lux i64 -"]
-  )
-
 (template: (!guarantee-no-new-lines content body)
   (case ("lux text index" content (static text.new-line) 0)
     (#.Some g!_)
@@ -294,45 +295,23 @@
     (#error.Error error)
     (#error.Error error)))
 
-(def: (parse-nat start [where offset source-code])
-  (-> Offset Parser)
-  (loop [end offset]
-    (case ("lux text char" source-code end)
-      (#.Some char)
-      (if (!digit?+ char)
-        (recur (!inc end))
-        (!discrete-output number.Codec #.Nat))
-      
-      _
-      (!discrete-output number.Codec #.Nat))))
-
-(def: (parse-int start [where offset source-code])
-  (-> Offset Parser)
-  (loop [end offset]
-    (case ("lux text char" source-code end)
-      (#.Some char)
-      (if (!digit?+ char)
-        (recur (!inc end))
-        (!discrete-output number.Codec #.Int))
-      
-      _
-      (!discrete-output number.Codec #.Int))))
-
-(def: (parse-rev start [where offset source-code])
-  (-> Offset Parser)
-  (loop [end offset]
-    (case ("lux text char" source-code end)
-      (#.Some char)
-      (if (!digit?+ char)
-        (recur (!inc end))
-        (!discrete-output number.Codec #.Rev))
-      
-      _
-      (!discrete-output number.Codec #.Rev))))
+(do-template [  ]
+  [(def: ( start [where offset source-code])
+     (-> Offset Parser)
+     (loop [end offset]
+       (<| (!with-char source-code end char (!discrete-output  ))
+           (if (!digit?+ char)
+             (recur (!inc end))
+             (!discrete-output  )))))]
+
+  [parse-nat number.Codec #.Nat]
+  [parse-int number.Codec #.Int]
+  [parse-rev number.Codec #.Rev]
+  )
 
-(template: (!parse-int offset where source-code)
+(template: (!parse-int offset where source-code @end)
   (let [g!offset/1 (!inc offset)]
-    (<| (!with-char source-code g!offset/1 g!char/1)
+    (<| (!with-char source-code g!offset/1 g!char/1 @end)
         (if (!digit? g!char/1)
           (parse-int offset [where (!inc/2 offset) source-code])
           (!parse-full-name offset [where (!inc offset) source-code] where #.Identifier)))))
@@ -344,16 +323,12 @@
   (def: (parse-name-part start [where offset source-code])
     (-> Offset Source (Error [Source Text]))
     (loop [end offset]
-      (case ("lux text char" source-code end)
-        (#.Some char)
-        (cond (!name-char? char)
-              (recur (!inc end))
+      (<| (!with-char source-code end char )
+          (cond (!name-char? char)
+                (recur (!inc end))
 
-              ## else
-              )
-        
-        _
-        ))))
+                ## else
+                )))))
 
 (template: (!new-line where)
   (let [[where::file where::line where::column] where]
@@ -364,14 +339,6 @@
                    (as-is [where (!inc offset/0) source-code])
                    (as-is [where (!inc/2 offset/0) source-code])]
 
-  (template: (!with-char @source-code @offset @char @body)
-    (case ("lux text char" @source-code @offset)
-      (#.Some @char)
-      @body
-      
-      _
-      ))
-
   (template: (!parse-half-name @offset//pre @offset//post @char @module)
     (let [@offset//post (!inc @offset//pre)]
       (cond (!name-char?|head @char)
@@ -387,11 +354,11 @@
 
   (`` (def: (parse-short-name current-module [where offset/0 source-code])
         (-> Text Source (Error [Source Name]))
-        (<| (!with-char source-code offset/0 char/0)
+        (<| (!with-char source-code offset/0 char/0 )
             (case char/0
               (^ (char (~~ (static ..name-separator))))
               (let [offset/1 (!inc offset/0)]
-                (<| (!with-char source-code offset/1 char/1)
+                (<| (!with-char source-code offset/1 char/1 )
                     (!parse-half-name offset/1 offset/2 char/1 current-module)))
 
               _
@@ -411,23 +378,19 @@
           (case (..parse-name-part start source)
             (#error.Success [source' simple])
             (let [[where' offset' source-code'] source']
-              (case ("lux text char" source-code' offset')
-                (#.Some char/separator)
-                (case char/separator
-                  (^ (char (~~ (static ..name-separator))))
-                  (let [offset'' (!inc offset')]
-                    (case (..parse-name-part offset'' [where' offset'' source-code'])
-                      (#error.Success [source'' complex])
-                      (#error.Success [source'' [simple complex]])
-                      
-                      (#error.Error error)
-                      (#error.Error error)))
+              (<| (!with-char source-code' offset' char/separator )
+                  (case char/separator
+                    (^ (char (~~ (static ..name-separator))))
+                    (let [offset'' (!inc offset')]
+                      (case (..parse-name-part offset'' [where' offset'' source-code'])
+                        (#error.Success [source'' complex])
+                        (#error.Success [source'' [simple complex]])
+                        
+                        (#error.Error error)
+                        (#error.Error error)))
 
-                  _
-                  )
-                
-                _
-                ))
+                    _
+                    )))
             
             (#error.Error error)
             (#error.Error error)))))
@@ -444,7 +407,7 @@
     (-> Text Aliases Source (Error [Source Code]))
     (let [parse' (parse current-module aliases)]
       (loop [[where offset/0 source-code] source]
-        (<| (!with-char source-code offset/0 char/0)
+        (<| (!with-char source-code offset/0 char/0 )
             (`` (case char/0
                   ## White-space
                   (^template [ ]
@@ -477,7 +440,7 @@
                   ## Special code
                   (^ (char (~~ (static ..sigil))))
                   (let [offset/1 (!inc offset/0)]
-                    (<| (!with-char source-code offset/1 char/1)
+                    (<| (!with-char source-code offset/1 char/1 )
                         (case char/1
                           (^template [ ]
                             (^ (char ))
@@ -509,14 +472,14 @@
 
                   (^ (char (~~ (static ..name-separator))))
                   (let [offset/1 (!inc offset/0)]
-                    (<| (!with-char source-code offset/1 char/1)
+                    (<| (!with-char source-code offset/1 char/1 )
                         (if (!digit? char/1)
                           (parse-rev offset/0 [where (!inc offset/1) source-code])
                           (!parse-short-name current-module  where #.Identifier))))
 
                   (^template []
                     (^ (char ))
-                    (!parse-int offset/0 where source-code))
+                    (!parse-int offset/0 where source-code ))
                   ([(~~ (static ..positive-sign))]
                    [(~~ (static ..negative-sign))])
 
diff --git a/stdlib/source/lux/data/number.lux b/stdlib/source/lux/data/number.lux
index f2845f48c..efd965d1b 100644
--- a/stdlib/source/lux/data/number.lux
+++ b/stdlib/source/lux/data/number.lux
@@ -178,9 +178,11 @@
   )
 
 ## [Values & Syntax]
+(type: Char Nat)
+
 (def: (get-char! full idx)
-  (-> Text Nat Text)
-  ("lux text clip" full idx ("lux i64 +" 1 idx)))
+  (-> Text Nat Char)
+  ("lux text char" full idx))
 
 (def: (binary-character value)
   (-> Nat (Maybe Text))
@@ -190,10 +192,10 @@
     _ #.None))
 
 (def: (binary-value digit)
-  (-> Text (Maybe Nat))
+  (-> Char (Maybe Nat))
   (case digit
-    "0" (#.Some 0)
-    "1" (#.Some 1)
+    (^ (char "0")) (#.Some 0)
+    (^ (char "1")) (#.Some 1)
     _ #.None))
 
 (def: (octal-character value)
@@ -210,16 +212,16 @@
     _ #.None))
 
 (def: (octal-value digit)
-  (-> Text (Maybe Nat))
+  (-> Char (Maybe Nat))
   (case digit
-    "0" (#.Some 0)
-    "1" (#.Some 1)
-    "2" (#.Some 2)
-    "3" (#.Some 3)
-    "4" (#.Some 4)
-    "5" (#.Some 5)
-    "6" (#.Some 6)
-    "7" (#.Some 7)
+    (^ (char "0")) (#.Some 0)
+    (^ (char "1")) (#.Some 1)
+    (^ (char "2")) (#.Some 2)
+    (^ (char "3")) (#.Some 3)
+    (^ (char "4")) (#.Some 4)
+    (^ (char "5")) (#.Some 5)
+    (^ (char "6")) (#.Some 6)
+    (^ (char "7")) (#.Some 7)
     _ #.None))
 
 (def: (decimal-character value)
@@ -238,18 +240,18 @@
     _ #.None))
 
 (def: (decimal-value digit)
-  (-> Text (Maybe Nat))
+  (-> Char (Maybe Nat))
   (case digit
-    "0" (#.Some 0)
-    "1" (#.Some 1)
-    "2" (#.Some 2)
-    "3" (#.Some 3)
-    "4" (#.Some 4)
-    "5" (#.Some 5)
-    "6" (#.Some 6)
-    "7" (#.Some 7)
-    "8" (#.Some 8)
-    "9" (#.Some 9)
+    (^ (char "0")) (#.Some 0)
+    (^ (char "1")) (#.Some 1)
+    (^ (char "2")) (#.Some 2)
+    (^ (char "3")) (#.Some 3)
+    (^ (char "4")) (#.Some 4)
+    (^ (char "5")) (#.Some 5)
+    (^ (char "6")) (#.Some 6)
+    (^ (char "7")) (#.Some 7)
+    (^ (char "8")) (#.Some 8)
+    (^ (char "9")) (#.Some 9)
     _ #.None))
 
 (def: (hexadecimal-character value)
@@ -274,24 +276,24 @@
     _ #.None))
 
 (def: (hexadecimal-value digit)
-  (-> Text (Maybe Nat))
+  (-> Char (Maybe Nat))
   (case digit
-    "0" (#.Some 0)
-    "1" (#.Some 1)
-    "2" (#.Some 2)
-    "3" (#.Some 3)
-    "4" (#.Some 4)
-    "5" (#.Some 5)
-    "6" (#.Some 6)
-    "7" (#.Some 7)
-    "8" (#.Some 8)
-    "9" (#.Some 9)
-    (^or "a" "A") (#.Some 10)
-    (^or "b" "B") (#.Some 11)
-    (^or "c" "C") (#.Some 12)
-    (^or "d" "D") (#.Some 13)
-    (^or "e" "E") (#.Some 14)
-    (^or "f" "F") (#.Some 15)
+    (^ (char "0")) (#.Some 0)
+    (^ (char "1")) (#.Some 1)
+    (^ (char "2")) (#.Some 2)
+    (^ (char "3")) (#.Some 3)
+    (^ (char "4")) (#.Some 4)
+    (^ (char "5")) (#.Some 5)
+    (^ (char "6")) (#.Some 6)
+    (^ (char "7")) (#.Some 7)
+    (^ (char "8")) (#.Some 8)
+    (^ (char "9")) (#.Some 9)
+    (^or (^ (char "a")) (^ (char "A"))) (#.Some 10)
+    (^or (^ (char "b")) (^ (char "B"))) (#.Some 11)
+    (^or (^ (char "c")) (^ (char "C"))) (#.Some 12)
+    (^or (^ (char "d")) (^ (char "D"))) (#.Some 13)
+    (^or (^ (char "e")) (^ (char "E"))) (#.Some 14)
+    (^or (^ (char "f")) (^ (char "F"))) (#.Some 15)
     _ #.None))
 
 (do-template [    ]
@@ -337,17 +339,17 @@
 (def: (int/sign?? representation)
   (-> Text (Maybe Int))
   (case (get-char! representation 0)
-    "-"
+    (^ (char "-"))
     (#.Some -1)
 
-    "+"
+    (^ (char "+"))
     (#.Some +1)
 
     _
     #.None))
 
 (def: (int-decode-loop input-size repr sign   )
-  (-> Nat Text Int Int (-> Text (Maybe Nat)) Text (Error Int))
+  (-> Nat Text Int Int (-> Char (Maybe Nat)) Text (Error Int))
   (loop [idx 1
          output +0]
     (if (n/< input-size idx)
@@ -397,32 +399,36 @@
   ("lux text clip" input 1 ("lux text size" input)))
 
 (do-template [   ]
-  [(structure: #export  (Codec Text Rev)
-     (def: (encode value)
-       (let [raw-output (de-prefix (::  encode (:coerce Nat value)))
-             max-num-chars (n//  64)
-             raw-size ("lux text size" raw-output)
-             zero-padding (loop [zeroes-left (n/- raw-size max-num-chars)
-                                 output ""]
-                            (if (n/= 0 zeroes-left)
-                              output
-                              (recur (dec zeroes-left)
-                                     ("lux text concat" "0" output))))
-             padded-output ("lux text concat" zero-padding raw-output)]
-         ("lux text concat" "." padded-output)))
-
-     (def: (decode repr)
-       (let [repr-size ("lux text size" repr)]
-         (if (n/>= 2 repr-size)
-           (case ("lux text char" repr 0)
-             (^multi (^ (#.Some (char ".")))
-                     [(::  decode (de-prefix repr))
-                      (#error.Success output)])
-             (#error.Success (:coerce Rev output))
-
-             _
-             (#error.Error ("lux text concat"  repr)))
-           (#error.Error ("lux text concat"  repr))))))]
+  [(with-expansions [ (as-is (#error.Error ("lux text concat"  repr)))]
+     (structure: #export  (Codec Text Rev)
+       (def: (encode value)
+         (let [raw-output (de-prefix (::  encode (:coerce Nat value)))
+               max-num-chars (n//  64)
+               raw-size ("lux text size" raw-output)
+               zero-padding (loop [zeroes-left (n/- raw-size max-num-chars)
+                                   output ""]
+                              (if (n/= 0 zeroes-left)
+                                output
+                                (recur (dec zeroes-left)
+                                       ("lux text concat" "0" output))))
+               padded-output ("lux text concat" zero-padding raw-output)]
+           ("lux text concat" "." padded-output)))
+
+       (def: (decode repr)
+         (let [repr-size ("lux text size" repr)]
+           (if (n/>= 2 repr-size)
+             (case ("lux text char" repr 0)
+               (^ (char "."))
+               (case (::  decode (de-prefix repr))
+                 (#error.Success output)
+                 (#error.Success (:coerce Rev output))
+
+                 _
+                 )
+               
+               _
+               )
+             )))))]
 
   [Binary@Codec Binary@Codec 1 "Invalid binary syntax: "]
   [Octal@Codec  Octal@Codec  3 "Invalid octal syntax: "]
@@ -442,9 +448,9 @@
                               (if (f/= +0.0 dec-left)
                                 ("lux text concat" "." output)
                                 (let [shifted (f/*  dec-left)
-                                      digit (|> shifted (f/% ) frac-to-int .nat (get-char! ))]
+                                      digit-idx (|> shifted (f/% ) frac-to-int .nat)]
                                   (recur (f/% +1.0 shifted)
-                                         ("lux text concat" output digit))))))]
+                                         ("lux text concat" output ("lux text clip"  digit-idx (inc digit-idx))))))))]
          ("lux text concat" whole-part decimal-part)))
 
      (def: (decode repr)
@@ -826,7 +832,7 @@
       (loop [idx 0
              output (make-digits [])]
         (if (n/< length idx)
-          (case ("lux text index" "+0123456789" (get-char! input idx) 0)
+          (case ("lux text index" "+0123456789" ("lux text clip" input idx (inc idx)) 0)
             #.None
             #.None
 
diff --git a/stdlib/source/lux/data/text.lux b/stdlib/source/lux/data/text.lux
index c33ab03a3..18ad49032 100644
--- a/stdlib/source/lux/data/text.lux
+++ b/stdlib/source/lux/data/text.lux
@@ -38,7 +38,9 @@
 
 (def: #export (nth idx input)
   (-> Nat Text (Maybe Nat))
-  ("lux text char" input idx))
+  (if (n/< ("lux text size" input) idx)
+    (#.Some ("lux text char" input idx))
+    #.None))
 
 (def: #export (index-of' pattern from input)
   (-> Text Nat Text (Maybe Nat))
@@ -204,12 +206,11 @@
                (loop [idx 0
                       hash 0]
                  (if (n/< length idx)
-                   (let [char (|> idx ("lux text char" input) (maybe.default 0))]
-                     (recur (inc idx)
-                            (|> hash
-                                (i64.left-shift 5)
-                                (n/- hash)
-                                (n/+ char))))
+                   (recur (inc idx)
+                          (|> hash
+                              (i64.left-shift 5)
+                              (n/- hash)
+                              (n/+ ("lux text char" input idx))))
                    hash)))))))
 
 (def: #export concat
diff --git a/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux b/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux
index cfc164df9..108b350d0 100644
--- a/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux
+++ b/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux
@@ -165,7 +165,7 @@
             (test "Can query the size/length of a text."
                   (check-success+ "lux text size" (list subjectC) Nat))
             (test "Can obtain the character code of a text at a given index."
-                  (check-success+ "lux text char" (list subjectC fromC) (type (Maybe Nat))))
+                  (check-success+ "lux text char" (list subjectC fromC) Nat))
             (test "Can clip a piece of text between 2 indices."
                   (check-success+ "lux text clip" (list subjectC fromC toC) Text))
             ))))
-- 
cgit v1.2.3


From 9b106ea2fc8b55f8081154511b2b59ef821d5991 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 19:50:42 -0400
Subject: Optimized character extraction by not having to query the length of
 the source-code every time.

---
 stdlib/source/lux/compiler/default.lux        |  56 +++--
 stdlib/source/lux/compiler/default/syntax.lux | 300 +++++++++++++-------------
 stdlib/source/lux/interpreter.lux             |   5 +-
 3 files changed, 193 insertions(+), 168 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default.lux b/stdlib/source/lux/compiler/default.lux
index 1744b1143..73b018c95 100644
--- a/stdlib/source/lux/compiler/default.lux
+++ b/stdlib/source/lux/compiler/default.lux
@@ -5,7 +5,7 @@
     ["ex" exception (#+ exception:)]]
    [data
     ["." product]
-    ["." error]
+    ["." error (#+ Error)]
     [text ("text/." Hash)
      format
      ["." encoding]]
@@ -36,10 +36,20 @@
   ##       [cache/io])
   )
 
-(def: (read current-module aliases)
-  (-> Text Aliases (analysis.Operation Code))
+(type: Reader
+  (-> .Source (Error [.Source Code])))
+
+(def: (reader current-module aliases)
+  (-> Text Aliases (analysis.Operation Reader))
+  (function (_ [bundle state])
+    (let [[cursor offset source-code] (get@ #.source state)]
+      (#error.Success [[bundle state]
+                       (syntax.parse current-module aliases ("lux text size" source-code))]))))
+
+(def: (read reader)
+  (-> Reader (analysis.Operation Code))
   (function (_ [bundle compiler])
-    (case (syntax.parse current-module aliases (get@ #.source compiler))
+    (case (reader (get@ #.source compiler))
       (#error.Error error)
       (#error.Error error)
 
@@ -86,26 +96,30 @@
     (|>> module.set-compiled
          statement.lift-analysis))
 
-  (def: (loop-module-compilation module-name)
+  (def: (module-compilation-iteration reader)
+    (-> Reader (All [anchor expression statement] ))
+    (<| (phase.timed (name-of ..module-compilation-iteration) "ITERATION")
+        (do phase.Monad
+          [code (statement.lift-analysis
+                 (do @
+                   [code (<| (phase.timed (name-of ..module-compilation-iteration) "syntax")
+                             (..read reader))
+                    #let [[cursor _] code]
+                    _ (analysis.set-cursor cursor)]
+                   (wrap code)))
+           _ (<| (phase.timed (name-of ..module-compilation-iteration) "PHASE")
+                 (totalS.phase code))]
+          init.refresh)))
+  
+  (def: (module-compilation-loop module-name)
     (All [anchor expression statement]
       (-> Text ))
-    (let [iteration (: (All [anchor expression statement]
-                         )
-                       (<| (phase.timed (name-of ..loop-module-compilation) "ITERATION")
-                           (do phase.Monad
-                             [code (statement.lift-analysis
-                                    (do @
-                                      [code (<| (phase.timed (name-of ..loop-module-compilation) "syntax")
-                                                (..read module-name syntax.no-aliases))
-                                       #let [[cursor _] code]
-                                       _ (analysis.set-cursor cursor)]
-                                      (wrap code)))
-                              _ (<| (phase.timed (name-of ..loop-module-compilation) "PHASE")
-                                    (totalS.phase code))]
-                             init.refresh)))]
+    (do phase.Monad
+      [reader (statement.lift-analysis
+               (..reader module-name syntax.no-aliases))]
       (function (_ state)
         (loop [state state]
-          (case (iteration state)
+          (case (module-compilation-iteration reader state)
             (#error.Success [state' output])
             (recur state')
             
@@ -119,7 +133,7 @@
       (-> Text Source ))
     (do phase.Monad
       [_ (begin-module-compilation module-name source)
-       _ (loop-module-compilation module-name)]
+       _ (module-compilation-loop module-name)]
       (end-module-compilation module-name)))
 
   (def: #export (compile-module platform configuration compiler)
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index af7c7ae90..d724a150b 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -160,36 +160,39 @@
   [!n/- "lux i64 -"]
   )
 
-(template: (!with-char @source-code @offset @char @else @body)
-  (if (!i/< (:coerce Int ("lux text size" @source-code))
-            ## TODO: Get rid of the above "lux text size" call.
-            ## The size should be calculated only once and re-used constantly.
+(template: (!with-char+ @source-code-size @source-code @offset @char @else @body)
+  (if (!i/< (:coerce Int @source-code-size)
             (:coerce Int @offset))
     (let [@char ("lux text char" @source-code @offset)]
       @body)
     @else))
 
+(template: (!with-char @source-code @offset @char @else @body)
+  (!with-char+ ("lux text size" @source-code) @source-code @offset @char @else @body))
+
 (do-template [  ]
   [(def: ( parse source)
      (-> Parser Parser)
-     (loop [source source
-            stack (: (List Code) #.Nil)]
-       (case (parse source)
-         (#error.Success [source' top])
-         (recur source' (#.Cons top stack))
-         
-         (#error.Error error)
-         (let [[where offset source-code] source]
-           (<| (!with-char source-code offset char (#error.Error error))
-               (`` (case char
-                     (^ (char (~~ (static ))))
-                     (#error.Success [[(update@ #.column inc where)
-                                       (!inc offset)
-                                       source-code]
-                                      [where ( (list.reverse stack))]])
-
-                     _
-                     (ex.throw unrecognized-input where))))))))]
+     (let [[_ _ source-code] source
+           source-code//size ("lux text size" source-code)]
+       (loop [source source
+              stack (: (List Code) #.Nil)]
+         (case (parse source)
+           (#error.Success [source' top])
+           (recur source' (#.Cons top stack))
+           
+           (#error.Error error)
+           (let [[where offset _] source]
+             (<| (!with-char+ source-code//size source-code offset char (#error.Error error))
+                 (`` (case char
+                       (^ (char (~~ (static ))))
+                       (#error.Success [[(update@ #.column inc where)
+                                         (!inc offset)
+                                         source-code]
+                                        [where ( (list.reverse stack))]])
+
+                       _
+                       (ex.throw unrecognized-input where)))))))))]
 
   ## Form and tuple syntax is mostly the same, differing only in the
   ## delimiters involved.
@@ -200,29 +203,31 @@
 
 (def: (parse-record parse source)
   (-> Parser Parser)
-  (loop [source source
-         stack (: (List [Code Code]) #.Nil)]
-    (case (parse source)
-      (#error.Success [sourceF field])
-      (case (parse sourceF)
-        (#error.Success [sourceFV value])
-        (recur sourceFV (#.Cons [field value] stack))
+  (let [[_ _ source-code] source
+        source-code//size ("lux text size" source-code)]
+    (loop [source source
+           stack (: (List [Code Code]) #.Nil)]
+      (case (parse source)
+        (#error.Success [sourceF field])
+        (case (parse sourceF)
+          (#error.Success [sourceFV value])
+          (recur sourceFV (#.Cons [field value] stack))
+
+          (#error.Error error)
+          (let [[where offset _] source]
+            (<| (!with-char+ source-code//size source-code offset char (#error.Error error))
+                (`` (case char
+                      (^ (char (~~ (static ..close-record))))
+                      (#error.Success [[(update@ #.column inc where)
+                                        (!inc offset)
+                                        source-code]
+                                       [where (#.Record (list.reverse stack))]])
+
+                      _
+                      (ex.throw unrecognized-input where))))))
 
         (#error.Error error)
-        (let [[where offset source-code] source]
-          (<| (!with-char source-code offset char (#error.Error error))
-              (`` (case char
-                    (^ (char (~~ (static ..close-record))))
-                    (#error.Success [[(update@ #.column inc where)
-                                      (!inc offset)
-                                      source-code]
-                                     [where (#.Record (list.reverse stack))]])
-
-                    _
-                    (ex.throw unrecognized-input where))))))
-
-      (#error.Error error)
-      (#error.Error error))))
+        (#error.Error error)))))
 
 (template: (!guarantee-no-new-lines content body)
   (case ("lux text index" content (static text.new-line) 0)
@@ -298,20 +303,21 @@
 (do-template [  ]
   [(def: ( start [where offset source-code])
      (-> Offset Parser)
-     (loop [end offset]
-       (<| (!with-char source-code end char (!discrete-output  ))
-           (if (!digit?+ char)
-             (recur (!inc end))
-             (!discrete-output  )))))]
+     (let [source-code//size ("lux text size" source-code)]
+       (loop [end offset]
+         (<| (!with-char+ source-code//size source-code end char (!discrete-output  ))
+             (if (!digit?+ char)
+               (recur (!inc end))
+               (!discrete-output  ))))))]
 
   [parse-nat number.Codec #.Nat]
   [parse-int number.Codec #.Int]
   [parse-rev number.Codec #.Rev]
   )
 
-(template: (!parse-int offset where source-code @end)
+(template: (!parse-int source-code//size offset where source-code @end)
   (let [g!offset/1 (!inc offset)]
-    (<| (!with-char source-code g!offset/1 g!char/1 @end)
+    (<| (!with-char+ source-code//size source-code g!offset/1 g!char/1 @end)
         (if (!digit? g!char/1)
           (parse-int offset [where (!inc/2 offset) source-code])
           (!parse-full-name offset [where (!inc offset) source-code] where #.Identifier)))))
@@ -322,13 +328,14 @@
                                             (!clip start end source-code)])]
   (def: (parse-name-part start [where offset source-code])
     (-> Offset Source (Error [Source Text]))
-    (loop [end offset]
-      (<| (!with-char source-code end char )
-          (cond (!name-char? char)
-                (recur (!inc end))
+    (let [source-code//size ("lux text size" source-code)]
+      (loop [end offset]
+        (<| (!with-char+ source-code//size source-code end char )
+            (cond (!name-char? char)
+                  (recur (!inc end))
 
-                ## else
-                )))))
+                  ## else
+                  ))))))
 
 (template: (!new-line where)
   (let [[where::file where::line where::column] where]
@@ -403,93 +410,96 @@
       (#error.Error error)
       (#error.Error error)))
   
-  (def: #export (parse current-module aliases source)
-    (-> Text Aliases Source (Error [Source Code]))
-    (let [parse' (parse current-module aliases)]
-      (loop [[where offset/0 source-code] source]
-        (<| (!with-char source-code offset/0 char/0 )
-            (`` (case char/0
-                  ## White-space
-                  (^template [ ]
-                    (^ (char ))
-                    (recur [(update@  inc where)
-                            (!inc offset/0)
-                            source-code]))
-                  ([(~~ (static ..space))              #.column]
-                   [(~~ (static text.carriage-return)) #.column])
-
-                  (^ (char (~~ (static text.new-line))))
-                  (recur [(!new-line where) (!inc offset/0) source-code])
-
-                  ## Form
-                  (^ (char (~~ (static ..open-form))))
-                  (parse-form parse' )
-
-                  ## Tuple
-                  (^ (char (~~ (static ..open-tuple))))
-                  (parse-tuple parse' )
-
-                  ## Record
-                  (^ (char (~~ (static ..open-record))))
-                  (parse-record parse' )
-
-                  ## Text
-                  (^ (char (~~ (static ..text-delimiter))))
-                  (read-text )
-
-                  ## Special code
-                  (^ (char (~~ (static ..sigil))))
-                  (let [offset/1 (!inc offset/0)]
-                    (<| (!with-char source-code offset/1 char/1 )
-                        (case char/1
-                          (^template [ ]
-                            (^ (char ))
-                            (#error.Success [[(update@ #.column (|>> !inc/2) where)
-                                              (!inc offset/1)
-                                              source-code]
-                                             [where (#.Bit )]]))
-                          (["0" #0]
-                           ["1" #1])
-
-                          ## Single-line comment
-                          (^ (char (~~ (static ..sigil))))
-                          (case ("lux text index" source-code (static text.new-line) offset/1)
-                            (#.Some end)
-                            (recur [(!new-line where) (!inc end) source-code])
-                            
+  (with-expansions [ (as-is (parse current-module aliases source-code//size))]
+    (def: #export (parse current-module aliases source-code//size)
+      (-> Text Aliases Nat (-> Source (Error [Source Code])))
+      ## The "exec []" is only there to avoid function fusion.
+      ## This is to preserve the loop as much as possible and keep it tight.
+      (exec []
+        (function (recur [where offset/0 source-code])
+          (<| (!with-char+ source-code//size source-code offset/0 char/0 )
+              (`` (case char/0
+                    ## White-space
+                    (^template [ ]
+                      (^ (char ))
+                      (recur [(update@  inc where)
+                              (!inc offset/0)
+                              source-code]))
+                    ([(~~ (static ..space))              #.column]
+                     [(~~ (static text.carriage-return)) #.column])
+
+                    (^ (char (~~ (static text.new-line))))
+                    (recur [(!new-line where) (!inc offset/0) source-code])
+
+                    ## Form
+                    (^ (char (~~ (static ..open-form))))
+                    (parse-form  )
+
+                    ## Tuple
+                    (^ (char (~~ (static ..open-tuple))))
+                    (parse-tuple  )
+
+                    ## Record
+                    (^ (char (~~ (static ..open-record))))
+                    (parse-record  )
+
+                    ## Text
+                    (^ (char (~~ (static ..text-delimiter))))
+                    (read-text )
+
+                    ## Special code
+                    (^ (char (~~ (static ..sigil))))
+                    (let [offset/1 (!inc offset/0)]
+                      (<| (!with-char+ source-code//size source-code offset/1 char/1 )
+                          (case char/1
+                            (^template [ ]
+                              (^ (char ))
+                              (#error.Success [[(update@ #.column (|>> !inc/2) where)
+                                                (!inc offset/1)
+                                                source-code]
+                                               [where (#.Bit )]]))
+                            (["0" #0]
+                             ["1" #1])
+
+                            ## Single-line comment
+                            (^ (char (~~ (static ..sigil))))
+                            (case ("lux text index" source-code (static text.new-line) offset/1)
+                              (#.Some end)
+                              (recur [(!new-line where) (!inc end) source-code])
+                              
+                              _
+                              )
+
+                            (^ (char (~~ (static ..name-separator))))
+                            (!parse-short-name current-module  where #.Identifier)
+
                             _
-                            )
-
-                          (^ (char (~~ (static ..name-separator))))
-                          (!parse-short-name current-module  where #.Identifier)
-
-                          _
-                          (cond (!name-char?|head char/1) ## Tag
-                                (!parse-full-name offset/1  where #.Tag)
-
-                                ## else
-                                ))))
-
-                  (^ (char (~~ (static ..name-separator))))
-                  (let [offset/1 (!inc offset/0)]
-                    (<| (!with-char source-code offset/1 char/1 )
-                        (if (!digit? char/1)
-                          (parse-rev offset/0 [where (!inc offset/1) source-code])
-                          (!parse-short-name current-module  where #.Identifier))))
-
-                  (^template []
-                    (^ (char ))
-                    (!parse-int offset/0 where source-code ))
-                  ([(~~ (static ..positive-sign))]
-                   [(~~ (static ..negative-sign))])
-
-                  _
-                  (cond (!digit? char/0) ## Natural number
-                        (parse-nat offset/0 )
-
-                        ## Identifier
-                        (!name-char?|head char/0)
-                        (!parse-full-name offset/0  where #.Identifier)
-                        
-                        ## else
-                        ))))))))
+                            (cond (!name-char?|head char/1) ## Tag
+                                  (!parse-full-name offset/1  where #.Tag)
+
+                                  ## else
+                                  ))))
+
+                    (^ (char (~~ (static ..name-separator))))
+                    (let [offset/1 (!inc offset/0)]
+                      (<| (!with-char+ source-code//size source-code offset/1 char/1 )
+                          (if (!digit? char/1)
+                            (parse-rev offset/0 [where (!inc offset/1) source-code])
+                            (!parse-short-name current-module  where #.Identifier))))
+
+                    (^template []
+                      (^ (char ))
+                      (!parse-int source-code//size offset/0 where source-code ))
+                    ([(~~ (static ..positive-sign))]
+                     [(~~ (static ..negative-sign))])
+
+                    _
+                    (cond (!digit? char/0) ## Natural number
+                          (parse-nat offset/0 )
+
+                          ## Identifier
+                          (!name-char?|head char/0)
+                          (!parse-full-name offset/0  where #.Identifier)
+                          
+                          ## else
+                          )))))))))
diff --git a/stdlib/source/lux/interpreter.lux b/stdlib/source/lux/interpreter.lux
index 41edcb708..e44084bc0 100644
--- a/stdlib/source/lux/interpreter.lux
+++ b/stdlib/source/lux/interpreter.lux
@@ -44,7 +44,7 @@
   Text
   (format text.new-line
           "Welcome to the interpreter!" text.new-line
-          "Type 'exit' to leave." text.new-line
+          "Type '" ..exit-command "' to leave." text.new-line
           text.new-line))
 
 (def: farewell-message
@@ -164,7 +164,8 @@
     (All [anchor expression statement]
       (->  (Error [ Text])))
     (do error.Monad
-      [[source' input] (syntax.parse ..module syntax.no-aliases (get@ #source context))
+      [#let [[_where _offset _code] (get@ #source context)]
+       [source' input] (syntax.parse ..module syntax.no-aliases (text.size _code) (get@ #source context))
        [state' representation] (let [## TODO: Simplify ASAP
                                      state (:share [anchor expression statement]
                                                    {
-- 
cgit v1.2.3


From a7f0b1e2c0f2c7c2f5d3fb0ea6e35e3f5957e1fd Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 22:20:43 -0400
Subject: Added a special compiler optimization to pattern-match on characters
 faster.

---
 stdlib/source/lux/compiler/default/syntax.lux | 102 +++++++++++++-------------
 1 file changed, 52 insertions(+), 50 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index d724a150b..1584321e5 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -410,7 +410,10 @@
       (#error.Error error)
       (#error.Error error)))
   
-  (with-expansions [ (as-is (parse current-module aliases source-code//size))]
+  (with-expansions [ (as-is (parse current-module aliases source-code//size))
+                     (as-is (recur [(update@ #.column inc where)
+                                                     (!inc offset/0)
+                                                     source-code]))]
     (def: #export (parse current-module aliases source-code//size)
       (-> Text Aliases Nat (-> Source (Error [Source Code])))
       ## The "exec []" is only there to avoid function fusion.
@@ -418,51 +421,50 @@
       (exec []
         (function (recur [where offset/0 source-code])
           (<| (!with-char+ source-code//size source-code offset/0 char/0 )
-              (`` (case char/0
-                    ## White-space
-                    (^template [ ]
-                      (^ (char ))
-                      (recur [(update@  inc where)
-                              (!inc offset/0)
-                              source-code]))
-                    ([(~~ (static ..space))              #.column]
-                     [(~~ (static text.carriage-return)) #.column])
-
-                    (^ (char (~~ (static text.new-line))))
+              (`` ("lux syntax char case!" char/0
+                   [## White-space
+                    (~~ (static ..space))
+                    
+                    
+                    (~~ (static text.carriage-return))
+                    
+
+                    (~~ (static text.new-line))
                     (recur [(!new-line where) (!inc offset/0) source-code])
 
                     ## Form
-                    (^ (char (~~ (static ..open-form))))
+                    (~~ (static ..open-form))
                     (parse-form  )
 
                     ## Tuple
-                    (^ (char (~~ (static ..open-tuple))))
+                    (~~ (static ..open-tuple))
                     (parse-tuple  )
 
                     ## Record
-                    (^ (char (~~ (static ..open-record))))
+                    (~~ (static ..open-record))
                     (parse-record  )
 
                     ## Text
-                    (^ (char (~~ (static ..text-delimiter))))
+                    (~~ (static ..text-delimiter))
                     (read-text )
 
                     ## Special code
-                    (^ (char (~~ (static ..sigil))))
+                    (~~ (static ..sigil))
                     (let [offset/1 (!inc offset/0)]
                       (<| (!with-char+ source-code//size source-code offset/1 char/1 )
-                          (case char/1
-                            (^template [ ]
-                              (^ (char ))
-                              (#error.Success [[(update@ #.column (|>> !inc/2) where)
-                                                (!inc offset/1)
-                                                source-code]
-                                               [where (#.Bit )]]))
-                            (["0" #0]
-                             ["1" #1])
+                          ("lux syntax char case!" char/1
+                           [(~~ (do-template [ ]
+                                  [
+                                   (#error.Success [[(update@ #.column (|>> !inc/2) where)
+                                                     (!inc offset/1)
+                                                     source-code]
+                                                    [where (#.Bit )]])]
+
+                                  ["0" #0]
+                                  ["1" #1]))
 
                             ## Single-line comment
-                            (^ (char (~~ (static ..sigil))))
+                            (~~ (static ..sigil))
                             (case ("lux text index" source-code (static text.new-line) offset/1)
                               (#.Some end)
                               (recur [(!new-line where) (!inc end) source-code])
@@ -470,36 +472,36 @@
                               _
                               )
 
-                            (^ (char (~~ (static ..name-separator))))
-                            (!parse-short-name current-module  where #.Identifier)
+                            (~~ (static ..name-separator))
+                            (!parse-short-name current-module  where #.Identifier)]
 
-                            _
-                            (cond (!name-char?|head char/1) ## Tag
-                                  (!parse-full-name offset/1  where #.Tag)
+                           ## else
+                           (cond (!name-char?|head char/1) ## Tag
+                                 (!parse-full-name offset/1  where #.Tag)
 
-                                  ## else
-                                  ))))
+                                 ## else
+                                 ))))
 
-                    (^ (char (~~ (static ..name-separator))))
+                    (~~ (static ..name-separator))
                     (let [offset/1 (!inc offset/0)]
                       (<| (!with-char+ source-code//size source-code offset/1 char/1 )
                           (if (!digit? char/1)
                             (parse-rev offset/0 [where (!inc offset/1) source-code])
                             (!parse-short-name current-module  where #.Identifier))))
 
-                    (^template []
-                      (^ (char ))
-                      (!parse-int source-code//size offset/0 where source-code ))
-                    ([(~~ (static ..positive-sign))]
-                     [(~~ (static ..negative-sign))])
+                    (~~ (static ..positive-sign))
+                    (!parse-int source-code//size offset/0 where source-code )
 
-                    _
-                    (cond (!digit? char/0) ## Natural number
-                          (parse-nat offset/0 )
-
-                          ## Identifier
-                          (!name-char?|head char/0)
-                          (!parse-full-name offset/0  where #.Identifier)
-                          
-                          ## else
-                          )))))))))
+                    (~~ (static ..negative-sign))
+                    (!parse-int source-code//size offset/0 where source-code )]
+
+                   ## else
+                   (cond (!digit? char/0) ## Natural number
+                         (parse-nat offset/0 )
+
+                         ## Identifier
+                         (!name-char?|head char/0)
+                         (!parse-full-name offset/0  where #.Identifier)
+                         
+                         ## else
+                         )))))))))
-- 
cgit v1.2.3


From 7c52f72aad338a0f14ed173926784373e551be71 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Thu, 23 Aug 2018 22:45:31 -0400
Subject: More inlining.

---
 stdlib/source/lux/compiler/default/syntax.lux | 58 ++++++++++++++++-----------
 1 file changed, 35 insertions(+), 23 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 1584321e5..d281cc168 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -237,17 +237,16 @@
     g!_
     body))
 
-(def: (read-text [where offset source-code])
-  Parser
+(template: (!read-text where offset source-code)
   (case ("lux text index" source-code (static ..text-delimiter) offset)
-    (#.Some end)
-    (let [content (!clip offset end source-code)]
-      (<| (!guarantee-no-new-lines content)
-          (#error.Success [[(update@ #.column (n/+ (!n/- offset end)) where)
-                            (!inc end)
+    (#.Some g!end)
+    (let [g!content (!clip offset g!end source-code)]
+      (<| (!guarantee-no-new-lines g!content)
+          (#error.Success [[(update@ #.column (n/+ (!n/- offset g!end)) where)
+                            (!inc g!end)
                             source-code]
                            [where
-                            (#.Text content)]])))
+                            (#.Text g!content)]])))
     
     _
     (ex.throw unrecognized-input where)))
@@ -289,11 +288,11 @@
   (or (!strict-name-char? char)
       (!digit? char)))
 
-(template: (!discrete-output  )
-  (case (::  decode (!clip start end source-code))
+(template: (!discrete-output    )
+  (case (::  decode (!clip   source-code))
     (#error.Success output)
-    (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
-                      end
+    (#error.Success [[(update@ #.column (n/+ (!n/-  )) where)
+                      
                       source-code]
                      [where ( output)]])
 
@@ -305,17 +304,27 @@
      (-> Offset Parser)
      (let [source-code//size ("lux text size" source-code)]
        (loop [end offset]
-         (<| (!with-char+ source-code//size source-code end char (!discrete-output  ))
+         (<| (!with-char+ source-code//size source-code end char (!discrete-output start end  ))
              (if (!digit?+ char)
                (recur (!inc end))
-               (!discrete-output  ))))))]
+               (!discrete-output start end  ))))))]
 
-  [parse-nat number.Codec #.Nat]
   [parse-int number.Codec #.Int]
-  [parse-rev number.Codec #.Rev]
   )
 
-(template: (!parse-int source-code//size offset where source-code @end)
+(do-template [  ]
+  [(template: ( source-code//size start where offset source-code)
+     (loop [g!end offset]
+       (<| (!with-char+ source-code//size source-code g!end g!char (!discrete-output start g!end  ))
+           (if (!digit?+ g!char)
+             (recur (!inc g!end))
+             (!discrete-output start g!end  )))))]
+
+  [!parse-nat number.Codec #.Nat]
+  [!parse-rev number.Codec #.Rev]
+  )
+
+(template: (!parse-signed source-code//size offset where source-code @end)
   (let [g!offset/1 (!inc offset)]
     (<| (!with-char+ source-code//size source-code g!offset/1 g!char/1 @end)
         (if (!digit? g!char/1)
@@ -446,7 +455,8 @@
 
                     ## Text
                     (~~ (static ..text-delimiter))
-                    (read-text )
+                    (let [offset/1 (!inc offset/0)]
+                      (!read-text where offset/1 source-code))
 
                     ## Special code
                     (~~ (static ..sigil))
@@ -486,21 +496,23 @@
                     (let [offset/1 (!inc offset/0)]
                       (<| (!with-char+ source-code//size source-code offset/1 char/1 )
                           (if (!digit? char/1)
-                            (parse-rev offset/0 [where (!inc offset/1) source-code])
+                            (let [offset/2 (!inc offset/1)]
+                              (!parse-rev source-code//size offset/0 where offset/2 source-code))
                             (!parse-short-name current-module  where #.Identifier))))
 
                     (~~ (static ..positive-sign))
-                    (!parse-int source-code//size offset/0 where source-code )
+                    (!parse-signed source-code//size offset/0 where source-code )
 
                     (~~ (static ..negative-sign))
-                    (!parse-int source-code//size offset/0 where source-code )]
+                    (!parse-signed source-code//size offset/0 where source-code )]
 
                    ## else
                    (cond (!digit? char/0) ## Natural number
-                         (parse-nat offset/0 )
+                         (let [offset/1 (!inc offset/0)]
+                           (!parse-nat source-code//size offset/0 where offset/1 source-code))
 
                          ## Identifier
-                         (!name-char?|head char/0)
+                         (!strict-name-char? char/0)
                          (!parse-full-name offset/0  where #.Identifier)
                          
                          ## else
-- 
cgit v1.2.3


From 676fbcc0d6a8962ce9cb83136b2a0d0e9ff1e28e Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Fri, 24 Aug 2018 00:19:02 -0400
Subject: Some micro-optimizations.

---
 stdlib/source/lux/compiler/default/syntax.lux | 245 +++++++++++++-------------
 1 file changed, 124 insertions(+), 121 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index d281cc168..2d6643da3 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -40,6 +40,10 @@
      ["." list]
      ["." dictionary (#+ Dictionary)]]]])
 
+## TODO: Implement "lux syntax char case!" as a custom extension.
+## That way, it should be possible to obtain the char without wrapping
+## it into a java.lang.Long, thereby improving performance.
+
 (type: #export Syntax
   (-> Cursor (Lexer [Cursor Code])))
 
@@ -149,8 +153,13 @@
 (template: (!clip from to text)
   ("lux text clip" text from to))
 
-(template: (!i/< reference subject)
-  ("lux int <" subject reference))
+(do-template [ ]
+  [(template: ( reference subject)
+     ( subject reference))]
+
+  [!n/= "lux i64 ="]
+  [!i/< "lux int <"]
+  )
 
 (do-template [ ]
   [(template: ( param subject)
@@ -183,16 +192,13 @@
            
            (#error.Error error)
            (let [[where offset _] source]
-             (<| (!with-char+ source-code//size source-code offset char (#error.Error error))
-                 (`` (case char
-                       (^ (char (~~ (static ))))
-                       (#error.Success [[(update@ #.column inc where)
-                                         (!inc offset)
-                                         source-code]
-                                        [where ( (list.reverse stack))]])
-
-                       _
-                       (ex.throw unrecognized-input where)))))))))]
+             (<| (!with-char+ source-code//size source-code offset closing-char (#error.Error error))
+                 (if (`` (!n/= (char (~~ (static ))) closing-char))
+                   (#error.Success [[(update@ #.column inc where)
+                                     (!inc offset)
+                                     source-code]
+                                    [where ( (list.reverse stack))]])
+                   (ex.throw unrecognized-input where))))))))]
 
   ## Form and tuple syntax is mostly the same, differing only in the
   ## delimiters involved.
@@ -215,16 +221,13 @@
 
           (#error.Error error)
           (let [[where offset _] source]
-            (<| (!with-char+ source-code//size source-code offset char (#error.Error error))
-                (`` (case char
-                      (^ (char (~~ (static ..close-record))))
-                      (#error.Success [[(update@ #.column inc where)
-                                        (!inc offset)
-                                        source-code]
-                                       [where (#.Record (list.reverse stack))]])
-
-                      _
-                      (ex.throw unrecognized-input where))))))
+            (<| (!with-char+ source-code//size source-code offset closing-char (#error.Error error))
+                (if (`` (!n/= (char (~~ (static ..close-record))) closing-char))
+                  (#error.Success [[(update@ #.column inc where)
+                                    (!inc offset)
+                                    source-code]
+                                   [where (#.Record (list.reverse stack))]])
+                  (ex.throw unrecognized-input where)))))
 
         (#error.Error error)
         (#error.Error error)))))
@@ -340,11 +343,9 @@
     (let [source-code//size ("lux text size" source-code)]
       (loop [end offset]
         (<| (!with-char+ source-code//size source-code end char )
-            (cond (!name-char? char)
-                  (recur (!inc end))
-
-                  ## else
-                  ))))))
+            (if (!name-char? char)
+              (recur (!inc end))
+              ))))))
 
 (template: (!new-line where)
   (let [[where::file where::line where::column] where]
@@ -371,13 +372,10 @@
   (`` (def: (parse-short-name current-module [where offset/0 source-code])
         (-> Text Source (Error [Source Name]))
         (<| (!with-char source-code offset/0 char/0 )
-            (case char/0
-              (^ (char (~~ (static ..name-separator))))
+            (if (!n/= (char (~~ (static ..name-separator))) char/0)
               (let [offset/1 (!inc offset/0)]
                 (<| (!with-char source-code offset/1 char/1 )
                     (!parse-half-name offset/1 offset/2 char/1 current-module)))
-
-              _
               (!parse-half-name offset/0 offset/1 char/0 ..prelude)))))
 
   (template: (!parse-short-name @current-module @source @where @tag)
@@ -395,8 +393,7 @@
             (#error.Success [source' simple])
             (let [[where' offset' source-code'] source']
               (<| (!with-char source-code' offset' char/separator )
-                  (case char/separator
-                    (^ (char (~~ (static ..name-separator))))
+                  (if (!n/= (char (~~ (static ..name-separator))) char/separator)
                     (let [offset'' (!inc offset')]
                       (case (..parse-name-part offset'' [where' offset'' source-code'])
                         (#error.Success [source'' complex])
@@ -404,8 +401,6 @@
                         
                         (#error.Error error)
                         (#error.Error error)))
-
-                    _
                     )))
             
             (#error.Error error)
@@ -418,6 +413,11 @@
       
       (#error.Error error)
       (#error.Error error)))
+
+  (`` (template: (<>)
+        [(~~ (static ..close-form))
+         (~~ (static ..close-tuple))
+         (~~ (static ..close-record))]))
   
   (with-expansions [ (as-is (parse current-module aliases source-code//size))
                      (as-is (recur [(update@ #.column inc where)
@@ -430,90 +430,93 @@
       (exec []
         (function (recur [where offset/0 source-code])
           (<| (!with-char+ source-code//size source-code offset/0 char/0 )
-              (`` ("lux syntax char case!" char/0
-                   [## White-space
-                    (~~ (static ..space))
+              ## The space was singled-out for special treatment
+              ## because of how common it is.
+              (`` (if (!n/= (char (~~ (static ..space))) char/0)
                     
-                    
-                    (~~ (static text.carriage-return))
-                    
-
-                    (~~ (static text.new-line))
-                    (recur [(!new-line where) (!inc offset/0) source-code])
-
-                    ## Form
-                    (~~ (static ..open-form))
-                    (parse-form  )
-
-                    ## Tuple
-                    (~~ (static ..open-tuple))
-                    (parse-tuple  )
-
-                    ## Record
-                    (~~ (static ..open-record))
-                    (parse-record  )
-
-                    ## Text
-                    (~~ (static ..text-delimiter))
-                    (let [offset/1 (!inc offset/0)]
-                      (!read-text where offset/1 source-code))
-
-                    ## Special code
-                    (~~ (static ..sigil))
-                    (let [offset/1 (!inc offset/0)]
-                      (<| (!with-char+ source-code//size source-code offset/1 char/1 )
-                          ("lux syntax char case!" char/1
-                           [(~~ (do-template [ ]
-                                  [
-                                   (#error.Success [[(update@ #.column (|>> !inc/2) where)
-                                                     (!inc offset/1)
-                                                     source-code]
-                                                    [where (#.Bit )]])]
-
-                                  ["0" #0]
-                                  ["1" #1]))
-
-                            ## Single-line comment
-                            (~~ (static ..sigil))
-                            (case ("lux text index" source-code (static text.new-line) offset/1)
-                              (#.Some end)
-                              (recur [(!new-line where) (!inc end) source-code])
-                              
-                              _
-                              )
-
-                            (~~ (static ..name-separator))
-                            (!parse-short-name current-module  where #.Identifier)]
-
-                           ## else
-                           (cond (!name-char?|head char/1) ## Tag
-                                 (!parse-full-name offset/1  where #.Tag)
-
-                                 ## else
-                                 ))))
-
-                    (~~ (static ..name-separator))
-                    (let [offset/1 (!inc offset/0)]
-                      (<| (!with-char+ source-code//size source-code offset/1 char/1 )
-                          (if (!digit? char/1)
-                            (let [offset/2 (!inc offset/1)]
-                              (!parse-rev source-code//size offset/0 where offset/2 source-code))
-                            (!parse-short-name current-module  where #.Identifier))))
-
-                    (~~ (static ..positive-sign))
-                    (!parse-signed source-code//size offset/0 where source-code )
-
-                    (~~ (static ..negative-sign))
-                    (!parse-signed source-code//size offset/0 where source-code )]
-
-                   ## else
-                   (cond (!digit? char/0) ## Natural number
-                         (let [offset/1 (!inc offset/0)]
-                           (!parse-nat source-code//size offset/0 where offset/1 source-code))
-
-                         ## Identifier
-                         (!strict-name-char? char/0)
-                         (!parse-full-name offset/0  where #.Identifier)
-                         
-                         ## else
-                         )))))))))
+                    ("lux syntax char case!" char/0
+                     [## New line
+                      [(~~ (static text.carriage-return))]
+                      
+                      
+                      [(~~ (static text.new-line))]
+                      (recur [(!new-line where) (!inc offset/0) source-code])
+
+                      ## Form
+                      [(~~ (static ..open-form))]
+                      (parse-form  )
+
+                      ## Tuple
+                      [(~~ (static ..open-tuple))]
+                      (parse-tuple  )
+
+                      ## Record
+                      [(~~ (static ..open-record))]
+                      (parse-record  )
+
+                      ## Text
+                      [(~~ (static ..text-delimiter))]
+                      (let [offset/1 (!inc offset/0)]
+                        (!read-text where offset/1 source-code))
+
+                      ## Special code
+                      [(~~ (static ..sigil))]
+                      (let [offset/1 (!inc offset/0)]
+                        (<| (!with-char+ source-code//size source-code offset/1 char/1 )
+                            ("lux syntax char case!" char/1
+                             [(~~ (do-template [ ]
+                                    [[]
+                                     (#error.Success [[(update@ #.column (|>> !inc/2) where)
+                                                       (!inc offset/1)
+                                                       source-code]
+                                                      [where (#.Bit )]])]
+
+                                    ["0" #0]
+                                    ["1" #1]))
+
+                              ## Single-line comment
+                              [(~~ (static ..sigil))]
+                              (case ("lux text index" source-code (static text.new-line) offset/1)
+                                (#.Some end)
+                                (recur [(!new-line where) (!inc end) source-code])
+                                
+                                _
+                                )
+
+                              [(~~ (static ..name-separator))]
+                              (!parse-short-name current-module  where #.Identifier)]
+
+                             ## else
+                             (cond (!name-char?|head char/1) ## Tag
+                                   (!parse-full-name offset/1  where #.Tag)
+
+                                   ## else
+                                   ))))
+
+                      [(~~ (static ..name-separator))]
+                      (let [offset/1 (!inc offset/0)]
+                        (<| (!with-char+ source-code//size source-code offset/1 char/1 )
+                            (if (!digit? char/1)
+                              (let [offset/2 (!inc offset/1)]
+                                (!parse-rev source-code//size offset/0 where offset/2 source-code))
+                              (!parse-short-name current-module  where #.Identifier))))
+
+                      [(~~ (static ..positive-sign))
+                       (~~ (static ..negative-sign))]
+                      (!parse-signed source-code//size offset/0 where source-code )
+
+                      ## Invalid characters at this point...
+                      (~~ (<>))
+                      ]
+
+                     ## else
+                     (if (!digit? char/0)
+                       ## Natural number
+                       (let [offset/1 (!inc offset/0)]
+                         (!parse-nat source-code//size offset/0 where offset/1 source-code))
+                       ## Identifier
+                       (!parse-full-name offset/0  where #.Identifier))
+                     )))
+              )))
+      ))
+  )
-- 
cgit v1.2.3


From db4d1dd31ac1860efb73f6326822c192302ecf25 Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Sat, 25 Aug 2018 00:48:47 -0400
Subject: - Fixed some bugs. - Improved performance.

---
 stdlib/source/lux/compiler/default/syntax.lux | 201 +++++++++++++++-----------
 1 file changed, 117 insertions(+), 84 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 2d6643da3..8cb41536e 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -40,6 +40,41 @@
      ["." list]
      ["." dictionary (#+ Dictionary)]]]])
 
+(type: Char Nat)
+
+(do-template [  ]
+  [(template: ( value)
+     ( value ))]
+
+  [!inc   "lux i64 +" 1]
+  [!inc/2 "lux i64 +" 2]
+  [!dec   "lux i64 -" 1]
+  )
+
+(template: (!clip from to text)
+  ("lux text clip" text from to))
+
+(do-template [ ]
+  [(template: ( reference subject)
+     ( subject reference))]
+
+  [!n/= "lux i64 ="]
+  [!i/< "lux int <"]
+  )
+
+(do-template [ ]
+  [(template: ( param subject)
+     ( subject param))]
+
+  [!n/+ "lux i64 +"]
+  [!n/- "lux i64 -"]
+  )
+
+## TODO: Optimize how forms, tuples & records are parsed in the end.
+## There is repeated-work going on when parsing the space before the
+## closing parenthesis/bracket/brace.
+## That repeated-work should be avoided.
+
 ## TODO: Implement "lux syntax char case!" as a custom extension.
 ## That way, it should be possible to obtain the char without wrapping
 ## it into a java.lang.Long, thereby improving performance.
@@ -120,10 +155,15 @@
 (exception: #export (end-of-file {module Text})
   (ex.report ["Module" (%t module)]))
 
-(exception: #export (unrecognized-input {[file line column] Cursor})
-  (ex.report ["File" (%t file)]
-             ["Line" (%n line)]
-             ["Column" (%n column)]))
+(def: amount-of-input-shown 64)
+
+(exception: #export (unrecognized-input {[file line column] Cursor} {context Text} {input Text} {offset Offset})
+  (let [end-offset (|> offset (n/+ amount-of-input-shown) (n/min ("lux text size" input)))]
+    (ex.report ["File" file]
+               ["Line" (%n line)]
+               ["Column" (%n column)]
+               ["Context" (%t context)]
+               ["Input" (!clip offset end-offset input)])))
 
 (exception: #export (text-cannot-contain-new-lines {text Text})
   (ex.report ["Text" (%t text)]))
@@ -131,6 +171,9 @@
 (exception: #export (invalid-escape-syntax)
   "")
 
+(exception: #export (cannot-close-composite-expression {closing-char Char})
+  (ex.report ["Closing Character" (text.from-code closing-char)]))
+
 (def: (ast current-module aliases)
   (-> Text Aliases Syntax)
   (function (ast' where)
@@ -141,34 +184,6 @@
 (type: Parser
   (-> Source (Error [Source Code])))
 
-(do-template [  ]
-  [(template: ( value)
-     ( value ))]
-
-  [!inc   "lux i64 +" 1]
-  [!inc/2 "lux i64 +" 2]
-  [!dec   "lux i64 -" 1]
-  )
-
-(template: (!clip from to text)
-  ("lux text clip" text from to))
-
-(do-template [ ]
-  [(template: ( reference subject)
-     ( subject reference))]
-
-  [!n/= "lux i64 ="]
-  [!i/< "lux int <"]
-  )
-
-(do-template [ ]
-  [(template: ( param subject)
-     ( subject param))]
-
-  [!n/+ "lux i64 +"]
-  [!n/- "lux i64 -"]
-  )
-
 (template: (!with-char+ @source-code-size @source-code @offset @char @else @body)
   (if (!i/< (:coerce Int @source-code-size)
             (:coerce Int @offset))
@@ -179,33 +194,50 @@
 (template: (!with-char @source-code @offset @char @else @body)
   (!with-char+ ("lux text size" @source-code) @source-code @offset @char @else @body))
 
-(do-template [  ]
-  [(def: ( parse source)
-     (-> Parser Parser)
-     (let [[_ _ source-code] source
-           source-code//size ("lux text size" source-code)]
-       (loop [source source
-              stack (: (List Code) #.Nil)]
-         (case (parse source)
-           (#error.Success [source' top])
-           (recur source' (#.Cons top stack))
-           
-           (#error.Error error)
-           (let [[where offset _] source]
-             (<| (!with-char+ source-code//size source-code offset closing-char (#error.Error error))
-                 (if (`` (!n/= (char (~~ (static ))) closing-char))
-                   (#error.Success [[(update@ #.column inc where)
-                                     (!inc offset)
-                                     source-code]
+(def: close-signal "CLOSE")
+
+(def: (read-close closing-char source-code//size source-code offset)
+  (-> Char Nat Text Offset (Error Offset))
+  (loop [end offset]
+    (<| (!with-char+ source-code//size source-code end char (ex.throw cannot-close-composite-expression closing-char)
+          (if (!n/= closing-char char)
+            (#error.Success (!inc end))
+            (`` ("lux syntax char case!" char
+                 [[(~~ (static ..space))
+                   (~~ (static text.carriage-return))
+                   (~~ (static text.new-line))]
+                  (recur (!inc end))]
+
+                 ## else
+                 (ex.throw cannot-close-composite-expression closing-char))))))))
+
+(`` (do-template [   ]
+      [(def: ( parse source)
+         (-> Parser Parser)
+         (let [[_ _ source-code] source
+               source-code//size ("lux text size" source-code)]
+           (loop [source source
+                  stack (: (List Code) #.Nil)]
+             (case (parse source)
+               (#error.Success [source' top])
+               (recur source' (#.Cons top stack))
+               
+               (#error.Error error)
+               (let [[where offset _] source]
+                 (case (read-close (char ) source-code//size source-code offset)
+                   (#error.Success offset')
+                   (#error.Success [[(update@ #.column inc where) offset' source-code]
                                     [where ( (list.reverse stack))]])
-                   (ex.throw unrecognized-input where))))))))]
 
-  ## Form and tuple syntax is mostly the same, differing only in the
-  ## delimiters involved.
-  ## They may have an arbitrary number of arbitrary Code nodes as elements.
-  [parse-form  ..close-form  #.Form]
-  [parse-tuple ..close-tuple #.Tuple]
-  )
+                   (#error.Error error)
+                   (#error.Error error)))))))]
+
+      ## Form and tuple syntax is mostly the same, differing only in the
+      ## delimiters involved.
+      ## They may have an arbitrary number of arbitrary Code nodes as elements.
+      [parse-form  (~~ (static ..close-form))  #.Form  "Form"]
+      [parse-tuple (~~ (static ..close-tuple)) #.Tuple "Tuple"]
+      ))
 
 (def: (parse-record parse source)
   (-> Parser Parser)
@@ -220,17 +252,18 @@
           (recur sourceFV (#.Cons [field value] stack))
 
           (#error.Error error)
-          (let [[where offset _] source]
-            (<| (!with-char+ source-code//size source-code offset closing-char (#error.Error error))
-                (if (`` (!n/= (char (~~ (static ..close-record))) closing-char))
-                  (#error.Success [[(update@ #.column inc where)
-                                    (!inc offset)
-                                    source-code]
-                                   [where (#.Record (list.reverse stack))]])
-                  (ex.throw unrecognized-input where)))))
+          (#error.Error error))
 
         (#error.Error error)
-        (#error.Error error)))))
+        (let [[where offset _] source]
+          (<| (!with-char+ source-code//size source-code offset closing-char (#error.Error error))
+              (case (read-close (`` (char (~~ (static ..close-record)))) source-code//size source-code offset)
+                (#error.Success offset')
+                (#error.Success [[(update@ #.column inc where) offset' source-code]
+                                 [where (#.Record (list.reverse stack))]])
+
+                (#error.Error error)
+                (#error.Error error))))))))
 
 (template: (!guarantee-no-new-lines content body)
   (case ("lux text index" content (static text.new-line) 0)
@@ -252,7 +285,7 @@
                             (#.Text g!content)]])))
     
     _
-    (ex.throw unrecognized-input where)))
+    (ex.throw unrecognized-input [where "Text" source-code offset])))
 
 (def: digit-bottom Nat (!dec (char "0")))
 (def: digit-top Nat (!inc (char "9")))
@@ -352,22 +385,22 @@
     [where::file (!inc where::line) 0]))
 
 (with-expansions [ (ex.throw end-of-file current-module)
-                   (ex.throw unrecognized-input where)
+                   (ex.throw unrecognized-input [where "General" source-code offset/0])
+                   (#error.Error (`` (~~ (static close-signal))))
                    (as-is [where (!inc offset/0) source-code])
                    (as-is [where (!inc/2 offset/0) source-code])]
 
-  (template: (!parse-half-name @offset//pre @offset//post @char @module)
-    (let [@offset//post (!inc @offset//pre)]
-      (cond (!name-char?|head @char)
-            (case (..parse-name-part @offset//post [where @offset//post source-code])
-              (#error.Success [source' name])
-              (#error.Success [source' [@module name]])
-              
-              (#error.Error error)
-              (#error.Error error))
+  (template: (!parse-half-name @offset @char @module)
+    (cond (!name-char?|head @char)
+          (case (..parse-name-part @offset [where (!inc @offset) source-code])
+            (#error.Success [source' name])
+            (#error.Success [source' [@module name]])
+            
+            (#error.Error error)
+            (#error.Error error))
 
-            ## else
-            )))
+          ## else
+          ))
 
   (`` (def: (parse-short-name current-module [where offset/0 source-code])
         (-> Text Source (Error [Source Name]))
@@ -375,8 +408,8 @@
             (if (!n/= (char (~~ (static ..name-separator))) char/0)
               (let [offset/1 (!inc offset/0)]
                 (<| (!with-char source-code offset/1 char/1 )
-                    (!parse-half-name offset/1 offset/2 char/1 current-module)))
-              (!parse-half-name offset/0 offset/1 char/0 ..prelude)))))
+                    (!parse-half-name offset/1 char/1 current-module)))
+              (!parse-half-name offset/0 char/0 ..prelude)))))
 
   (template: (!parse-short-name @current-module @source @where @tag)
     (case (..parse-short-name @current-module @source)
@@ -484,7 +517,7 @@
                                 )
 
                               [(~~ (static ..name-separator))]
-                              (!parse-short-name current-module  where #.Identifier)]
+                              (!parse-short-name current-module  where #.Tag)]
 
                              ## else
                              (cond (!name-char?|head char/1) ## Tag
@@ -499,7 +532,7 @@
                             (if (!digit? char/1)
                               (let [offset/2 (!inc offset/1)]
                                 (!parse-rev source-code//size offset/0 where offset/2 source-code))
-                              (!parse-short-name current-module  where #.Identifier))))
+                              (!parse-short-name current-module [where offset/1 source-code] where #.Identifier))))
 
                       [(~~ (static ..positive-sign))
                        (~~ (static ..negative-sign))]
@@ -507,7 +540,7 @@
 
                       ## Invalid characters at this point...
                       (~~ (<>))
-                      ]
+                      ]
 
                      ## else
                      (if (!digit? char/0)
-- 
cgit v1.2.3


From b614f2875fb2e98e8867399b7013503f2b1a4e4c Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Sun, 26 Aug 2018 09:12:46 -0400
Subject: Added Frac parsing.

---
 .../default/phase/extension/analysis/common.lux    |   2 +-
 stdlib/source/lux/compiler/default/syntax.lux      | 104 ++++++++++++++-------
 2 files changed, 71 insertions(+), 35 deletions(-)

(limited to 'stdlib')

diff --git a/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux b/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux
index c654d9a00..d599af130 100644
--- a/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux
+++ b/stdlib/source/lux/compiler/default/phase/extension/analysis/common.lux
@@ -201,7 +201,7 @@
           (bundle.install "concat" (binary Text Text Text))
           (bundle.install "index" (trinary Text Text Nat (type (Maybe Nat))))
           (bundle.install "size" (unary Text Nat))
-          (bundle.install "char" (binary Text Nat (type (Maybe Nat))))
+          (bundle.install "char" (binary Text Nat Nat))
           (bundle.install "clip" (trinary Text Nat Nat Text))
           )))
 
diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux
index 8cb41536e..52ac38720 100644
--- a/stdlib/source/lux/compiler/default/syntax.lux
+++ b/stdlib/source/lux/compiler/default/syntax.lux
@@ -40,6 +40,18 @@
      ["." list]
      ["." dictionary (#+ Dictionary)]]]])
 
+## TODO: Optimize how forms, tuples & records are parsed in the end.
+## There is repeated-work going on when parsing the white-space before the
+## closing parenthesis/bracket/brace.
+## That repeated-work should be avoided.
+
+## TODO: Implement "lux syntax char case!" as a custom extension.
+## That way, it should be possible to obtain the char without wrapping
+## it into a java.lang.Long, thereby improving performance.
+
+## TODO: Make an extension to take advantage of java/lang/String::indexOf
+## to get better performance than the current "lux text index" extension.
+
 (type: Char Nat)
 
 (do-template [  ]
@@ -70,15 +82,6 @@
   [!n/- "lux i64 -"]
   )
 
-## TODO: Optimize how forms, tuples & records are parsed in the end.
-## There is repeated-work going on when parsing the space before the
-## closing parenthesis/bracket/brace.
-## That repeated-work should be avoided.
-
-## TODO: Implement "lux syntax char case!" as a custom extension.
-## That way, it should be possible to obtain the char without wrapping
-## it into a java.lang.Long, thereby improving performance.
-
 (type: #export Syntax
   (-> Cursor (Lexer [Cursor Code])))
 
@@ -107,6 +110,17 @@
 (def: #export positive-sign "+")
 (def: #export negative-sign "-")
 
+(def: #export frac-separator ".")
+
+## The parts of an name are separated by a single mark.
+## E.g. module.short.
+## Only one such mark may be used in an name, since there
+## can only be 2 parts to an name (the module [before the
+## mark], and the short [after the mark]).
+## There are also some extra rules regarding name syntax,
+## encoded on the parser.
+(def: #export name-separator ".")
+
 ## These are very simple parsers that just cut chunks of text in
 ## specific shapes and then use decoders already present in the
 ## standard library to actually produce the values from the literals.
@@ -143,15 +157,6 @@
       (wrap [(update@ #.column (n/+ (text.size chunk)) where)
              [where (#.Frac value)]]))))
 
-## The parts of an name are separated by a single mark.
-## E.g. module.short.
-## Only one such mark may be used in an name, since there
-## can only be 2 parts to an name (the module [before the
-## mark], and the short [after the mark]).
-## There are also some extra rules regarding name syntax,
-## encoded on the parser.
-(def: name-separator ".")
-
 (exception: #export (end-of-file {module Text})
   (ex.report ["Module" (%t module)]))
 
@@ -324,7 +329,7 @@
   (or (!strict-name-char? char)
       (!digit? char)))
 
-(template: (!discrete-output    )
+(template: (!number-output    )
   (case (::  decode (!clip   source-code))
     (#error.Success output)
     (#error.Success [[(update@ #.column (n/+ (!n/-  )) where)
@@ -335,26 +340,56 @@
     (#error.Error error)
     (#error.Error error)))
 
-(do-template [  ]
-  [(def: ( start [where offset source-code])
-     (-> Offset Parser)
-     (let [source-code//size ("lux text size" source-code)]
-       (loop [end offset]
-         (<| (!with-char+ source-code//size source-code end char (!discrete-output start end  ))
-             (if (!digit?+ char)
-               (recur (!inc end))
-               (!discrete-output start end  ))))))]
-
-  [parse-int number.Codec #.Int]
-  )
+(def: no-exponent Offset 0)
+
+(with-expansions [ (as-is (!number-output start end number.Codec #.Int))
+                   (as-is (!number-output start end number.Codec #.Frac))
+                   (ex.throw unrecognized-input [where "Frac" source-code offset])]
+  (def: (parse-frac source-code//size start [where offset source-code])
+    (-> Nat Offset Parser)
+    (loop [end offset
+           exponent ..no-exponent]
+      (<| (!with-char+ source-code//size source-code end char/0 )
+          (cond (!digit?+ char/0)
+                (recur (!inc end) exponent)
+
+                (and (or (!n/= (char "e") char/0)
+                         (!n/= (char "E") char/0))
+                     (not (is? ..no-exponent exponent)))
+                (<| (!with-char+ source-code//size source-code (!inc end) char/1 )
+                    (if (or (!n/= (`` (char (~~ (static ..positive-sign)))) char/1)
+                            (!n/= (`` (char (~~ (static ..negative-sign)))) char/1))
+                      (<| (!with-char+ source-code//size source-code (!n/+ 2 end) char/2 )
+                          (if (!digit?+ char/2)
+                            (recur (!n/+ 3 end) char/0)
+                            ))
+                      ))
+
+                ## else
+                ))))
+
+  (def: (parse-signed start [where offset source-code])
+    (-> Offset Parser)
+    (let [source-code//size ("lux text size" source-code)]
+      (loop [end offset]
+        (<| (!with-char+ source-code//size source-code end char )
+            (cond (!digit?+ char)
+                  (recur (!inc end))
+
+                  (!n/= (`` (.char (~~ (static ..frac-separator))))
+                        char)
+                  (parse-frac source-code//size start [where (!inc end) source-code])
+
+                  ## else
+                  ))))))
 
 (do-template [  ]
   [(template: ( source-code//size start where offset source-code)
      (loop [g!end offset]
-       (<| (!with-char+ source-code//size source-code g!end g!char (!discrete-output start g!end  ))
+       (<| (!with-char+ source-code//size source-code g!end g!char (!number-output start g!end  ))
            (if (!digit?+ g!char)
              (recur (!inc g!end))
-             (!discrete-output start g!end  )))))]
+             (!number-output start g!end  )))))]
 
   [!parse-nat number.Codec #.Nat]
   [!parse-rev number.Codec #.Rev]
@@ -364,7 +399,7 @@
   (let [g!offset/1 (!inc offset)]
     (<| (!with-char+ source-code//size source-code g!offset/1 g!char/1 @end)
         (if (!digit? g!char/1)
-          (parse-int offset [where (!inc/2 offset) source-code])
+          (parse-signed offset [where (!inc/2 offset) source-code])
           (!parse-full-name offset [where (!inc offset) source-code] where #.Identifier)))))
 
 (with-expansions [ (#error.Success [[(update@ #.column (n/+ (!n/- start end)) where)
@@ -526,6 +561,7 @@
                                    ## else
                                    ))))
 
+                      ## Coincidentally (= name-separator frac-separator)
                       [(~~ (static ..name-separator))]
                       (let [offset/1 (!inc offset/0)]
                         (<| (!with-char+ source-code//size source-code offset/1 char/1 )
-- 
cgit v1.2.3