tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

consumer_text_lines.tri (3246B)


      1 -- Practical filter use case: split text once, then discard blank and
      2 -- #-prefixed lines. Differentially check source-authored lexical workers.
      3 !import "consumers.base-source" B
      4 !import "consumers.structural" S
      5 !import "consumers.lexical-worker" L
      6 !import "prelude" !Local
      7 !import "io" !Local
      8 
      9 load path = do onOk_
     10   source <- readFile path
     11   pure (matchResult (_ _ : err "consumer source did not parse" t)
     12     (named _ : ok (snd named) t) (B.compileBaseSource source))
     13 base name = append "lib/consumer/" (append name ".scp")
     14 worker program state = S.makeConsumer state (snd program)
     15 reference splitter compact bytes = (bindResult (S.runConsumer splitter bytes)
     16   (lines _ : S.runConsumer compact lines))
     17 lexical splitter compact bytes = (bindResult (L.lRunChecked splitter bytes)
     18   (lines _ : L.lRunChecked compact lines))
     19 badPredicate = snd (resultOr t (B.compileBaseSource
     20   "consumer invalidPredicate\n  line @ _ => (leaf, leaf)"))
     21 checks splitter reverser folder prepend predicate filtering sample =
     22   let refPrepend = worker prepend t in
     23   let lexPrepend = resultOr t (L.lCompile refPrepend) in
     24   let refFold = worker folder t in
     25   let lexFold = resultOr t (L.lCompile refFold) in
     26   let refReverse = worker reverser (pair refFold refPrepend) in
     27   let lexReverse = resultOr t (L.lCompile
     28     (worker reverser (pair lexFold lexPrepend))) in
     29   let refSplit = worker splitter (pair [] refReverse) in
     30   let lexSplit = resultOr t (L.lCompile
     31     (worker splitter (pair [] lexReverse))) in
     32   let refPredicate = worker predicate t in
     33   let lexPredicate = resultOr t (L.lCompile refPredicate) in
     34   let refFilter = worker filtering refPredicate in
     35   let lexFilter = resultOr t (L.lCompile
     36     (worker filtering lexPredicate)) in
     37   let refBad = worker filtering badPredicate in
     38   let lexBad = resultOr t (L.lCompile
     39     (worker filtering (resultOr t (L.lCompile badPredicate)))) in
     40   let same text expected = (and?
     41     (equal? (reference refSplit refFilter text) (ok expected t))
     42     (equal? (lexical lexSplit lexFilter text) (ok expected t))) in
     43   foldl and? true [
     44     (resultIsOk (L.lCompile refPredicate))
     45     (resultIsOk (L.lCompile (worker filtering lexPredicate)))
     46     (equal? (S.runConsumer refBad ["alpha"])
     47       (err "no matching output arm" t))
     48     (equal? (L.lRunChecked lexBad ["alpha"])
     49       (err "no matching output arm" t))
     50     (resultIsOk (L.lCompile (worker splitter (pair [] lexReverse))))
     51     (same sample ["alpha" "beta"])
     52     (same "" [])
     53     (same "\n" [])
     54     (same "a\n\n" ["a"])
     55     (same "#note\nonly\n" ["only"])
     56     (same "#note\r\nvalue\r\n" ["value\r"])
     57     (same "  #not-a-comment\n" ["  #not-a-comment"])]
     58 stage = do onOk_
     59   splitter <- load "lib/consumer/text/splitLines.scp"
     60   reverser <- load (base "reverse")
     61   folder <- load (base "fold")
     62   prepend <- load (base "prepend")
     63   predicate <- load "demos/consumers/data-lines/data-line.scp"
     64   filtering <- load (base "filter")
     65   sample <- readFile "demos/consumers/data-lines/data-lines-input.txt"
     66   pure (ok (checks splitter reverser folder prepend predicate filtering sample) t)
     67 main = io (onResult_ stage
     68   (_ : putStrLn "consumer-text-lines-LOAD-FAIL")
     69   (success : putStrLn (matchBool "consumer-text-lines-ok"
     70     "consumer-text-lines-DIFFER" success)))
     71 main