diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-08-18 21:09:27 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-08-18 21:09:27 -0700 |
commit | a621ef95f4728d15bdf0b1828ac7dd6ac5af2795 (patch) | |
tree | 55e215014e53dfd5327dbd6eefb8d072b5b08a08 | |
parent | 47219d0b2b41096547a02b506d7413fe9a3d308a (diff) | |
download | mu-a621ef95f4728d15bdf0b1828ac7dd6ac5af2795.tar.gz |
3225 - testable interface for writing files
For example usage of file operations, see filesystem.mu. Is it ugly that we don't actually write to disk unless we wait for the writing routine to exit? Maybe there's a nice way to wrap it. At any rate, all buffering is explicit, which seems a win compared to *nix.
-rw-r--r-- | 075channel.mu | 1 | ||||
-rw-r--r-- | 087file.cc | 4 | ||||
-rw-r--r-- | 088file.mu | 27 | ||||
-rw-r--r-- | filesystem.mu | 24 |
4 files changed, 41 insertions, 15 deletions
diff --git a/075channel.mu b/075channel.mu index d47410da..1ee716a2 100644 --- a/075channel.mu +++ b/075channel.mu @@ -302,7 +302,6 @@ after <channel-write-initial> [ closed?:boolean <- get *chan, closed?:offset return-if closed? ] - after <channel-read-empty> [ closed?:boolean <- get *chan, closed?:offset { diff --git a/087file.cc b/087file.cc index 6109fe26..ebb90689 100644 --- a/087file.cc +++ b/087file.cc @@ -125,8 +125,8 @@ case _WRITE_TO_FILE: { raise << maybe(get(Recipe, r).name) << "first ingredient of '$write-to-file' should be a number, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); break; } - if (!is_mu_number(inst.ingredients.at(1))) { - raise << maybe(get(Recipe, r).name) << "second ingredient of '$write-to-file' should be a number, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); + if (!is_mu_character(inst.ingredients.at(1))) { + raise << maybe(get(Recipe, r).name) << "second ingredient of '$write-to-file' should be a character, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); break; } break; diff --git a/088file.mu b/088file.mu index 6e6a89e1..b26ae438 100644 --- a/088file.mu +++ b/088file.mu @@ -8,12 +8,12 @@ container filesystem [ def start-reading fs:address:filesystem, filename:address:array:character -> contents:address:source:character [ local-scope load-ingredients - x:number/file <- $open-file-for-reading filename + file:number <- $open-file-for-reading filename contents:address:source:character, sink:address:sink:character <- new-channel 30 - start-running transmit x, sink + start-running transmit-from-file file, sink ] -def transmit file:number, sink:address:sink:character -> file:number, sink:address:sink:character [ +def transmit-from-file file:number, sink:address:sink:character -> file:number, sink:address:sink:character [ local-scope load-ingredients { @@ -23,4 +23,25 @@ def transmit file:number, sink:address:sink:character -> file:number, sink:addre loop } sink <- close sink + $close-file file +] + +def start-writing fs:address:filesystem, filename:address:array:character -> sink:address:sink:character, routine-id:number [ + local-scope + load-ingredients + file:number <- $open-file-for-writing filename + source:address:source:character, sink:address:sink:character <- new-channel 30 + routine-id <- start-running transmit-to-file file, source +] + +def transmit-to-file file:number, source:address:source:character -> file:number, source:address:source:character [ + local-scope + load-ingredients + { + c:character, done?:boolean, source <- read source + break-if done? + $write-to-file file, c + loop + } + $close-file file ] diff --git a/filesystem.mu b/filesystem.mu index 274397be..3e6c45f7 100644 --- a/filesystem.mu +++ b/filesystem.mu @@ -1,16 +1,22 @@ +# example program: copy one file into another, character by character +# BEWARE: this will modify your file system +# before running it, put some text into /tmp/mu-x +# after running it, check /tmp/mu-y + def main [ local-scope - $print [reading characters from /tmp/mu-fs], 10/newline - # initialize filesystem - fs:address:filesystem <- copy 0/real-filesystem - content-source:address:source:character <- start-reading fs, [/tmp/mu-fs] - # read from channel until exhausted and print out characters + source-file:address:source:character <- start-reading 0/real-filesystem, [/tmp/mu-x] + sink-file:address:sink:character, write-routine:number <- start-writing 0/real-filesystem, [/tmp/mu-y] { - c:character, done?:boolean, content-source <- read content-source + c:character, done?:boolean, source-file <- read source-file break-if done? - $print [ ], c, 10/newline + eof?:boolean <- equal c, -1 + break-if eof? + sink-file <- write sink-file, c loop } - $print [done reading], 10/newline - # TODO: writing to file + close sink-file + # make sure to wait for the file to be actually written to disk + # (Mu practices structured concurrency: http://250bpm.com/blog:71) + wait-for-routine write-routine ] |