Something went wrong. Try again.
The Monad language. Dependent types, functional programming compiled with LLVM. Hobby project.
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394// OS-specific I/O: console output and the filesystem. The `IO` type// itself lives in init/io.mo (pure, portable); everything here is a// genuine side effect, hence std/. See AGENTS.md's "init vs std"// section.// Qualified (not bare `use path {...}`) deliberately: the Rust// reference's module loader registers std/*.mo siblings under their// full `std.<name>` path (to avoid colliding with init/io.mo's own// bare `io`), and has no base-dir-relative fallback the way the// self-hosted loader does -- a bare `use path {...}` here resolves// fine self-hosted but fails "module not found: path" under `cargo// run`. Qualified works identically on both sides.use lib::path {Path}#[native print_str]pub def IO.println (s: String) : IO Unit#[native "write_file"]def IO.write_file_native (path : String) (content : String) : IO Unit// TODO Return Option and none on failure#[native "read_file"]def IO.read_file_native (path : String) : IO String#[native "file_exists"]def IO.file_exists_native (path : String) : IO Bool#[native "is_dir"]def IO.is_dir_native (path : String) : IO Bool// Bare entry names (not full paths), sorted, one directory level.#[native "list_dir"]def IO.list_dir_native (path : String) : IO (List String)#[native "get_env"]def IO.get_env (s : String) : IO (Option String)// Milliseconds since the Unix epoch, from the system WALL clock// (`SystemTime::now`, core/src/core_native.rs). Use it for differences// between two readings; because it is the wall clock and not a// monotonic one, a clock adjustment (NTP, a manual set, a suspend) can// make a later reading SMALLER than an earlier one, so a computed// interval can come out negative -- callers that render a duration// must handle that (`fmt_dur_ns`, lang/codegen/test_driver.mo, clamps// it to zero).//// TODO: back this with a genuinely monotonic source// (`Instant`/`CLOCK_MONOTONIC`), which is what an interval timer// actually wants; the epoch-based reading would then move to a// separate `IO.current_time_epoch` for the callers that want a real// timestamp. Documented as the wall clock rather than quietly changed// because the two natives must agree across BOTH runtimes at once.//// `IO` because reading a clock is a side effect in the same sense// reading a file is: two calls in one expression may legitimately differ,// so it must not be something the evaluator can duplicate, reorder or// share. `std/bench.mo`'s `Bench.now` is the name callers use.#[native current_time]def IO.current_time : IO I64// Nanoseconds since the Unix epoch, from the same system WALL clock as// `IO.current_time` above -- same caveats (a backwards clock step can// make an interval negative), just finer.//// Exists because per-test timing needs sub-millisecond resolution: the// self-hosted test runner reports each test's duration the way the Rust// runner's `format_duration` does (`core/src/lib.rs`), and most tests// finish well inside one millisecond, where `current_time` can only// ever say "0ms". The native hands over RAW NANOSECONDS and nothing// else -- every unit conversion and all the ns/us/ms/s formatting is// done in Monad, by the driver this runner synthesizes// (`lang/codegen/test_driver.mo`).#[native current_time_nano]def IO.current_time_nano : IO I64def IO.write_file (path : Path) (content : String) : IO Unit := IO.write_file_native (Path.to_string path) contentpub def IO.read_file (path : Path) : IO String := IO.read_file_native (Path.to_string path)pub def IO.file_exists (path : Path) : IO Bool := IO.file_exists_native (Path.to_string path)pub def IO.is_dir (path : Path) : IO Bool := IO.is_dir_native (Path.to_string path)pub def IO.list_dir (path : Path) : IO (List String) := IO.list_dir_native (Path.to_string path)// TODO support constraints// def IO.fprintln [ToString A] (a: A) : IO Unit :=// IO.println (ToString.to_string a)