add configs/bundle_pure

This commit is contained in:
Mark 2024-06-23 22:14:29 +02:00
parent 4d570ec5a5
commit 94111a5eaa
8 changed files with 60 additions and 33 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers" name = "mers"
version = "0.8.12" version = "0.8.13"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "dynamically typed but type-checked programming language" description = "dynamically typed but type-checked programming language"
@ -11,7 +11,7 @@ repository = "https://github.com/Dummi26/mers"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
mers_lib = "0.8.12" # mers_lib = "0.8.13"
# mers_lib = { path = "../mers_lib" } mers_lib = { path = "../mers_lib" }
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }
colored = "2.1.0" colored = "2.1.0"

View File

@ -52,6 +52,7 @@ enum From {
enum Configs { enum Configs {
None, None,
Base, Base,
Pure,
Std, Std,
} }
@ -60,6 +61,7 @@ fn main() {
let config = cfg_globals::add_general(match args.config { let config = cfg_globals::add_general(match args.config {
Configs::None => Config::new(), Configs::None => Config::new(),
Configs::Base => Config::new().bundle_base(), Configs::Base => Config::new().bundle_base(),
Configs::Pure => Config::new().bundle_pure(),
Configs::Std => Config::new().bundle_std(), Configs::Std => Config::new().bundle_std(),
}); });
fn get_source(source: From) -> Source { fn get_source(source: From) -> Source {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers_lib" name = "mers_lib"
version = "0.8.12" version = "0.8.13"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "library to use the mers language in other projects" description = "library to use the mers language in other projects"

View File

@ -90,6 +90,8 @@ pub mod error_colors {
pub const StacktraceDescend: Color = Color::Yellow; pub const StacktraceDescend: Color = Color::Yellow;
pub const StacktraceDescendHashInclude: Color = Color::Red; pub const StacktraceDescendHashInclude: Color = Color::Red;
pub const MaximumRuntimeExceeded: Color = Color::BrightYellow;
} }
#[derive(Clone)] #[derive(Clone)]
pub enum CheckErrorComponent { pub enum CheckErrorComponent {

View File

@ -22,12 +22,6 @@ pub mod with_string;
/// bundle_* for bundles (combines multiple groups or even bundles) /// bundle_* for bundles (combines multiple groups or even bundles)
/// with_* for usage-oriented groups /// with_* for usage-oriented groups
/// add_* to add custom things /// add_* to add custom things
///
/// For doc-comments:
/// Description
/// `bundle_std()`
/// `type` - description
/// `var: type` - description
pub struct Config { pub struct Config {
globals: usize, globals: usize,
info_parsed: super::parsed::Info, info_parsed: super::parsed::Info,
@ -37,25 +31,32 @@ pub struct Config {
impl Config { impl Config {
/// standard utilitis used in many programs /// standard utilitis used in many programs
/// `bundle_base()` ///
/// `with_stdio()` /// - `bundle_pure()`
/// `with_list()` /// - `with_stdio()`
/// `with_string()` /// - `with_command_running()`
/// `with_command_running()` /// - `with_multithreading()`
/// `with_multithreading()`
pub fn bundle_std(self) -> Self { pub fn bundle_std(self) -> Self {
self.with_multithreading() self.with_multithreading()
.with_command_running() .with_command_running()
.with_string()
.with_list()
.with_stdio() .with_stdio()
.bundle_base() .bundle_pure()
}
/// standard utilities, but don't allow code to do any I/O.
/// (multithreading can be added using `.with_multithreading()`)
///
/// - `bundle_base()`
/// - `with_list()`
/// - `with_string()`
pub fn bundle_pure(self) -> Self {
self.with_string().with_list().bundle_base()
} }
/// base utilities used in most programs /// base utilities used in most programs
/// `with_base()` ///
/// `with_math()` /// - `with_base()`
/// `with_get()` /// - `with_math()`
/// `with_iters()` /// - `with_get()`
/// - `with_iters()`
pub fn bundle_base(self) -> Self { pub fn bundle_base(self) -> Self {
self.with_iters().with_get().with_math().with_base() self.with_iters().with_get().with_math().with_base()
} }
@ -86,6 +87,7 @@ impl Config {
} }
} }
/// Add a variable. Its type will be that of the value stored in `val`.
pub fn add_var(self, name: String, val: Data) -> Self { pub fn add_var(self, name: String, val: Data) -> Self {
let t = val.get().as_type(); let t = val.get().as_type();
self.add_var_arc(name, Arc::new(RwLock::new(val)), t) self.add_var_arc(name, Arc::new(RwLock::new(val)), t)

View File

@ -1,6 +1,6 @@
use std::{ use std::{
sync::{Arc, Mutex, RwLock}, sync::{Arc, Mutex, RwLock},
time::Duration, time::{Duration, Instant},
}; };
use crate::{ use crate::{
@ -86,15 +86,20 @@ impl Config {
} else { } else {
Err(format!("cannot call sleep with non-int or non-float argument.").into()) Err(format!("cannot call sleep with non-int or non-float argument.").into())
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, i| {
let a = a.get(); let a = a.get();
std::thread::sleep(if let Some(data::int::Int(n)) = a.as_any().downcast_ref() { let mut sleep_dur = if let Some(data::int::Int(n)) = a.as_any().downcast_ref() {
Duration::from_secs(*n as _) Duration::from_secs(*n as _)
} else if let Some(data::float::Float(n)) = a.as_any().downcast_ref() { } else if let Some(data::float::Float(n)) = a.as_any().downcast_ref() {
Duration::from_secs_f64(*n) Duration::from_secs_f64(*n)
} else { } else {
return Err("sleep called on non-int/non-float".into()); return Err("sleep called on non-int/non-float".into());
}); };
// limit how long sleep can take
if let Some(cutoff) = i.global.limit_runtime {
sleep_dur = sleep_dur.min(cutoff.saturating_duration_since(Instant::now()));
}
std::thread::sleep(sleep_dur);
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,

View File

@ -464,7 +464,7 @@ fn genfunc_iter_in_val_out(
name: String, name: String,
iter_type: impl MersType + 'static, iter_type: impl MersType + 'static,
out_type: Type, out_type: Type,
run: impl Fn(Data, &mut crate::info::Info<program::run::Local>) -> Result<Data, CheckError> run: impl Fn(Data, &mut crate::info::Info<program::run::RunLocal>) -> Result<Data, CheckError>
+ Send + Send
+ Sync + Sync
+ 'static, + 'static,

View File

@ -2,11 +2,12 @@ use std::{
collections::HashMap, collections::HashMap,
fmt::Debug, fmt::Debug,
sync::{Arc, Mutex, RwLock}, sync::{Arc, Mutex, RwLock},
time::Instant,
}; };
use crate::{ use crate::{
data::{self, Data, Type}, data::{self, Data, Type},
errors::{CheckError, SourceRange}, errors::{error_colors, CheckError, SourceRange},
info, info,
}; };
@ -94,6 +95,16 @@ pub trait MersStatement: Debug + Send + Sync {
o o
} }
fn run(&self, info: &mut Info) -> Result<Data, CheckError> { fn run(&self, info: &mut Info) -> Result<Data, CheckError> {
if let Some(cutoff) = info.global.limit_runtime {
if Instant::now() >= cutoff {
return Err(CheckError::new()
.msg("maximum runtime exceeded".to_owned())
.src(vec![(
self.source_range(),
Some(error_colors::MaximumRuntimeExceeded),
)]));
}
}
if self.has_scope() { if self.has_scope() {
info.create_scope(); info.create_scope();
} }
@ -108,13 +119,18 @@ pub trait MersStatement: Debug + Send + Sync {
fn as_any(&self) -> &dyn std::any::Any; fn as_any(&self) -> &dyn std::any::Any;
} }
pub type Info = info::Info<Local>; pub type Info = info::Info<RunLocal>;
pub type CheckInfo = info::Info<CheckLocal>; pub type CheckInfo = info::Info<CheckLocal>;
#[derive(Default, Clone, Debug)] #[derive(Default, Clone, Debug)]
pub struct Local { pub struct RunLocal {
pub vars: Vec<Arc<RwLock<Data>>>, pub vars: Vec<Arc<RwLock<Data>>>,
} }
#[derive(Default, Clone, Debug)]
pub struct RunLocalGlobalInfo {
/// if set, if `Instant::now()` is equal to or after the set `Instant`, stop the program with an error.
pub limit_runtime: Option<Instant>,
}
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct CheckLocal { pub struct CheckLocal {
pub vars: Vec<Type>, pub vars: Vec<Type>,
@ -149,10 +165,10 @@ impl Debug for CheckLocal {
write!(f, "CheckLocal {:?}, {:?}", self.vars, self.types.keys()) write!(f, "CheckLocal {:?}, {:?}", self.vars, self.types.keys())
} }
} }
impl info::Local for Local { impl info::Local for RunLocal {
type VariableIdentifier = usize; type VariableIdentifier = usize;
type VariableData = Arc<RwLock<Data>>; type VariableData = Arc<RwLock<Data>>;
type Global = (); type Global = RunLocalGlobalInfo;
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) { fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false)))); let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false))));
while self.vars.len() <= id { while self.vars.len() <= id {