diff --git a/mers/Cargo.toml b/mers/Cargo.toml index 2653b8d..e0de380 100644 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers" -version = "0.9.19" +version = "0.9.20" edition = "2021" license = "MIT OR Apache-2.0" description = "dynamically typed but type-checked programming language" @@ -15,7 +15,7 @@ default = ["colored-output"] colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"] [dependencies] -mers_lib = "0.9.19" +mers_lib = "0.9.20" # mers_lib = { path = "../mers_lib" } clap = { version = "4.3.19", features = ["derive"] } colored = { version = "2.1.0", optional = true } diff --git a/mers_lib/Cargo.toml b/mers_lib/Cargo.toml index 2f16e29..9f8040f 100755 --- a/mers_lib/Cargo.toml +++ b/mers_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers_lib" -version = "0.9.19" +version = "0.9.20" edition = "2021" license = "MIT OR Apache-2.0" description = "library to use the mers language in other projects" diff --git a/mers_lib/src/program/configs/mod.rs b/mers_lib/src/program/configs/mod.rs index b5b225c..7f52878 100755 --- a/mers_lib/src/program/configs/mod.rs +++ b/mers_lib/src/program/configs/mod.rs @@ -15,6 +15,7 @@ pub mod gen; pub mod util; pub mod with_base; pub mod with_command_running; +pub mod with_fs; pub mod with_get; pub mod with_iters; pub mod with_list; @@ -41,8 +42,10 @@ impl Config { /// - `with_stdio()` /// - `with_command_running()` /// - `with_multithreading()` + /// - `with_fs()` pub fn bundle_std(self) -> Self { - self.with_multithreading() + self.with_fs() + .with_multithreading() .with_command_running() .with_stdio() .bundle_pure() diff --git a/mers_lib/src/program/configs/with_fs.rs b/mers_lib/src/program/configs/with_fs.rs new file mode 100644 index 0000000..14443d0 --- /dev/null +++ b/mers_lib/src/program/configs/with_fs.rs @@ -0,0 +1,99 @@ +use std::sync::Arc; + +use crate::data::{ + self, + function::Function, + object::{Object, ObjectFieldsMap, ObjectT}, + string::StringT, + tuple::{Tuple, TupleT}, + Data, Type, +}; + +use super::Config; + +impl Config { + pub fn with_fs(self) -> Self { + self.add_var( + "fs_read_text", + Function::new_generic( + |a, i| { + if a.is_included_in_single(&StringT) { + Ok(Type::newm(vec![ + Arc::new(StringT), + Arc::new(ObjectT::new(vec![( + i.global.object_fields.get_or_add_field("fs_read_error"), + Type::new(data::string::StringT), + )])), + ])) + } else { + Err(format!( + "Called fs_read_text with argument type {}, but expected String", + a.with_info(i) + ))? + } + }, + |a, i| { + let a = a.get(); + let a = a + .as_any() + .downcast_ref::() + .expect("got non-string argument to fs_read_text"); + Ok(match std::fs::read_to_string(&a.0) { + Ok(contents) => Data::new(data::string::String(contents)), + Err(e) => Data::new(Object::new(vec![( + i.global.object_fields.get_or_add_field("fs_read_error"), + Data::new(data::string::String(e.to_string())), + )])), + }) + }, + ), + ) + .add_var( + "fs_write", + Function::new_generic( + |a, i| { + if a.is_included_in_single(&TupleT(vec![ + Type::new(StringT), + Type::new(StringT), + ])) { + Ok(Type::newm(vec![ + Arc::new(TupleT(vec![])), + Arc::new(ObjectT::new(vec![( + i.global.object_fields.get_or_add_field("fs_write_error"), + Type::new(data::string::StringT), + )])), + ])) + } else { + Err(format!( + "Called fs_write with argument type {}, but expected (String, String)", + a.with_info(i) + ))? + } + }, + |a, i| { + let a = a.get(); + let a = a + .as_any() + .downcast_ref::() + .expect("got non-tuple argument to fs_read_text"); + let (a, b) = (a.0[0].get(), a.0[1].get()); + let a = a + .as_any() + .downcast_ref::() + .expect("file path was not a string in fs_write"); + let b = b + .as_any() + .downcast_ref::() + .expect("file content was not a string in fs_write"); + Ok(match std::fs::write(&a.0, &b.0) { + Ok(()) => Data::empty_tuple(), + Err(e) => Data::new(Object::new(vec![( + i.global.object_fields.get_or_add_field("fs_write_error"), + Data::new(data::string::String(e.to_string())), + )])), + }) + }, + ), + ) + } +}