# Part of http://akkartik.name/coroutines-in-mu # # Version 3a: coroutines set up by decompressor # # To run: # $ git clone https://github.com/akkartik/mu1 # $ cd mu1 # $ git checkout 4a48bedcd1 # state as of this writing; later versions may be incompatible # $ wget http://akkartik.name/coroutines-in-mu/version3a.mu # $ ./mu version3a.mu exclusive-container token [ word:text punc:char ] def decompressor src:&:source:num, dest:&:sink:token -> src:&:source:num, dest:&:sink:token [ local-scope load-inputs emit:continuation <- call-with-continuation-mark parser, dest { x:num, eof?:bool <- read src break-if eof? c:char <- copy x $print [decompress: ] c 10/newline repeat-tag?:bool <- equal c, 255 { break-unless repeat-tag? len:num <- read src x:num <- read src c:char <- copy x $print [run: ] c [*] len 10/newline i:num <- copy 0 { done?:bool <- equal i, len break-if done? emit <- call emit, c i <- add i, 1 loop } } { break-if repeat-tag? emit <- call emit, c } loop } call emit, 4/EOF ] def parser dest:&:sink:token -> dest:&:sink:token [ local-scope load-inputs { c:char <- getchar eof?:bool <- equal c, 4/EOF break-if eof? { alpha?:bool <- isalpha c break-unless alpha? buf:&:buffer:char <- new-buffer 5 { buf <- append buf, c c <- getchar eof?:bool <- equal c, 4/EOF break-if eof? alpha?:bool <- isalpha c loop-if alpha? } word:text <- buffer-to-array buf out:token <- merge 0/word, word dest <- write dest, out break-if eof?, +end } out:token <- merge 1/punc, c dest <- write dest, out loop } +end close dest ] def getchar -> c:char [ local-scope load-inputs c <- return-continuation-until-mark ] def isalpha c:char -> result:bool [ local-scope load-inputs # 'a' <= c <= 'z' || 'A' <= c <= 'Z' b1:bool <- greater-or-equal c, 65/A b2:bool <- lesser-or-equal c, 90/Z uppercase?:bool <- and b1, b2 return-if uppercase?, 1/true b1 <- greater-or-equal c, 97/a b2 <- lesser-or-equal c, 122/z lowercase?:bool <- and b1, b2 return lowercase? ] # test def main [ local-scope # Make channel capacities large enough to never block; we don't use # concurrency in this example. number-source:&:source:num, in:&:sink:num <- new-channel 30 out:&:source:token, token-sink:&:sink:token <- new-channel 30 # set up input ["aaaabbb,,cccdd;e"] write in, 255 write in, 4/len write in, 97/a write in, 255 write in, 3/len write in, 98/b write in, 255 write in, 2/len write in, 44/comma write in, 255 write in, 3/len write in, 99/c write in, 255 write in, 2/len write in, 100/d write in, 59/semi-colon write in, 101/e close in # run decompressor number-source, token-sink # read out result { t:token, done?:bool <- read out break-if done? { w:text, match?:bool <- maybe-convert t, word:variant break-unless match? $print [word: ] *w 10/newline } { p:char, match?:bool <- maybe-convert t, punc:variant break-unless match? $print [punc: ] p 10/newline } loop } # Expected output: # word: 7 97 97 97 97 98 98 98 ("aaaabbb") # punc: 44 (',') # punc: 44 (',') # word: 5 99 99 99 100 100 ("cccdd") # punc: 59 (';') # word: 1 101 ("e") ]