load "misc.quox" load "maybe.quox" load "list.quox" namespace io { def0 IORes : ★ → ★ = λ A ⇒ A × IOState def0 IO : ★ → ★ = λ A ⇒ IOState → IORes A def pure : 0.(A : ★) → A → IO A = λ A x s ⇒ (x, s) def bind : 0.(A B : ★) → IO A → (A → IO B) → IO B = λ A B m k s0 ⇒ case m s0 return IORes B of { (x, s1) ⇒ k x s1 } def bindω : 0.(A B : ★) → IO [ω.A] → (ω.A → IO B) → IO B = λ A B m k s0 ⇒ case m s0 return IORes B of { (x, s1) ⇒ case x return IORes B of { [x] ⇒ k x s1 } } def map : 0.(A B : ★) → (A → B) → IO A → IO B = λ A B f m ⇒ bind A B m (λ x ⇒ pure B (f x)) def mapω : 0.(A B : ★) → (ω.A → B) → IO [ω.A] → IO B = λ A B f m ⇒ bindω A B m (λ x ⇒ pure B (f x)) def seq : 0.(B : ★) → IO True → IO B → IO B = λ B x y ⇒ bind True B x (λ u ⇒ case u return IO B of { 'true ⇒ y }) def seq' : IO True → IO True → IO True = seq True def pass : IO True = pure True 'true #[compile-scheme "(lambda (str) (builtin-io (display str) 'true))"] postulate print : String → IO True #[compile-scheme "(lambda (str) (builtin-io (write str) (newline) 'true))"] postulate dump : 0.(A : ★) → A → IO True def newline = print "\n" def println : String → IO True = λ str ⇒ seq' (print str) newline #[compile-scheme "(builtin-io (get-line (current-input-port)))"] postulate readln : IO String -- [todo] errors lmao {- postulate0 File : ★ #[compile-scheme "(lambda (path) (builtin-io (open-input-file path)))"] postulate open-read : String → IO File #[compile-scheme "(lambda (file) (builtin-io (close-port file) 'true))"] postulate close : File → IO True #[compile-scheme "(lambda% (file if-eof if-line) (builtin-io (let ([result (get-line file)]) (if (eof-object? result) (cons if-eof file) (cons (if-line result) file)))))"] postulate prim-read-line : File → ω.(if-eof : Maybe [ω.String]) → ω.(if-line : ω.String → Maybe [ω.String]) → IO (Maybe [ω.String] × File) def read-line : File → IO (Maybe [ω.String] × File) = λ f ⇒ prim-read-line f (Nothing [ω.String]) (λ x ⇒ Just [ω.String] [x]) -} #[compile-scheme "(lambda (path) (builtin-io (call-with-input-file path get-string-all)))"] postulate read-fileω : ω.(path : String) → IO [ω.String] def read-file : ω.(path : String) → IO String = λ path ⇒ map [ω.String] String (getω String) (read-fileω path) #[compile-scheme "(lambda (path) (builtin-io (call-with-input-file path (lambda (file) (do [(line (get-line file) (get-line file)) (acc '() (cons line acc))] [(eof-object? line) (reverse acc)])))))"] postulate read-file-lines : ω.(path : String) → IO (List String) } def0 IO = io.IO