forked from Orchid/orchid
Fixed a tricky type erasure bug in the scheduler
This commit is contained in:
7
examples/y/main.orc
Normal file
7
examples/y/main.orc
Normal file
@@ -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
|
||||||
|
)
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
//! Various errors the pipeline can produce
|
//! Various errors the pipeline can produce
|
||||||
|
mod assertion_error;
|
||||||
mod conflicting_roles;
|
mod conflicting_roles;
|
||||||
mod import_all;
|
mod import_all;
|
||||||
mod no_targets;
|
mod no_targets;
|
||||||
mod not_exported;
|
mod not_exported;
|
||||||
mod parse_error_with_tokens;
|
mod parse_error_with_tokens;
|
||||||
mod project_error;
|
mod project_error;
|
||||||
|
mod runtime_error;
|
||||||
mod too_many_supers;
|
mod too_many_supers;
|
||||||
mod unexpected_directory;
|
mod unexpected_directory;
|
||||||
mod visibility_mismatch;
|
mod visibility_mismatch;
|
||||||
mod assertion_error;
|
|
||||||
mod runtime_error;
|
|
||||||
|
|
||||||
|
pub use assertion_error::AssertionError;
|
||||||
pub use conflicting_roles::ConflictingRoles;
|
pub use conflicting_roles::ConflictingRoles;
|
||||||
pub use import_all::ImportAll;
|
pub use import_all::ImportAll;
|
||||||
pub use no_targets::NoTargets;
|
pub use no_targets::NoTargets;
|
||||||
pub use not_exported::NotExported;
|
pub use not_exported::NotExported;
|
||||||
pub use parse_error_with_tokens::ParseErrorWithTokens;
|
pub use parse_error_with_tokens::ParseErrorWithTokens;
|
||||||
pub use project_error::{ErrorPosition, ProjectError, ProjectResult};
|
pub use project_error::{ErrorPosition, ProjectError, ProjectResult};
|
||||||
|
pub use runtime_error::RuntimeError;
|
||||||
pub use too_many_supers::TooManySupers;
|
pub use too_many_supers::TooManySupers;
|
||||||
pub use unexpected_directory::UnexpectedDirectory;
|
pub use unexpected_directory::UnexpectedDirectory;
|
||||||
pub use visibility_mismatch::VisibilityMismatch;
|
pub use visibility_mismatch::VisibilityMismatch;
|
||||||
pub use assertion_error::AssertionError;
|
|
||||||
pub use runtime_error::RuntimeError;
|
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ pub trait StrictEq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Functionality the interpreter needs to handle a value
|
/// Functionality the interpreter needs to handle a value
|
||||||
pub trait Atomic:
|
pub trait Atomic: Any + Debug + DynClone + StrictEq + Responder + Send
|
||||||
Any + Debug + DynClone + StrictEq + Responder + Send
|
|
||||||
where
|
where
|
||||||
Self: 'static,
|
Self: 'static,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::fmt::{Debug, Display};
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use dyn_clone::{DynClone, clone_box};
|
use dyn_clone::{clone_box, DynClone};
|
||||||
|
|
||||||
use super::XfnResult;
|
use super::XfnResult;
|
||||||
use crate::interpreted::ExprInst;
|
use crate::interpreted::ExprInst;
|
||||||
@@ -81,7 +81,5 @@ impl ExFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Clone for ExFn {
|
impl Clone for ExFn {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self { Self(clone_box(self.0.as_ref())) }
|
||||||
Self(clone_box(self.0.as_ref()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ mod inert;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub use atom::{Atom, Atomic, AtomicResult, AtomicReturn, StrictEq};
|
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::{
|
pub use fn_bridge::constructors::{
|
||||||
xfn_1ary, xfn_2ary, xfn_3ary, xfn_4ary, xfn_5ary, xfn_6ary, xfn_7ary,
|
xfn_1ary, xfn_2ary, xfn_3ary, xfn_4ary, xfn_5ary, xfn_6ary, xfn_7ary,
|
||||||
xfn_8ary, xfn_9ary,
|
xfn_8ary, xfn_9ary,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::hash::{BuildHasher, Hash};
|
use std::hash::{BuildHasher, Hash};
|
||||||
use std::sync::{RwLock, Arc};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
|
|||||||
@@ -70,14 +70,12 @@ pub fn run_handler(
|
|||||||
loop {
|
loop {
|
||||||
let mut ret = run(expr, ctx.clone())?;
|
let mut ret = run(expr, ctx.clone())?;
|
||||||
let quit = take_with_output(&mut ret.state, |exi| match exi.expr_val() {
|
let quit = take_with_output(&mut ret.state, |exi| match exi.expr_val() {
|
||||||
Expr { clause: Clause::Atom(a), .. } => {
|
Expr { clause: Clause::Atom(a), .. } => match handlers.dispatch(a.0) {
|
||||||
match handlers.dispatch(a.0) {
|
Err(b) => (Clause::Atom(Atom(b)).wrap(), Ok(true)),
|
||||||
Err(b) => (Clause::Atom(Atom(b)).wrap(), Ok(true)),
|
Ok(e) => match e {
|
||||||
Ok(e) => match e {
|
Ok(expr) => (expr, Ok(false)),
|
||||||
Ok(expr) => (expr, Ok(false)),
|
Err(e) => (Clause::Bottom.wrap(), Err(e)),
|
||||||
Err(e) => (Clause::Bottom.wrap(), Err(e)),
|
},
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
expr => (ExprInst::new(expr), Ok(true)),
|
expr => (ExprInst::new(expr), Ok(true)),
|
||||||
})?;
|
})?;
|
||||||
|
|||||||
@@ -183,7 +183,9 @@ impl ProjectError for NaNLiteral {
|
|||||||
|
|
||||||
pub struct LiteralOverflow(pub Location);
|
pub struct LiteralOverflow(pub Location);
|
||||||
impl ProjectError for LiteralOverflow {
|
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() }
|
fn one_position(&self) -> Location { self.0.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,12 @@ pub fn parse2(ctx: impl Context) -> ProjectResult<Vec<FileEntry>> {
|
|||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
} else {
|
} else {
|
||||||
parse_module_body(Stream::from_slice(&tokens), &ctx).map_err(|error| {
|
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()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ use std::sync::Arc;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ordered_float::NotNan;
|
use ordered_float::NotNan;
|
||||||
|
|
||||||
use super::LexerPlugin;
|
|
||||||
use super::context::Context;
|
use super::context::Context;
|
||||||
use super::errors::{FloatPlacehPrio, NoCommentEnd};
|
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::ast::{PHClass, Placeholder};
|
||||||
use crate::error::{ProjectResult, ProjectError};
|
use crate::error::{ProjectError, ProjectResult};
|
||||||
use crate::foreign::Atom;
|
use crate::foreign::Atom;
|
||||||
use crate::interner::Tok;
|
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::parse::string::lex_string;
|
||||||
use crate::systems::stl::Numeric;
|
use crate::systems::stl::Numeric;
|
||||||
use crate::utils::pure_seq::next;
|
use crate::utils::pure_seq::next;
|
||||||
@@ -210,7 +210,7 @@ pub fn lex(
|
|||||||
ctx: &impl Context,
|
ctx: &impl Context,
|
||||||
) -> ProjectResult<Vec<Entry>> {
|
) -> ProjectResult<Vec<Entry>> {
|
||||||
let mut prev_len = data.len() + 1;
|
let mut prev_len = data.len() + 1;
|
||||||
'tail:loop {
|
'tail: loop {
|
||||||
if prev_len == data.len() {
|
if prev_len == data.len() {
|
||||||
panic!("got stuck at {data:?}, parsed {:?}", tokens.last().unwrap());
|
panic!("got stuck at {data:?}, parsed {:?}", tokens.last().unwrap());
|
||||||
}
|
}
|
||||||
@@ -234,12 +234,13 @@ pub fn lex(
|
|||||||
}
|
}
|
||||||
for (prefix, lexeme) in lit_table() {
|
for (prefix, lexeme) in lit_table() {
|
||||||
if let Some(tail) = data.strip_prefix(prefix) {
|
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;
|
data = tail;
|
||||||
continue 'tail;
|
continue 'tail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(tail) = data.strip_prefix(',') {
|
if let Some(tail) = data.strip_prefix(',') {
|
||||||
let lexeme = Lexeme::Name(ctx.interner().i(","));
|
let lexeme = Lexeme::Name(ctx.interner().i(","));
|
||||||
tokens.push(Entry::new(ctx.location(1, tail), lexeme));
|
tokens.push(Entry::new(ctx.location(1, tail), lexeme));
|
||||||
@@ -267,7 +268,11 @@ pub fn lex(
|
|||||||
if tail.chars().next().map_or(false, numstart) {
|
if tail.chars().next().map_or(false, numstart) {
|
||||||
let (num, post_num) = split_filter(tail, numchar);
|
let (num, post_num) = split_filter(tail, numchar);
|
||||||
if let Some(tail) = post_num.strip_prefix("=>") {
|
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);
|
let location = ctx.location(num.len() + 3, tail);
|
||||||
tokens.push(Entry::new(location, lexeme));
|
tokens.push(Entry::new(location, lexeme));
|
||||||
data = tail;
|
data = tail;
|
||||||
@@ -281,7 +286,8 @@ pub fn lex(
|
|||||||
if !name.is_empty() {
|
if !name.is_empty() {
|
||||||
let name = ctx.interner().i(name);
|
let name = ctx.interner().i(name);
|
||||||
let location = ctx.location(name.len() + 1, tail);
|
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));
|
tokens.push(Entry::new(location, lexeme));
|
||||||
data = tail;
|
data = tail;
|
||||||
continue 'tail;
|
continue 'tail;
|
||||||
@@ -302,13 +308,14 @@ pub fn lex(
|
|||||||
.map_err(|e| e.into_proj(num_str.len(), tail, ctx))
|
.map_err(|e| e.into_proj(num_str.len(), tail, ctx))
|
||||||
.and_then(|num| {
|
.and_then(|num| {
|
||||||
Ok(unwrap_or!(num => Numeric::Uint; {
|
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))
|
.map(|p| (p, num_str.len() + 1, tail))
|
||||||
})
|
})
|
||||||
.unwrap_or(Ok((0, 0, 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 name = ctx.interner().i(name);
|
||||||
let class = PHClass::Vec { nonzero, prio };
|
let class = PHClass::Vec { nonzero, prio };
|
||||||
let lexeme = Lexeme::Placeh(Placeholder { name, class });
|
let lexeme = Lexeme::Placeh(Placeholder { name, class });
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ mod sourcefile;
|
|||||||
mod stream;
|
mod stream;
|
||||||
mod string;
|
mod string;
|
||||||
|
|
||||||
pub use context::{ParsingContext, Context, LexerPlugin, LineParser};
|
pub use context::{Context, LexerPlugin, LineParser, ParsingContext};
|
||||||
pub use facade::parse2;
|
pub use facade::parse2;
|
||||||
pub use lexer::{namechar, namestart, opchar, split_filter, Entry, Lexeme};
|
pub use lexer::{namechar, namestart, opchar, split_filter, Entry, Lexeme};
|
||||||
pub use numeric::{
|
pub use numeric::{
|
||||||
|
|||||||
@@ -143,14 +143,14 @@ mod test {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn print_nat16(num: NotNan<f64>) -> String {
|
pub fn print_nat16(num: NotNan<f64>) -> String {
|
||||||
if *num == 0.0 {
|
if *num == 0.0 {
|
||||||
return "0x0".to_string()
|
return "0x0".to_string();
|
||||||
} else if num.is_infinite() {
|
} else if num.is_infinite() {
|
||||||
return match num.is_sign_positive() {
|
return match num.is_sign_positive() {
|
||||||
true => "Infinity".to_string(),
|
true => "Infinity".to_string(),
|
||||||
false => "-Infinity".to_string(),
|
false => "-Infinity".to_string(),
|
||||||
}
|
};
|
||||||
} else if num.is_nan() {
|
} else if num.is_nan() {
|
||||||
return "NaN".to_string()
|
return "NaN".to_string();
|
||||||
}
|
}
|
||||||
let exp = num.log(16.0).floor();
|
let exp = num.log(16.0).floor();
|
||||||
let man = *num / 16_f64.powf(exp);
|
let man = *num / 16_f64.powf(exp);
|
||||||
|
|||||||
@@ -111,7 +111,10 @@ mod test {
|
|||||||
let (data, tail) = lex_string(source, &MockContext(&i))
|
let (data, tail) = lex_string(source, &MockContext(&i))
|
||||||
.expect("the snippet starts with a quote")
|
.expect("the snippet starts with a quote")
|
||||||
.expect("it contains a valid string");
|
.expect("it contains a valid string");
|
||||||
assert_eq!(data.try_downcast::<OrcString>().unwrap().as_str(), "hello world!");
|
assert_eq!(
|
||||||
|
data.try_downcast::<OrcString>().unwrap().as_str(),
|
||||||
|
"hello world!"
|
||||||
|
);
|
||||||
assert_eq!(tail, " - says the programmer");
|
assert_eq!(tail, " - says the programmer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::sourcefile::FileEntry;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LoadedSource {
|
pub struct LoadedSource {
|
||||||
pub entries: Vec<FileEntry>
|
pub entries: Vec<FileEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type LoadedSourceTable = HashMap<VName, LoadedSource>;
|
pub type LoadedSourceTable = HashMap<VName, LoadedSource>;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, TryLockError, Mutex};
|
use std::sync::{Arc, Mutex, TryLockError};
|
||||||
|
|
||||||
#[allow(unused)] // for doc
|
#[allow(unused)] // for doc
|
||||||
use super::ast;
|
use super::ast;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::fmt::{Debug, Write};
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::location::Location;
|
use super::location::Location;
|
||||||
use crate::foreign::{ExFn, Atom};
|
use crate::foreign::{Atom, ExFn};
|
||||||
use crate::utils::string_from_charset;
|
use crate::utils::string_from_charset;
|
||||||
use crate::Sym;
|
use crate::Sym;
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,10 @@ fn collect_paths_cls_rec(
|
|||||||
match cls {
|
match cls {
|
||||||
postmacro::Clause::Atom(_) | postmacro::Clause::ExternFn(_) => None,
|
postmacro::Clause::Atom(_) | postmacro::Clause::ExternFn(_) => None,
|
||||||
postmacro::Clause::Constant(_) => None,
|
postmacro::Clause::Constant(_) => None,
|
||||||
postmacro::Clause::LambdaArg(h) =>
|
postmacro::Clause::LambdaArg(h) => match *h != depth {
|
||||||
match *h != depth {
|
true => None,
|
||||||
true => None,
|
false => Some(PathSet::pick()),
|
||||||
false => Some(PathSet::pick())
|
},
|
||||||
},
|
|
||||||
postmacro::Clause::Lambda(b) => collect_paths_expr_rec(b, depth + 1),
|
postmacro::Clause::Lambda(b) => collect_paths_expr_rec(b, depth + 1),
|
||||||
postmacro::Clause::Apply(f, x) => {
|
postmacro::Clause::Apply(f, x) => {
|
||||||
let f_opt = collect_paths_expr_rec(f, depth);
|
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) =>
|
postmacro::Clause::Constant(name) =>
|
||||||
interpreted::Clause::Constant(name.clone()),
|
interpreted::Clause::Constant(name.clone()),
|
||||||
postmacro::Clause::Atom(a) => interpreted::Clause::Atom(a.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) =>
|
postmacro::Clause::Apply(f, x) =>
|
||||||
interpreted::Clause::Apply { f: expr(f.as_ref()), x: expr(x.as_ref()) },
|
interpreted::Clause::Apply { f: expr(f.as_ref()), x: expr(x.as_ref()) },
|
||||||
postmacro::Clause::Lambda(body) => interpreted::Clause::Lambda {
|
postmacro::Clause::Lambda(body) => interpreted::Clause::Lambda {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use super::state::apply_exprv;
|
|||||||
use super::{update_first_seq, RuleError, VectreeMatcher};
|
use super::{update_first_seq, RuleError, VectreeMatcher};
|
||||||
use crate::ast::Rule;
|
use crate::ast::Rule;
|
||||||
use crate::interner::Interner;
|
use crate::interner::Interner;
|
||||||
use crate::Sym;
|
|
||||||
use crate::parse::print_nat16;
|
use crate::parse::print_nat16;
|
||||||
|
use crate::Sym;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CachedRule<M: Matcher> {
|
pub struct CachedRule<M: Matcher> {
|
||||||
|
|||||||
@@ -51,8 +51,9 @@ impl Display for RuleError {
|
|||||||
Self::Multiple(key) => {
|
Self::Multiple(key) => {
|
||||||
write!(f, "Key {key} appears multiple times in match pattern")
|
write!(f, "Key {key} appears multiple times in match pattern")
|
||||||
},
|
},
|
||||||
Self::VecNeighbors(left, right) =>
|
Self::VecNeighbors(left, right) => {
|
||||||
write!(f, "vectorials {left} and {right} are next to each other"),
|
write!(f, "vectorials {left} and {right} are next to each other")
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ pub fn apply_exprv(template: &[RuleExpr], state: &State) -> Vec<RuleExpr> {
|
|||||||
pub fn apply_expr(template: &RuleExpr, state: &State) -> Vec<RuleExpr> {
|
pub fn apply_expr(template: &RuleExpr, state: &State) -> Vec<RuleExpr> {
|
||||||
let Expr { location, value } = template;
|
let Expr { location, value } = template;
|
||||||
match value {
|
match value {
|
||||||
Clause::Atom(_) | Clause::Name(_) | Clause::ExternFn(_) =>
|
Clause::Atom(_) | Clause::Name(_) | Clause::ExternFn(_) => {
|
||||||
vec![template.clone()],
|
vec![template.clone()]
|
||||||
|
},
|
||||||
Clause::S(c, body) => vec![Expr {
|
Clause::S(c, body) => vec![Expr {
|
||||||
location: location.clone(),
|
location: location.clone(),
|
||||||
value: Clause::S(*c, Rc::new(apply_exprv(body.as_slice(), state))),
|
value: Clause::S(*c, Rc::new(apply_exprv(body.as_slice(), state))),
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use crate::interpreted::{Clause, ExprInst};
|
|||||||
use crate::interpreter::HandlerTable;
|
use crate::interpreter::HandlerTable;
|
||||||
use crate::pipeline::file_loader::embed_to_map;
|
use crate::pipeline::file_loader::embed_to_map;
|
||||||
use crate::systems::codegen::call;
|
use crate::systems::codegen::call;
|
||||||
|
use crate::systems::stl::Numeric;
|
||||||
use crate::utils::poller::{PollEvent, Poller};
|
use crate::utils::poller::{PollEvent, Poller};
|
||||||
use crate::utils::unwrap_or;
|
use crate::utils::unwrap_or;
|
||||||
use crate::{ConstTree, Interner};
|
use crate::{ConstTree, Interner};
|
||||||
@@ -28,8 +29,8 @@ struct Timer {
|
|||||||
delay: NotNan<f64>,
|
delay: NotNan<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_timer(recurring: bool, delay: NotNan<f64>) -> XfnResult<Clause> {
|
pub fn set_timer(recurring: bool, delay: Numeric) -> XfnResult<Clause> {
|
||||||
Ok(init_cps(2, Timer { recurring, delay }))
|
Ok(init_cps(2, Timer { recurring, delay: delay.as_float() }))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -38,9 +39,7 @@ impl CancelTimer {
|
|||||||
pub fn new(f: impl Fn() + Send + 'static) -> Self {
|
pub fn new(f: impl Fn() + Send + 'static) -> Self {
|
||||||
Self(Arc::new(Mutex::new(f)))
|
Self(Arc::new(Mutex::new(f)))
|
||||||
}
|
}
|
||||||
pub fn cancel(&self) {
|
pub fn cancel(&self) { self.0.lock().unwrap()() }
|
||||||
self.0.lock().unwrap()()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl Debug for CancelTimer {
|
impl Debug for CancelTimer {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ pub fn tuple(data: impl IntoIterator<Item = ExprInst>) -> Clause {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{systems::codegen::tuple, foreign::Atomic};
|
use crate::foreign::Atomic;
|
||||||
|
use crate::systems::codegen::tuple;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tuple_printer() {
|
fn tuple_printer() {
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ use super::flow::IOCmdHandlePack;
|
|||||||
use super::instances::{BRead, ReadCmd, SRead, Sink, Source, WriteCmd};
|
use super::instances::{BRead, ReadCmd, SRead, Sink, Source, WriteCmd};
|
||||||
use crate::error::RuntimeError;
|
use crate::error::RuntimeError;
|
||||||
use crate::foreign::cps_box::init_cps;
|
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::interpreted::Clause;
|
||||||
use crate::representations::OrcString;
|
use crate::representations::OrcString;
|
||||||
use crate::systems::scheduler::SharedHandle;
|
use crate::systems::scheduler::SharedHandle;
|
||||||
use crate::systems::stl::Binary;
|
use crate::systems::stl::Binary;
|
||||||
use crate::{ConstTree, Interner, ast};
|
use crate::{ast, ConstTree, Interner};
|
||||||
|
|
||||||
type WriteHandle = SharedHandle<Sink>;
|
type WriteHandle = SharedHandle<Sink>;
|
||||||
type ReadHandle = SharedHandle<Source>;
|
type ReadHandle = SharedHandle<Source>;
|
||||||
@@ -62,9 +62,7 @@ pub fn io_bindings<'a>(
|
|||||||
]) + ConstTree::Tree(
|
]) + ConstTree::Tree(
|
||||||
std_streams
|
std_streams
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(n, at)| {
|
.map(|(n, at)| (i.i(n), ConstTree::clause(ast::Clause::Atom(Atom(at)))))
|
||||||
(i.i(n), ConstTree::clause(ast::Clause::Atom(Atom(at))))
|
|
||||||
})
|
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ use super::Canceller;
|
|||||||
use crate::interpreted::ExprInst;
|
use crate::interpreted::ExprInst;
|
||||||
|
|
||||||
pub type SyncResult<T> = (T, Box<dyn Any + Send>);
|
pub type SyncResult<T> = (T, Box<dyn Any + Send>);
|
||||||
|
/// Output from handlers contains the resource being processed and any Orchid
|
||||||
|
/// handlers executed as a result of the operation
|
||||||
|
pub type HandlerRes<T> = (T, Vec<ExprInst>);
|
||||||
pub type SyncOperation<T> =
|
pub type SyncOperation<T> =
|
||||||
Box<dyn FnOnce(T, Canceller) -> SyncResult<T> + Send>;
|
Box<dyn FnOnce(T, Canceller) -> SyncResult<T> + Send>;
|
||||||
pub type SyncOpResultHandler<T> = Box<
|
pub type SyncOpResultHandler<T> = Box<
|
||||||
dyn FnOnce(T, Box<dyn Any + Send>, Canceller) -> (T, Vec<ExprInst>)
|
dyn FnOnce(T, Box<dyn Any + Send>, Canceller) -> (T, Vec<ExprInst>) + Send,
|
||||||
|
|
||||||
+ Send,
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
struct SyncQueueItem<T> {
|
struct SyncQueueItem<T> {
|
||||||
@@ -43,10 +44,7 @@ pub struct BusyState<T> {
|
|||||||
}
|
}
|
||||||
impl<T> BusyState<T> {
|
impl<T> BusyState<T> {
|
||||||
pub fn new<U: 'static + Send>(
|
pub fn new<U: 'static + Send>(
|
||||||
handler: impl FnOnce(T, U, Canceller) -> (T, Vec<ExprInst>)
|
handler: impl FnOnce(T, U, Canceller) -> HandlerRes<T> + Send + 'static,
|
||||||
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
BusyState {
|
BusyState {
|
||||||
handler: Box::new(|t, payload, cancel| {
|
handler: Box::new(|t, payload, cancel| {
|
||||||
@@ -65,8 +63,8 @@ impl<T> BusyState<T> {
|
|||||||
pub fn enqueue<U: 'static + Send>(
|
pub fn enqueue<U: 'static + Send>(
|
||||||
&mut self,
|
&mut self,
|
||||||
operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static,
|
operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static,
|
||||||
handler: impl FnOnce(T, U, Canceller) -> (T, Vec<ExprInst>) + Send + 'static,
|
handler: impl FnOnce(T, U, Canceller) -> HandlerRes<T> + Send + 'static,
|
||||||
early_cancel: impl FnOnce(T) -> (T, Vec<ExprInst>) + Send + 'static,
|
early_cancel: impl FnOnce(T) -> HandlerRes<T> + Send + 'static,
|
||||||
) -> Option<Canceller> {
|
) -> Option<Canceller> {
|
||||||
if self.seal.is_some() {
|
if self.seal.is_some() {
|
||||||
return None;
|
return None;
|
||||||
@@ -80,28 +78,31 @@ impl<T> BusyState<T> {
|
|||||||
(t, Box::new(r))
|
(t, Box::new(r))
|
||||||
}),
|
}),
|
||||||
handler: Box::new(|t, u, c| {
|
handler: Box::new(|t, u, c| {
|
||||||
let u = u.downcast().expect("mismatched handler and operation");
|
let u: Box<U> = u.downcast().expect("mismatched handler and operation");
|
||||||
handler(t, *u, c)
|
handler(t, *u, c)
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
Some(cancelled)
|
Some(cancelled)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seal(&mut self, recipient: impl FnOnce(T) -> Vec<ExprInst> + Send + 'static) {
|
pub fn seal(
|
||||||
|
&mut self,
|
||||||
|
recipient: impl FnOnce(T) -> Vec<ExprInst> + Send + 'static,
|
||||||
|
) {
|
||||||
assert!(self.seal.is_none(), "Already sealed");
|
assert!(self.seal.is_none(), "Already sealed");
|
||||||
self.seal = Some(Box::new(recipient))
|
self.seal = Some(Box::new(recipient))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_sealed(&self) -> bool { self.seal.is_some() }
|
pub fn is_sealed(&self) -> bool { self.seal.is_some() }
|
||||||
|
|
||||||
pub fn rotate<U: Send + 'static>(
|
pub fn rotate(
|
||||||
mut self,
|
mut self,
|
||||||
instance: T,
|
instance: T,
|
||||||
result: U,
|
result: Box<dyn Any + Send>,
|
||||||
cancelled: Canceller,
|
cancelled: Canceller,
|
||||||
) -> NextItemReport<T> {
|
) -> NextItemReport<T> {
|
||||||
let (mut instance, mut events) =
|
let (mut instance, mut events) =
|
||||||
(self.handler)(instance, Box::new(result), cancelled);
|
(self.handler)(instance, result, cancelled);
|
||||||
let next_item = loop {
|
let next_item = loop {
|
||||||
if let Some(candidate) = self.queue.pop_front() {
|
if let Some(candidate) = self.queue.pop_front() {
|
||||||
if candidate.cancelled.is_cancelled() {
|
if candidate.cancelled.is_cancelled() {
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ mod busy;
|
|||||||
mod canceller;
|
mod canceller;
|
||||||
mod system;
|
mod system;
|
||||||
|
|
||||||
|
pub use busy::HandlerRes;
|
||||||
pub use canceller::Canceller;
|
pub use canceller::Canceller;
|
||||||
pub use system::{SealedOrTaken, SeqScheduler, SharedHandle, SharedState};
|
pub use system::{SealedOrTaken, SeqScheduler, SharedHandle, SharedState};
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use hashbrown::HashMap;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use trait_set::trait_set;
|
use trait_set::trait_set;
|
||||||
|
|
||||||
use super::busy::{BusyState, NextItemReportKind};
|
use super::busy::{BusyState, NextItemReportKind, SyncOperation};
|
||||||
use super::Canceller;
|
use super::{Canceller, HandlerRes};
|
||||||
use crate::error::AssertionError;
|
use crate::error::AssertionError;
|
||||||
use crate::facade::{IntoSystem, System};
|
use crate::facade::{IntoSystem, System};
|
||||||
use crate::foreign::cps_box::{init_cps, CPSBox};
|
use crate::foreign::cps_box::{init_cps, CPSBox};
|
||||||
@@ -80,13 +80,10 @@ impl<T> SharedHandle<T> {
|
|||||||
/// is to return values synchronously after they have been removed with
|
/// is to return values synchronously after they have been removed with
|
||||||
/// [SyncHandle::untake].
|
/// [SyncHandle::untake].
|
||||||
pub fn untake(&self, value: T) -> Result<(), T> {
|
pub fn untake(&self, value: T) -> Result<(), T> {
|
||||||
take_with_output(
|
take_with_output(&mut *self.0.lock().unwrap(), |state| match state {
|
||||||
&mut *self.0.lock().unwrap(),
|
SharedResource::Taken => (SharedResource::Free(value), Ok(())),
|
||||||
|state| match state {
|
_ => (state, Err(value)),
|
||||||
SharedResource::Taken => (SharedResource::Free(value), Ok(())),
|
})
|
||||||
_ => (state, Err(value)),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> Clone for SharedHandle<T> {
|
impl<T> Clone for SharedHandle<T> {
|
||||||
@@ -144,7 +141,7 @@ pub fn is_taken_error(x: ExprInst) -> XfnResult<bool> {
|
|||||||
trait_set! {
|
trait_set! {
|
||||||
/// The part of processing a blocking I/O task that cannot be done on a remote
|
/// 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.
|
/// thread, eg. because it accesses other systems or Orchid code.
|
||||||
trait NonSendFn = FnOnce(Box<dyn Any>, SeqScheduler) -> Vec<ExprInst>;
|
trait NonSendFn = FnOnce(Box<dyn Any + Send>, SeqScheduler) -> Vec<ExprInst>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SyncReply {
|
struct SyncReply {
|
||||||
@@ -198,9 +195,9 @@ impl SeqScheduler {
|
|||||||
pub fn schedule<T: Send + 'static, U: Send + 'static>(
|
pub fn schedule<T: Send + 'static, U: Send + 'static>(
|
||||||
&self,
|
&self,
|
||||||
handle: SharedHandle<T>,
|
handle: SharedHandle<T>,
|
||||||
operation: impl FnOnce(T, Canceller) -> (T, U) + Sync + Send + 'static,
|
operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static,
|
||||||
handler: impl FnOnce(T, U, Canceller) -> (T, Vec<ExprInst>) + Sync + Send + 'static,
|
handler: impl FnOnce(T, U, Canceller) -> HandlerRes<T> + Send + 'static,
|
||||||
early_cancel: impl FnOnce(T) -> (T, Vec<ExprInst>) + Sync + Send + 'static,
|
early_cancel: impl FnOnce(T) -> HandlerRes<T> + Send + 'static,
|
||||||
) -> Result<Canceller, SealedOrTaken> {
|
) -> Result<Canceller, SealedOrTaken> {
|
||||||
take_with_output(&mut *handle.0.lock().unwrap(), {
|
take_with_output(&mut *handle.0.lock().unwrap(), {
|
||||||
let handle = handle.clone();
|
let handle = handle.clone();
|
||||||
@@ -216,7 +213,11 @@ impl SeqScheduler {
|
|||||||
SharedResource::Free(t) => {
|
SharedResource::Free(t) => {
|
||||||
let cancelled = Canceller::new();
|
let cancelled = Canceller::new();
|
||||||
drop(early_cancel); // cannot possibly be useful
|
drop(early_cancel); // cannot possibly be useful
|
||||||
self.submit(t, handle, cancelled.clone(), operation);
|
let op_erased: SyncOperation<T> = 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))
|
(SharedResource::Busy(BusyState::new(handler)), Ok(cancelled))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -233,9 +234,11 @@ impl SeqScheduler {
|
|||||||
) -> Canceller {
|
) -> Canceller {
|
||||||
let cancelled = Canceller::new();
|
let cancelled = Canceller::new();
|
||||||
let canc1 = cancelled.clone();
|
let canc1 = cancelled.clone();
|
||||||
let opid = self.0.pending.borrow_mut().insert(Box::new(|data, _| {
|
let opid = self.0.pending.borrow_mut().insert(Box::new(
|
||||||
handler(*data.downcast().expect("This is associated by ID"), canc1)
|
|data: Box<dyn Any + Send>, _| {
|
||||||
}));
|
handler(*data.downcast().expect("This is associated by ID"), canc1)
|
||||||
|
},
|
||||||
|
));
|
||||||
let canc1 = cancelled.clone();
|
let canc1 = cancelled.clone();
|
||||||
let mut port = self.0.port.clone();
|
let mut port = self.0.port.clone();
|
||||||
self.0.pool.submit(Box::new(move || {
|
self.0.pool.submit(Box::new(move || {
|
||||||
@@ -251,18 +254,15 @@ impl SeqScheduler {
|
|||||||
handle: SharedHandle<T>,
|
handle: SharedHandle<T>,
|
||||||
seal: impl FnOnce(T) -> Vec<ExprInst> + Sync + Send + 'static,
|
seal: impl FnOnce(T) -> Vec<ExprInst> + Sync + Send + 'static,
|
||||||
) -> Result<Vec<ExprInst>, SealedOrTaken> {
|
) -> Result<Vec<ExprInst>, SealedOrTaken> {
|
||||||
take_with_output(
|
take_with_output(&mut *handle.0.lock().unwrap(), |state| match state {
|
||||||
&mut *handle.0.lock().unwrap(),
|
SharedResource::Busy(mut b) if !b.is_sealed() => {
|
||||||
|state| match state {
|
b.seal(seal);
|
||||||
SharedResource::Busy(mut b) if !b.is_sealed() => {
|
(SharedResource::Busy(b), Ok(Vec::new()))
|
||||||
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))),
|
|
||||||
},
|
},
|
||||||
)
|
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
|
/// 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
|
/// from the callback passed to the [AsynchSystem] so that if the task is
|
||||||
/// never resolved but the [AsynchSystem] through which the resolving event
|
/// never resolved but the [AsynchSystem] through which the resolving event
|
||||||
/// would arrive is dropped this [SeqScheduler] is also dropped.
|
/// would arrive is dropped this [SeqScheduler] is also dropped.
|
||||||
fn submit<T: Send + 'static, U: Send + 'static>(
|
fn submit<T: Send + 'static>(
|
||||||
&self,
|
&self,
|
||||||
t: T,
|
t: T,
|
||||||
handle: SharedHandle<T>,
|
handle: SharedHandle<T>,
|
||||||
cancelled: Canceller,
|
cancelled: Canceller,
|
||||||
operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static,
|
operation: SyncOperation<T>,
|
||||||
) {
|
) {
|
||||||
// referenced by self until run, references handle
|
// referenced by self until run, references handle
|
||||||
let opid = self.0.pending.borrow_mut().insert(Box::new({
|
let opid = self.0.pending.borrow_mut().insert(Box::new({
|
||||||
let cancelled = cancelled.clone();
|
let cancelled = cancelled.clone();
|
||||||
move |data, this| {
|
move |data: Box<dyn Any + Send>, this: SeqScheduler| {
|
||||||
let (t, u): (T, U) =
|
let (t, u): (T, Box<dyn Any + Send>) =
|
||||||
*data.downcast().expect("This is associated by ID");
|
*data.downcast().expect("This is associated by ID");
|
||||||
let handle2 = handle.clone();
|
let handle2 = handle.clone();
|
||||||
take_with_output(&mut *handle.0.lock().unwrap(), |state| {
|
take_with_output(&mut *handle.0.lock().unwrap(), |state| {
|
||||||
|
|||||||
@@ -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::interner::Interner;
|
||||||
use crate::representations::interpreted::Clause;
|
use crate::representations::interpreted::Clause;
|
||||||
use crate::error::AssertionError;
|
|
||||||
use crate::{ConstTree, Location, OrcString};
|
use crate::{ConstTree, Location, OrcString};
|
||||||
|
|
||||||
use super::Numeric;
|
|
||||||
|
|
||||||
/// Takes a boolean and two branches, runs the first if the bool is true, the
|
/// Takes a boolean and two branches, runs the first if the bool is true, the
|
||||||
/// second if it's false.
|
/// second if it's false.
|
||||||
// Even though it's a ternary function, IfThenElse is implemented as an unary
|
// 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<Clause> {
|
|||||||
/// - both are bool,
|
/// - both are bool,
|
||||||
/// - both are either uint or num
|
/// - both are either uint or num
|
||||||
pub fn equals(a: Atom, b: Atom) -> XfnResult<bool> {
|
pub fn equals(a: Atom, b: Atom) -> XfnResult<bool> {
|
||||||
let (a, b) = match (a.try_downcast::<OrcString>(), b.try_downcast::<OrcString>()) {
|
let (a, b) =
|
||||||
(Ok(a), Ok(b)) => return Ok(a == b),
|
match (a.try_downcast::<OrcString>(), b.try_downcast::<OrcString>()) {
|
||||||
(Err(a), Err(b)) => (a, b),
|
(Ok(a), Ok(b)) => return Ok(a == b),
|
||||||
_ => return Ok(false),
|
(Err(a), Err(b)) => (a, b),
|
||||||
};
|
_ => return Ok(false),
|
||||||
|
};
|
||||||
match (a.request::<Numeric>(), b.request::<Numeric>()) {
|
match (a.request::<Numeric>(), b.request::<Numeric>()) {
|
||||||
(Some(a), Some(b)) => return Ok(a.as_float() == b.as_float()),
|
(Some(a), Some(b)) => return Ok(a.as_float() == b.as_float()),
|
||||||
(None, None) => (),
|
(None, None) => (),
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import std::panic
|
|||||||
|
|
||||||
-- utilities for using lists as pairs
|
-- utilities for using lists as pairs
|
||||||
|
|
||||||
export const fst := \l. (
|
const fst := \l. (
|
||||||
list::get l 0
|
list::get l 0
|
||||||
(panic "nonempty expected")
|
(panic "nonempty expected")
|
||||||
\x.x
|
\x.x
|
||||||
)
|
)
|
||||||
export const snd := \l. (
|
const snd := \l. (
|
||||||
list::get l 1
|
list::get l 1
|
||||||
(panic "2 elements expected")
|
(panic "2 elements expected")
|
||||||
\x.x
|
\x.x
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ mod arithmetic_error;
|
|||||||
mod binary;
|
mod binary;
|
||||||
mod bool;
|
mod bool;
|
||||||
mod conv;
|
mod conv;
|
||||||
|
mod exit_status;
|
||||||
mod inspect;
|
mod inspect;
|
||||||
mod number;
|
mod number;
|
||||||
mod panic;
|
mod panic;
|
||||||
mod state;
|
mod state;
|
||||||
mod stl_system;
|
mod stl_system;
|
||||||
mod string;
|
mod string;
|
||||||
mod exit_status;
|
|
||||||
pub use arithmetic_error::ArithmeticError;
|
pub use arithmetic_error::ArithmeticError;
|
||||||
pub use binary::Binary;
|
pub use binary::Binary;
|
||||||
|
pub use exit_status::ExitStatus;
|
||||||
pub use number::Numeric;
|
pub use number::Numeric;
|
||||||
pub use stl_system::StlConfig;
|
pub use stl_system::StlConfig;
|
||||||
pub use exit_status::ExitStatus;
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use ordered_float::NotNan;
|
|||||||
|
|
||||||
use super::ArithmeticError;
|
use super::ArithmeticError;
|
||||||
use crate::error::AssertionError;
|
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::interpreted::TryFromExprInst;
|
||||||
use crate::representations::interpreted::{Clause, ExprInst};
|
use crate::representations::interpreted::{Clause, ExprInst};
|
||||||
use crate::{ConstTree, Interner, Location};
|
use crate::{ConstTree, Interner, Location};
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ pub fn pushed_ref<'a, T: Clone + 'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Pure version of [Iterator::next]
|
/// Pure version of [Iterator::next]
|
||||||
///
|
///
|
||||||
/// Remove an item from the iterator. If successful, returns the item and the
|
/// Remove an item from the iterator. If successful, returns the item and the
|
||||||
/// iterator. If the iterator is empty it is consumed.
|
/// iterator. If the iterator is empty it is consumed.
|
||||||
pub fn next<I: Iterator>(mut i: I) -> Option<(I::Item, I)> {
|
pub fn next<I: Iterator>(mut i: I) -> Option<(I::Item, I)> {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::{rc::Rc, sync::Arc};
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub fn rc_to_owned<T: Clone>(rc: Rc<T>) -> T {
|
pub fn rc_to_owned<T: Clone>(rc: Rc<T>) -> T {
|
||||||
Rc::try_unwrap(rc).unwrap_or_else(|rc| rc.as_ref().clone())
|
Rc::try_unwrap(rc).unwrap_or_else(|rc| rc.as_ref().clone())
|
||||||
|
|||||||
Reference in New Issue
Block a user