diff options
author | Vladimir Azarov <avm@intermediate-node.net> | 2025-05-19 23:43:59 +0200 |
---|---|---|
committer | Vladimir Azarov <avm@intermediate-node.net> | 2025-05-19 23:43:59 +0200 |
commit | 82701db07a6f9ae3ec79defbcf46e3de9346c766 (patch) | |
tree | 9fab427369799e891e8d15bc44810be27ec698c0 /common.sml | |
parent | b2d8dcd8673cfcdbf1e8a02aa19c53e42b8a60b6 (diff) |
printf F
Diffstat (limited to 'common.sml')
-rw-r--r-- | common.sml | 67 |
1 files changed, 43 insertions, 24 deletions
@@ -107,50 +107,69 @@ fun exit code = ( fun output stream s = TextIO.output (stream, s) -fun fprint stream g = Fold.fold ((false, output stream), fn _ => ()) g -fun printf g = fprint TextIO.stdOut g -fun sprintf g = +fun makePrintfBase output = let - val buf = ref [] - fun output s = (buf := s :: (!buf)) - fun finish _ = String.concat (rev (!buf)) + val firstOnLine = ref true + fun endsWithNL "" = raise Unreachable + | endsWithNL s = String.sub (s, size s - 1) = #"\n" + + fun output' "" = () + | output' s = ( + output s; + firstOnLine := endsWithNL s + ) + fun mf () = + if not $ !firstOnLine then + (output "\n"; firstOnLine := true) + else + () in - Fold.fold ((false, output), finish) -end g -fun Printf output g = Fold.fold ((false, output), fn _ => ()) g + (output', mf) +end + +local + val ctx = ((false, makePrintfBase $ output TextIO.stdOut), + fn (_: bool * ((string -> unit) * (unit -> unit))) => ()) +in + fun printf g = Fold.fold ctx g +end + +fun Printf out g = Fold.fold ((false, out), fn _ => ()) g local fun ifF flag cl = if not flag then cl () else () in - fun ` z = Fold.step1 (fn (s, (ign, output)) => - (ifF ign (fn () => output s); (ign, output))) z - - fun A0 z = Fold.step1 (fn (f, (ign, output)) => - (ifF ign (fn () => f output); (ign, output))) z - fun A1 z = Fold.step2 (fn (f, v, (ign, output)) => - (ifF ign (fn () => f (output, v)); (ign, output))) z - fun A2 z = Fold.step3 (fn (f, v1, v2, (ign, output)) => - (ifF ign (fn () => f (output, v1, v2)); (ign, output))) z + fun ` z = Fold.step1 (fn (s, (ign, out as (output, _))) => + (ifF ign (fn () => output s); (ign, out))) z + + fun A0 z = Fold.step1 (fn (f, (ign, out)) => + (ifF ign (fn () => f out); (ign, out))) z + fun A1 z = Fold.step2 (fn (f, v, (ign, out)) => + (ifF ign (fn () => f (out, v)); (ign, out))) z + fun A2 z = Fold.step3 (fn (f, v1, v2, (ign, out)) => + (ifF ign (fn () => f (out, v1, v2)); (ign, out))) z end -fun Ign z = Fold.step0 (fn (_, output) => (true, output)) z +fun Ign z = Fold.step0 (fn (_, out) => (true, out)) z fun bind A f = fn z => Fold.fold z A f -fun bindWith2str to = bind A1 (fn (output, v) => output (to v)) +fun bindWith2str to = bind A1 (fn ((output, _), v) => output $ to v) + +fun F z = bind A0 (fn (_, mf) => mf ()) z val I = fn z => bindWith2str Int.toString z val C = fn z => bindWith2str str z val B = fn z => bindWith2str Bool.toString z -val R = fn z => bind A1 (fn (output, n) => app (fn f => f ()) +val R = fn z => bind A1 (fn ((output, _), n) => app (fn f => f ()) (List.tabulate (n, fn _ => fn () => output "\t"))) z -type ('t, 'a, 'b) a1printer = (bool * (string -> unit)) * 'a -> 't -> - ((bool * (string -> unit)) * 'a -> 'b) -> 'b +type ('t, 'a, 'b, 'c) a1printer = (bool * ((string -> unit) * 'a)) * 'b + -> 't -> ((bool * ((string -> unit) * 'a)) * 'b -> 'c) -> 'c fun die code g = let fun finish (true, _) = raise Unreachable - | finish (false, output) = ( + | finish (false, (output, _)) = ( output "\n"; exit code ) |