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