Imports
/-
Copyright (c) 2026 Terence Rokop. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Terence Rokop
-/
module
public import Geb.Prototypes.CanonicalSExprset_option doc.verso trueFile I/O for canonical S-expressions
The file operations wrap the parsers and printers of
Geb.Csexp.parse and Geb.Rose.parse. A read returns none for a
syntax error or a label outside Fin k; filesystem errors remain
IO.Error exceptions. The parsers retain their existing acceptance
rules, including their treatment of leading zeros and trailing input.
Main definitions
-
Geb.Csexp.readFile,Geb.Csexp.writeFile: the tagged binary encoding. -
Geb.Rose.readFile,Geb.Rose.writeFile: the canonical rose encoding. -
Geb.CSexp.writeFile: render an ASCII canonical expression.
Implementation notes
IO.FS.readBinFile supplies bytes, each mapped to the character with
that value. Both tree encodings use ASCII, so no Unicode decoding is needed.
IO.FS.writeFile writes the ASCII rendering without a trailing newline,
creating or truncating the destination. Reads hold the complete file in memory.
Compose a canonical rose read with Option.map Geb.Ast.ofRose
to obtain a binary tree, or pass Geb.Ast.toRose to the rose writer.
Tags
canonical S-expression, file I/O, binary tree, rose tree
public sectionnamespace Geb.CsexpRead a tagged canonical binary tree, requiring the parser to consume the whole file.
def readFile (k : Nat) (path : System.FilePath) : IO (Option (Ast k)) := do
return parse k ((← IO.FS.readBinFile path).data.toList.map fun b ↦ Char.ofNat b.toNat)Write a binary tree in the tagged canonical encoding, without a trailing newline.
def writeFile {k : Nat} (path : System.FilePath) (a : Ast k) : IO Unit :=
IO.FS.writeFile path (String.ofList (print a))end Geb.Csexpnamespace Geb.CSexp
Write an ASCII expression. Reject non-ASCII characters before opening the output,
since render counts characters rather than UTF-8 bytes.
def writeFile (path : System.FilePath) (s : CSexp) : IO Unit := do
let cs := render s
unless cs.all (fun c ↦ c.toNat < 128) do
throw <| IO.userError "canonical S-expression output requires ASCII atoms"
IO.FS.writeFile path (String.ofList cs)end Geb.CSexpnamespace Geb.Rose
Read a canonical rose expression, leaving conversion by Ast.ofRose to the caller.
def readFile (k : Nat) (path : System.FilePath) : IO (Option (Rose k)) := do
return parse k ((← IO.FS.readBinFile path).data.toList.map fun b ↦ Char.ofNat b.toNat)Write a canonical rose expression, without a trailing newline.
def writeFile {k : Nat} (path : System.FilePath) (r : Rose k) : IO Unit :=
IO.FS.writeFile path (String.ofList (print r))end Geb.Rose