From cb395da8944d4b4f066f621a27cb509993e01e02 Mon Sep 17 00:00:00 2001 From: Lawrence Bethlenfalvy Date: Thu, 12 Oct 2023 14:36:59 +0100 Subject: [PATCH] Fixed a tricky type erasure bug in the scheduler --- examples/y/main.orc | 7 ++ src/error/mod.rs | 8 +-- src/foreign/atom.rs | 3 +- src/foreign/extern_fn.rs | 6 +- src/foreign/mod.rs | 2 +- src/interner/monotype.rs | 2 +- src/interpreter/handler.rs | 14 ++-- src/parse/errors.rs | 4 +- src/parse/facade.rs | 7 +- src/parse/lexer.rs | 29 +++++---- src/parse/mod.rs | 2 +- src/parse/numeric.rs | 6 +- src/parse/string.rs | 5 +- src/pipeline/source_loader/loaded_source.rs | 2 +- src/representations/interpreted.rs | 2 +- src/representations/postmacro.rs | 2 +- .../postmacro_to_interpreted.rs | 12 ++-- src/rule/repository.rs | 2 +- src/rule/rule_error.rs | 5 +- src/rule/state.rs | 5 +- src/systems/asynch/system.rs | 9 ++- src/systems/codegen.rs | 3 +- src/systems/io/bindings.rs | 8 +-- src/systems/scheduler/busy.rs | 29 +++++---- src/systems/scheduler/mod.rs | 1 + src/systems/scheduler/system.rs | 64 +++++++++---------- src/systems/stl/bool.rs | 18 +++--- src/systems/stl/map.orc | 4 +- src/systems/stl/mod.rs | 4 +- src/systems/stl/number.rs | 2 +- src/utils/pure_seq.rs | 2 +- src/utils/rc_tools.rs | 3 +- 32 files changed, 147 insertions(+), 125 deletions(-) create mode 100644 examples/y/main.orc diff --git a/examples/y/main.orc b/examples/y/main.orc new file mode 100644 index 0000000..d4b3647 --- /dev/null +++ b/examples/y/main.orc @@ -0,0 +1,7 @@ +import system::async::(set_timer, yield) +import system::io::(readln, println) + +const main := ( + set_timer true 1 (println "y" yield) + \cancel. readln \a. cancel +) diff --git a/src/error/mod.rs b/src/error/mod.rs index 07d472b..4842e66 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -1,24 +1,24 @@ //! Various errors the pipeline can produce +mod assertion_error; mod conflicting_roles; mod import_all; mod no_targets; mod not_exported; mod parse_error_with_tokens; mod project_error; +mod runtime_error; mod too_many_supers; mod unexpected_directory; mod visibility_mismatch; -mod assertion_error; -mod runtime_error; +pub use assertion_error::AssertionError; pub use conflicting_roles::ConflictingRoles; pub use import_all::ImportAll; pub use no_targets::NoTargets; pub use not_exported::NotExported; pub use parse_error_with_tokens::ParseErrorWithTokens; pub use project_error::{ErrorPosition, ProjectError, ProjectResult}; +pub use runtime_error::RuntimeError; pub use too_many_supers::TooManySupers; pub use unexpected_directory::UnexpectedDirectory; pub use visibility_mismatch::VisibilityMismatch; -pub use assertion_error::AssertionError; -pub use runtime_error::RuntimeError; diff --git a/src/foreign/atom.rs b/src/foreign/atom.rs index 0e7fddc..64ef590 100644 --- a/src/foreign/atom.rs +++ b/src/foreign/atom.rs @@ -37,8 +37,7 @@ pub trait StrictEq { } /// Functionality the interpreter needs to handle a value -pub trait Atomic: - Any + Debug + DynClone + StrictEq + Responder + Send +pub trait Atomic: Any + Debug + DynClone + StrictEq + Responder + Send where Self: 'static, { diff --git a/src/foreign/extern_fn.rs b/src/foreign/extern_fn.rs index e4d629d..707cc17 100644 --- a/src/foreign/extern_fn.rs +++ b/src/foreign/extern_fn.rs @@ -3,7 +3,7 @@ use std::fmt::{Debug, Display}; use std::hash::Hash; use std::rc::Rc; -use dyn_clone::{DynClone, clone_box}; +use dyn_clone::{clone_box, DynClone}; use super::XfnResult; use crate::interpreted::ExprInst; @@ -81,7 +81,5 @@ impl ExFn { } } impl Clone for ExFn { - fn clone(&self) -> Self { - Self(clone_box(self.0.as_ref())) - } + fn clone(&self) -> Self { Self(clone_box(self.0.as_ref())) } } diff --git a/src/foreign/mod.rs b/src/foreign/mod.rs index c0cf495..9a3e084 100644 --- a/src/foreign/mod.rs +++ b/src/foreign/mod.rs @@ -11,7 +11,7 @@ mod inert; use std::rc::Rc; pub use atom::{Atom, Atomic, AtomicResult, AtomicReturn, StrictEq}; -pub use extern_fn::{ExternError, ExternFn, ExFn}; +pub use extern_fn::{ExFn, ExternError, ExternFn}; pub use fn_bridge::constructors::{ xfn_1ary, xfn_2ary, xfn_3ary, xfn_4ary, xfn_5ary, xfn_6ary, xfn_7ary, xfn_8ary, xfn_9ary, diff --git a/src/interner/monotype.rs b/src/interner/monotype.rs index 28d390a..5c0d322 100644 --- a/src/interner/monotype.rs +++ b/src/interner/monotype.rs @@ -1,6 +1,6 @@ use std::borrow::Borrow; use std::hash::{BuildHasher, Hash}; -use std::sync::{RwLock, Arc}; +use std::sync::{Arc, RwLock}; use hashbrown::HashMap; diff --git a/src/interpreter/handler.rs b/src/interpreter/handler.rs index 38b6c01..3c8374c 100644 --- a/src/interpreter/handler.rs +++ b/src/interpreter/handler.rs @@ -70,14 +70,12 @@ pub fn run_handler( loop { let mut ret = run(expr, ctx.clone())?; let quit = take_with_output(&mut ret.state, |exi| match exi.expr_val() { - Expr { clause: Clause::Atom(a), .. } => { - match handlers.dispatch(a.0) { - Err(b) => (Clause::Atom(Atom(b)).wrap(), Ok(true)), - Ok(e) => match e { - Ok(expr) => (expr, Ok(false)), - Err(e) => (Clause::Bottom.wrap(), Err(e)), - }, - } + Expr { clause: Clause::Atom(a), .. } => match handlers.dispatch(a.0) { + Err(b) => (Clause::Atom(Atom(b)).wrap(), Ok(true)), + Ok(e) => match e { + Ok(expr) => (expr, Ok(false)), + Err(e) => (Clause::Bottom.wrap(), Err(e)), + }, }, expr => (ExprInst::new(expr), Ok(true)), })?; diff --git a/src/parse/errors.rs b/src/parse/errors.rs index 563435a..a3d7712 100644 --- a/src/parse/errors.rs +++ b/src/parse/errors.rs @@ -183,7 +183,9 @@ impl ProjectError for NaNLiteral { pub struct LiteralOverflow(pub Location); impl ProjectError for LiteralOverflow { - fn description(&self) -> &str { "number literal described number greater than usize::MAX" } + fn description(&self) -> &str { + "number literal described number greater than usize::MAX" + } fn one_position(&self) -> Location { self.0.clone() } } diff --git a/src/parse/facade.rs b/src/parse/facade.rs index 481e0b8..d71f152 100644 --- a/src/parse/facade.rs +++ b/src/parse/facade.rs @@ -11,7 +11,12 @@ pub fn parse2(ctx: impl Context) -> ProjectResult> { Ok(Vec::new()) } else { parse_module_body(Stream::from_slice(&tokens), &ctx).map_err(|error| { - ParseErrorWithTokens { error, full_source: ctx.source().to_string(), tokens }.rc() + ParseErrorWithTokens { + error, + full_source: ctx.source().to_string(), + tokens, + } + .rc() }) } } diff --git a/src/parse/lexer.rs b/src/parse/lexer.rs index 25e6856..c5d67bb 100644 --- a/src/parse/lexer.rs +++ b/src/parse/lexer.rs @@ -5,15 +5,15 @@ use std::sync::Arc; use itertools::Itertools; use ordered_float::NotNan; -use super::LexerPlugin; use super::context::Context; use super::errors::{FloatPlacehPrio, NoCommentEnd}; -use super::numeric::{parse_num, print_nat16, numstart}; +use super::numeric::{numstart, parse_num, print_nat16}; +use super::LexerPlugin; use crate::ast::{PHClass, Placeholder}; -use crate::error::{ProjectResult, ProjectError}; +use crate::error::{ProjectError, ProjectResult}; use crate::foreign::Atom; use crate::interner::Tok; -use crate::parse::numeric::{numchar, lex_numeric}; +use crate::parse::numeric::{lex_numeric, numchar}; use crate::parse::string::lex_string; use crate::systems::stl::Numeric; use crate::utils::pure_seq::next; @@ -210,7 +210,7 @@ pub fn lex( ctx: &impl Context, ) -> ProjectResult> { let mut prev_len = data.len() + 1; - 'tail:loop { + 'tail: loop { if prev_len == data.len() { panic!("got stuck at {data:?}, parsed {:?}", tokens.last().unwrap()); } @@ -234,12 +234,13 @@ pub fn lex( } for (prefix, lexeme) in lit_table() { if let Some(tail) = data.strip_prefix(prefix) { - tokens.push(Entry::new(ctx.location(prefix.len(), tail), lexeme.clone())); + tokens + .push(Entry::new(ctx.location(prefix.len(), tail), lexeme.clone())); data = tail; continue 'tail; } } - + if let Some(tail) = data.strip_prefix(',') { let lexeme = Lexeme::Name(ctx.interner().i(",")); tokens.push(Entry::new(ctx.location(1, tail), lexeme)); @@ -267,7 +268,11 @@ pub fn lex( if tail.chars().next().map_or(false, numstart) { let (num, post_num) = split_filter(tail, numchar); if let Some(tail) = post_num.strip_prefix("=>") { - let lexeme = Lexeme::Arrow(parse_num(num).map_err(|e| e.into_proj(num.len(), post_num, ctx))?.as_float()); + let lexeme = Lexeme::Arrow( + parse_num(num) + .map_err(|e| e.into_proj(num.len(), post_num, ctx))? + .as_float(), + ); let location = ctx.location(num.len() + 3, tail); tokens.push(Entry::new(location, lexeme)); data = tail; @@ -281,7 +286,8 @@ pub fn lex( if !name.is_empty() { let name = ctx.interner().i(name); let location = ctx.location(name.len() + 1, tail); - let lexeme = Lexeme::Placeh(Placeholder { name, class: PHClass::Scalar }); + let lexeme = + Lexeme::Placeh(Placeholder { name, class: PHClass::Scalar }); tokens.push(Entry::new(location, lexeme)); data = tail; continue 'tail; @@ -302,13 +308,14 @@ pub fn lex( .map_err(|e| e.into_proj(num_str.len(), tail, ctx)) .and_then(|num| { Ok(unwrap_or!(num => Numeric::Uint; { - return Err(FloatPlacehPrio(ctx.location(num_str.len(), tail)).rc()) + let location = ctx.location(num_str.len(), tail); + return Err(FloatPlacehPrio(location).rc()) })) }) .map(|p| (p, num_str.len() + 1, tail)) }) .unwrap_or(Ok((0, 0, tail)))?; - let byte_len = if nonzero { 4 } else { 3 } + priolen + name.len(); + let byte_len = if nonzero { 4 } else { 3 } + priolen + name.len(); let name = ctx.interner().i(name); let class = PHClass::Vec { nonzero, prio }; let lexeme = Lexeme::Placeh(Placeholder { name, class }); diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 530ba41..30de92a 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -8,7 +8,7 @@ mod sourcefile; mod stream; mod string; -pub use context::{ParsingContext, Context, LexerPlugin, LineParser}; +pub use context::{Context, LexerPlugin, LineParser, ParsingContext}; pub use facade::parse2; pub use lexer::{namechar, namestart, opchar, split_filter, Entry, Lexeme}; pub use numeric::{ diff --git a/src/parse/numeric.rs b/src/parse/numeric.rs index 26f636e..ac758f2 100644 --- a/src/parse/numeric.rs +++ b/src/parse/numeric.rs @@ -143,14 +143,14 @@ mod test { #[must_use] pub fn print_nat16(num: NotNan) -> String { if *num == 0.0 { - return "0x0".to_string() + return "0x0".to_string(); } else if num.is_infinite() { return match num.is_sign_positive() { true => "Infinity".to_string(), false => "-Infinity".to_string(), - } + }; } else if num.is_nan() { - return "NaN".to_string() + return "NaN".to_string(); } let exp = num.log(16.0).floor(); let man = *num / 16_f64.powf(exp); diff --git a/src/parse/string.rs b/src/parse/string.rs index 63175c0..4963351 100644 --- a/src/parse/string.rs +++ b/src/parse/string.rs @@ -111,7 +111,10 @@ mod test { let (data, tail) = lex_string(source, &MockContext(&i)) .expect("the snippet starts with a quote") .expect("it contains a valid string"); - assert_eq!(data.try_downcast::().unwrap().as_str(), "hello world!"); + assert_eq!( + data.try_downcast::().unwrap().as_str(), + "hello world!" + ); assert_eq!(tail, " - says the programmer"); } } diff --git a/src/pipeline/source_loader/loaded_source.rs b/src/pipeline/source_loader/loaded_source.rs index 6109b60..f58b298 100644 --- a/src/pipeline/source_loader/loaded_source.rs +++ b/src/pipeline/source_loader/loaded_source.rs @@ -5,7 +5,7 @@ use crate::sourcefile::FileEntry; #[derive(Debug)] pub struct LoadedSource { - pub entries: Vec + pub entries: Vec, } pub type LoadedSourceTable = HashMap; diff --git a/src/representations/interpreted.rs b/src/representations/interpreted.rs index 8e636c6..358c8bb 100644 --- a/src/representations/interpreted.rs +++ b/src/representations/interpreted.rs @@ -5,7 +5,7 @@ use std::fmt::{Debug, Display}; use std::ops::{Deref, DerefMut}; use std::rc::Rc; -use std::sync::{Arc, TryLockError, Mutex}; +use std::sync::{Arc, Mutex, TryLockError}; #[allow(unused)] // for doc use super::ast; diff --git a/src/representations/postmacro.rs b/src/representations/postmacro.rs index b8e5588..f98df7f 100644 --- a/src/representations/postmacro.rs +++ b/src/representations/postmacro.rs @@ -2,7 +2,7 @@ use std::fmt::{Debug, Write}; use std::rc::Rc; use super::location::Location; -use crate::foreign::{ExFn, Atom}; +use crate::foreign::{Atom, ExFn}; use crate::utils::string_from_charset; use crate::Sym; diff --git a/src/representations/postmacro_to_interpreted.rs b/src/representations/postmacro_to_interpreted.rs index b3bb6f9..fed105d 100644 --- a/src/representations/postmacro_to_interpreted.rs +++ b/src/representations/postmacro_to_interpreted.rs @@ -19,11 +19,10 @@ fn collect_paths_cls_rec( match cls { postmacro::Clause::Atom(_) | postmacro::Clause::ExternFn(_) => None, postmacro::Clause::Constant(_) => None, - postmacro::Clause::LambdaArg(h) => - match *h != depth { - true => None, - false => Some(PathSet::pick()) - }, + postmacro::Clause::LambdaArg(h) => match *h != depth { + true => None, + false => Some(PathSet::pick()), + }, postmacro::Clause::Lambda(b) => collect_paths_expr_rec(b, depth + 1), postmacro::Clause::Apply(f, x) => { let f_opt = collect_paths_expr_rec(f, depth); @@ -43,7 +42,8 @@ pub fn clause(cls: &postmacro::Clause) -> interpreted::Clause { postmacro::Clause::Constant(name) => interpreted::Clause::Constant(name.clone()), postmacro::Clause::Atom(a) => interpreted::Clause::Atom(a.clone()), - postmacro::Clause::ExternFn(fun) => interpreted::Clause::ExternFn(fun.clone()), + postmacro::Clause::ExternFn(fun) => + interpreted::Clause::ExternFn(fun.clone()), postmacro::Clause::Apply(f, x) => interpreted::Clause::Apply { f: expr(f.as_ref()), x: expr(x.as_ref()) }, postmacro::Clause::Lambda(body) => interpreted::Clause::Lambda { diff --git a/src/rule/repository.rs b/src/rule/repository.rs index fe789d5..d5868dd 100644 --- a/src/rule/repository.rs +++ b/src/rule/repository.rs @@ -11,8 +11,8 @@ use super::state::apply_exprv; use super::{update_first_seq, RuleError, VectreeMatcher}; use crate::ast::Rule; use crate::interner::Interner; -use crate::Sym; use crate::parse::print_nat16; +use crate::Sym; #[derive(Debug)] pub struct CachedRule { diff --git a/src/rule/rule_error.rs b/src/rule/rule_error.rs index 8e48ca2..63ce72c 100644 --- a/src/rule/rule_error.rs +++ b/src/rule/rule_error.rs @@ -51,8 +51,9 @@ impl Display for RuleError { Self::Multiple(key) => { write!(f, "Key {key} appears multiple times in match pattern") }, - Self::VecNeighbors(left, right) => - write!(f, "vectorials {left} and {right} are next to each other"), + Self::VecNeighbors(left, right) => { + write!(f, "vectorials {left} and {right} are next to each other") + }, } } } diff --git a/src/rule/state.rs b/src/rule/state.rs index 0338ef1..a5cbadd 100644 --- a/src/rule/state.rs +++ b/src/rule/state.rs @@ -27,8 +27,9 @@ pub fn apply_exprv(template: &[RuleExpr], state: &State) -> Vec { pub fn apply_expr(template: &RuleExpr, state: &State) -> Vec { let Expr { location, value } = template; match value { - Clause::Atom(_) | Clause::Name(_) | Clause::ExternFn(_) => - vec![template.clone()], + Clause::Atom(_) | Clause::Name(_) | Clause::ExternFn(_) => { + vec![template.clone()] + }, Clause::S(c, body) => vec![Expr { location: location.clone(), value: Clause::S(*c, Rc::new(apply_exprv(body.as_slice(), state))), diff --git a/src/systems/asynch/system.rs b/src/systems/asynch/system.rs index 6893227..38448cb 100644 --- a/src/systems/asynch/system.rs +++ b/src/systems/asynch/system.rs @@ -18,6 +18,7 @@ use crate::interpreted::{Clause, ExprInst}; use crate::interpreter::HandlerTable; use crate::pipeline::file_loader::embed_to_map; use crate::systems::codegen::call; +use crate::systems::stl::Numeric; use crate::utils::poller::{PollEvent, Poller}; use crate::utils::unwrap_or; use crate::{ConstTree, Interner}; @@ -28,8 +29,8 @@ struct Timer { delay: NotNan, } -pub fn set_timer(recurring: bool, delay: NotNan) -> XfnResult { - Ok(init_cps(2, Timer { recurring, delay })) +pub fn set_timer(recurring: bool, delay: Numeric) -> XfnResult { + Ok(init_cps(2, Timer { recurring, delay: delay.as_float() })) } #[derive(Clone)] @@ -38,9 +39,7 @@ impl CancelTimer { pub fn new(f: impl Fn() + Send + 'static) -> Self { Self(Arc::new(Mutex::new(f))) } - pub fn cancel(&self) { - self.0.lock().unwrap()() - } + pub fn cancel(&self) { self.0.lock().unwrap()() } } impl Debug for CancelTimer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/src/systems/codegen.rs b/src/systems/codegen.rs index cfc6502..b0d31a3 100644 --- a/src/systems/codegen.rs +++ b/src/systems/codegen.rs @@ -39,7 +39,8 @@ pub fn tuple(data: impl IntoIterator) -> Clause { #[cfg(test)] mod test { - use crate::{systems::codegen::tuple, foreign::Atomic}; + use crate::foreign::Atomic; + use crate::systems::codegen::tuple; #[test] fn tuple_printer() { diff --git a/src/systems/io/bindings.rs b/src/systems/io/bindings.rs index 19f36d9..1b4230a 100644 --- a/src/systems/io/bindings.rs +++ b/src/systems/io/bindings.rs @@ -2,12 +2,12 @@ use super::flow::IOCmdHandlePack; use super::instances::{BRead, ReadCmd, SRead, Sink, Source, WriteCmd}; use crate::error::RuntimeError; use crate::foreign::cps_box::init_cps; -use crate::foreign::{xfn_1ary, xfn_2ary, Atomic, XfnResult, Atom}; +use crate::foreign::{xfn_1ary, xfn_2ary, Atom, Atomic, XfnResult}; use crate::interpreted::Clause; use crate::representations::OrcString; use crate::systems::scheduler::SharedHandle; use crate::systems::stl::Binary; -use crate::{ConstTree, Interner, ast}; +use crate::{ast, ConstTree, Interner}; type WriteHandle = SharedHandle; type ReadHandle = SharedHandle; @@ -62,9 +62,7 @@ pub fn io_bindings<'a>( ]) + ConstTree::Tree( std_streams .into_iter() - .map(|(n, at)| { - (i.i(n), ConstTree::clause(ast::Clause::Atom(Atom(at)))) - }) + .map(|(n, at)| (i.i(n), ConstTree::clause(ast::Clause::Atom(Atom(at))))) .collect(), ), ) diff --git a/src/systems/scheduler/busy.rs b/src/systems/scheduler/busy.rs index f5dc1d0..6544988 100644 --- a/src/systems/scheduler/busy.rs +++ b/src/systems/scheduler/busy.rs @@ -5,12 +5,13 @@ use super::Canceller; use crate::interpreted::ExprInst; pub type SyncResult = (T, Box); +/// Output from handlers contains the resource being processed and any Orchid +/// handlers executed as a result of the operation +pub type HandlerRes = (T, Vec); pub type SyncOperation = Box SyncResult + Send>; pub type SyncOpResultHandler = Box< - dyn FnOnce(T, Box, Canceller) -> (T, Vec) - - + Send, + dyn FnOnce(T, Box, Canceller) -> (T, Vec) + Send, >; struct SyncQueueItem { @@ -43,10 +44,7 @@ pub struct BusyState { } impl BusyState { pub fn new( - handler: impl FnOnce(T, U, Canceller) -> (T, Vec) - - + Send - + 'static, + handler: impl FnOnce(T, U, Canceller) -> HandlerRes + Send + 'static, ) -> Self { BusyState { handler: Box::new(|t, payload, cancel| { @@ -65,8 +63,8 @@ impl BusyState { pub fn enqueue( &mut self, operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static, - handler: impl FnOnce(T, U, Canceller) -> (T, Vec) + Send + 'static, - early_cancel: impl FnOnce(T) -> (T, Vec) + Send + 'static, + handler: impl FnOnce(T, U, Canceller) -> HandlerRes + Send + 'static, + early_cancel: impl FnOnce(T) -> HandlerRes + Send + 'static, ) -> Option { if self.seal.is_some() { return None; @@ -80,28 +78,31 @@ impl BusyState { (t, Box::new(r)) }), handler: Box::new(|t, u, c| { - let u = u.downcast().expect("mismatched handler and operation"); + let u: Box = u.downcast().expect("mismatched handler and operation"); handler(t, *u, c) }), }); Some(cancelled) } - pub fn seal(&mut self, recipient: impl FnOnce(T) -> Vec + Send + 'static) { + pub fn seal( + &mut self, + recipient: impl FnOnce(T) -> Vec + Send + 'static, + ) { assert!(self.seal.is_none(), "Already sealed"); self.seal = Some(Box::new(recipient)) } pub fn is_sealed(&self) -> bool { self.seal.is_some() } - pub fn rotate( + pub fn rotate( mut self, instance: T, - result: U, + result: Box, cancelled: Canceller, ) -> NextItemReport { let (mut instance, mut events) = - (self.handler)(instance, Box::new(result), cancelled); + (self.handler)(instance, result, cancelled); let next_item = loop { if let Some(candidate) = self.queue.pop_front() { if candidate.cancelled.is_cancelled() { diff --git a/src/systems/scheduler/mod.rs b/src/systems/scheduler/mod.rs index d4952ec..f9e4ead 100644 --- a/src/systems/scheduler/mod.rs +++ b/src/systems/scheduler/mod.rs @@ -5,5 +5,6 @@ mod busy; mod canceller; mod system; +pub use busy::HandlerRes; pub use canceller::Canceller; pub use system::{SealedOrTaken, SeqScheduler, SharedHandle, SharedState}; diff --git a/src/systems/scheduler/system.rs b/src/systems/scheduler/system.rs index b346792..c5b7618 100644 --- a/src/systems/scheduler/system.rs +++ b/src/systems/scheduler/system.rs @@ -8,8 +8,8 @@ use hashbrown::HashMap; use itertools::Itertools; use trait_set::trait_set; -use super::busy::{BusyState, NextItemReportKind}; -use super::Canceller; +use super::busy::{BusyState, NextItemReportKind, SyncOperation}; +use super::{Canceller, HandlerRes}; use crate::error::AssertionError; use crate::facade::{IntoSystem, System}; use crate::foreign::cps_box::{init_cps, CPSBox}; @@ -80,13 +80,10 @@ impl SharedHandle { /// is to return values synchronously after they have been removed with /// [SyncHandle::untake]. pub fn untake(&self, value: T) -> Result<(), T> { - take_with_output( - &mut *self.0.lock().unwrap(), - |state| match state { - SharedResource::Taken => (SharedResource::Free(value), Ok(())), - _ => (state, Err(value)), - }, - ) + take_with_output(&mut *self.0.lock().unwrap(), |state| match state { + SharedResource::Taken => (SharedResource::Free(value), Ok(())), + _ => (state, Err(value)), + }) } } impl Clone for SharedHandle { @@ -144,7 +141,7 @@ pub fn is_taken_error(x: ExprInst) -> XfnResult { trait_set! { /// The part of processing a blocking I/O task that cannot be done on a remote /// thread, eg. because it accesses other systems or Orchid code. - trait NonSendFn = FnOnce(Box, SeqScheduler) -> Vec; + trait NonSendFn = FnOnce(Box, SeqScheduler) -> Vec; } struct SyncReply { @@ -198,9 +195,9 @@ impl SeqScheduler { pub fn schedule( &self, handle: SharedHandle, - operation: impl FnOnce(T, Canceller) -> (T, U) + Sync + Send + 'static, - handler: impl FnOnce(T, U, Canceller) -> (T, Vec) + Sync + Send + 'static, - early_cancel: impl FnOnce(T) -> (T, Vec) + Sync + Send + 'static, + operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static, + handler: impl FnOnce(T, U, Canceller) -> HandlerRes + Send + 'static, + early_cancel: impl FnOnce(T) -> HandlerRes + Send + 'static, ) -> Result { take_with_output(&mut *handle.0.lock().unwrap(), { let handle = handle.clone(); @@ -216,7 +213,11 @@ impl SeqScheduler { SharedResource::Free(t) => { let cancelled = Canceller::new(); drop(early_cancel); // cannot possibly be useful - self.submit(t, handle, cancelled.clone(), operation); + let op_erased: SyncOperation = Box::new(|t, c| { + let (t, u) = operation(t, c); + (t, Box::new(u)) + }); + self.submit(t, handle, cancelled.clone(), op_erased); (SharedResource::Busy(BusyState::new(handler)), Ok(cancelled)) }, } @@ -233,9 +234,11 @@ impl SeqScheduler { ) -> Canceller { let cancelled = Canceller::new(); let canc1 = cancelled.clone(); - let opid = self.0.pending.borrow_mut().insert(Box::new(|data, _| { - handler(*data.downcast().expect("This is associated by ID"), canc1) - })); + let opid = self.0.pending.borrow_mut().insert(Box::new( + |data: Box, _| { + handler(*data.downcast().expect("This is associated by ID"), canc1) + }, + )); let canc1 = cancelled.clone(); let mut port = self.0.port.clone(); self.0.pool.submit(Box::new(move || { @@ -251,18 +254,15 @@ impl SeqScheduler { handle: SharedHandle, seal: impl FnOnce(T) -> Vec + Sync + Send + 'static, ) -> Result, SealedOrTaken> { - take_with_output( - &mut *handle.0.lock().unwrap(), - |state| match state { - SharedResource::Busy(mut b) if !b.is_sealed() => { - b.seal(seal); - (SharedResource::Busy(b), Ok(Vec::new())) - }, - SharedResource::Busy(_) => (state, Err(SealedOrTaken)), - SharedResource::Taken => (SharedResource::Taken, Err(SealedOrTaken)), - SharedResource::Free(t) => (SharedResource::Taken, Ok(seal(t))), + take_with_output(&mut *handle.0.lock().unwrap(), |state| match state { + SharedResource::Busy(mut b) if !b.is_sealed() => { + b.seal(seal); + (SharedResource::Busy(b), Ok(Vec::new())) }, - ) + SharedResource::Busy(_) => (state, Err(SealedOrTaken)), + SharedResource::Taken => (SharedResource::Taken, Err(SealedOrTaken)), + SharedResource::Free(t) => (SharedResource::Taken, Ok(seal(t))), + }) } /// Asynchronously recursive function to schedule a new task for execution and @@ -270,18 +270,18 @@ impl SeqScheduler { /// from the callback passed to the [AsynchSystem] so that if the task is /// never resolved but the [AsynchSystem] through which the resolving event /// would arrive is dropped this [SeqScheduler] is also dropped. - fn submit( + fn submit( &self, t: T, handle: SharedHandle, cancelled: Canceller, - operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static, + operation: SyncOperation, ) { // referenced by self until run, references handle let opid = self.0.pending.borrow_mut().insert(Box::new({ let cancelled = cancelled.clone(); - move |data, this| { - let (t, u): (T, U) = + move |data: Box, this: SeqScheduler| { + let (t, u): (T, Box) = *data.downcast().expect("This is associated by ID"); let handle2 = handle.clone(); take_with_output(&mut *handle.0.lock().unwrap(), |state| { diff --git a/src/systems/stl/bool.rs b/src/systems/stl/bool.rs index 508fc85..79e0909 100644 --- a/src/systems/stl/bool.rs +++ b/src/systems/stl/bool.rs @@ -1,11 +1,10 @@ -use crate::foreign::{xfn_1ary, xfn_2ary, XfnResult, Atom}; +use super::Numeric; +use crate::error::AssertionError; +use crate::foreign::{xfn_1ary, xfn_2ary, Atom, XfnResult}; use crate::interner::Interner; use crate::representations::interpreted::Clause; -use crate::error::AssertionError; use crate::{ConstTree, Location, OrcString}; -use super::Numeric; - /// Takes a boolean and two branches, runs the first if the bool is true, the /// second if it's false. // Even though it's a ternary function, IfThenElse is implemented as an unary @@ -23,11 +22,12 @@ pub fn if_then_else(b: bool) -> XfnResult { /// - both are bool, /// - both are either uint or num pub fn equals(a: Atom, b: Atom) -> XfnResult { - let (a, b) = match (a.try_downcast::(), b.try_downcast::()) { - (Ok(a), Ok(b)) => return Ok(a == b), - (Err(a), Err(b)) => (a, b), - _ => return Ok(false), - }; + let (a, b) = + match (a.try_downcast::(), b.try_downcast::()) { + (Ok(a), Ok(b)) => return Ok(a == b), + (Err(a), Err(b)) => (a, b), + _ => return Ok(false), + }; match (a.request::(), b.request::()) { (Some(a), Some(b)) => return Ok(a.as_float() == b.as_float()), (None, None) => (), diff --git a/src/systems/stl/map.orc b/src/systems/stl/map.orc index fa4e105..b9142f1 100644 --- a/src/systems/stl/map.orc +++ b/src/systems/stl/map.orc @@ -3,12 +3,12 @@ import std::panic -- utilities for using lists as pairs -export const fst := \l. ( +const fst := \l. ( list::get l 0 (panic "nonempty expected") \x.x ) -export const snd := \l. ( +const snd := \l. ( list::get l 1 (panic "2 elements expected") \x.x diff --git a/src/systems/stl/mod.rs b/src/systems/stl/mod.rs index b1b3b6f..3a169f0 100644 --- a/src/systems/stl/mod.rs +++ b/src/systems/stl/mod.rs @@ -4,15 +4,15 @@ mod arithmetic_error; mod binary; mod bool; mod conv; +mod exit_status; mod inspect; mod number; mod panic; mod state; mod stl_system; mod string; -mod exit_status; pub use arithmetic_error::ArithmeticError; pub use binary::Binary; +pub use exit_status::ExitStatus; pub use number::Numeric; pub use stl_system::StlConfig; -pub use exit_status::ExitStatus; diff --git a/src/systems/stl/number.rs b/src/systems/stl/number.rs index 66290af..a3f9d49 100644 --- a/src/systems/stl/number.rs +++ b/src/systems/stl/number.rs @@ -4,7 +4,7 @@ use ordered_float::NotNan; use super::ArithmeticError; use crate::error::AssertionError; -use crate::foreign::{xfn_2ary, ExternError, ToClause, XfnResult, Atomic}; +use crate::foreign::{xfn_2ary, Atomic, ExternError, ToClause, XfnResult}; use crate::interpreted::TryFromExprInst; use crate::representations::interpreted::{Clause, ExprInst}; use crate::{ConstTree, Interner, Location}; diff --git a/src/utils/pure_seq.rs b/src/utils/pure_seq.rs index 490a201..bfdf34f 100644 --- a/src/utils/pure_seq.rs +++ b/src/utils/pure_seq.rs @@ -20,7 +20,7 @@ pub fn pushed_ref<'a, T: Clone + 'a>( } /// Pure version of [Iterator::next] -/// +/// /// Remove an item from the iterator. If successful, returns the item and the /// iterator. If the iterator is empty it is consumed. pub fn next(mut i: I) -> Option<(I::Item, I)> { diff --git a/src/utils/rc_tools.rs b/src/utils/rc_tools.rs index 8d397be..57c06a5 100644 --- a/src/utils/rc_tools.rs +++ b/src/utils/rc_tools.rs @@ -1,4 +1,5 @@ -use std::{rc::Rc, sync::Arc}; +use std::rc::Rc; +use std::sync::Arc; pub fn rc_to_owned(rc: Rc) -> T { Rc::try_unwrap(rc).unwrap_or_else(|rc| rc.as_ref().clone())