Shared Rust kernels
catalogue/logical
All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.
logicals · 18 lines · calc-func/src/catalogue/logical.rs on GitHub/// An eager named call that takes 1 to `most` logicals, values or references, the last parameter
/// repeating.
const fn logicals(
id: FunctionId,
spelling: &'static str,
most: usize,
kernel: EagerKernel,
) -> CatalogueEntry {
CatalogueEntry {
id,
spelling,
notation: Notation::Call,
arity: CallableArityShape::range(1, most),
parameters: LOGICALS,
demand: ArgumentDemand::Eager,
kernel: Kernel::Eager(kernel),
}
}
Used by 3 functions.
constant · 12 lines · calc-func/src/catalogue/logical.rs on GitHub/// An eager named call that takes no argument.
const fn constant(id: FunctionId, spelling: &'static str, kernel: EagerKernel) -> CatalogueEntry {
CatalogueEntry {
id,
spelling,
notation: Notation::Call,
arity: CallableArityShape::exact(0),
parameters: &[],
demand: ArgumentDemand::Eager,
kernel: Kernel::Eager(kernel),
}
}
Used by 2 functions.
decide · 17 lines · calc-func/src/catalogue/logical.rs on GitHub/// The result of the entry `id` on `arguments`: the first error met in the reading order, #VALUE!
/// when no logical is read, and otherwise the logical `rule` gives the tally.
fn decide(
id: FunctionId,
arguments: &[CalcValue],
services: &mut EvalServices<'_>,
rule: fn(&Tally) -> bool,
) -> Result<CalcValue, FunctionFault> {
let site = Site::new(id, services);
Site::finish(tally(&site, arguments, services).and_then(|tally| {
if tally.logicals == 0 {
Err(Exit::Error(WorksheetErrorCode::Value))
} else {
Ok(CalcValue::logical(rule(&tally)))
}
}))
}
Used by 3 functions.
tally · 37 lines · calc-func/src/catalogue/logical.rs on GitHub/// Reads every argument in the two passes of the module documentation and counts the logicals;
/// stops at the first error or refusal.
fn tally(site: &Site<'_>, arguments: &[CalcValue], services: &mut EvalServices<'_>) -> Step<Tally> {
let mut tally = Tally::default();
let mut take = |logical: Option<bool>| {
if let Some(logical) = logical {
tally.logicals += 1;
tally.trues += u64::from(logical);
}
};
for (index, argument) in arguments.iter().enumerate() {
if !matches!(
argument.core_ref(),
CoreRef::Reference(_) | CoreRef::Array(_)
) {
take(direct(site, index, argument)?);
}
}
for (index, argument) in arguments.iter().enumerate() {
match argument.core_ref() {
CoreRef::Reference(reference) => {
let cells = reader(site, services, index)?;
read_reference(site, cells, reference, index, &mut |_, _, value| {
take(held(site, index, value)?);
Ok(())
})?;
}
CoreRef::Array(array) => {
for element in array.iter_row_major() {
take(held(site, index, element)?);
}
}
_ => {}
}
}
Ok(tally)
}
Used by 3 functions.
direct · 14 lines · calc-func/src/catalogue/logical.rs on GitHub/// A direct argument, at `index`, as a logical, or `None` when it is skipped.
fn direct(site: &Site<'_>, index: usize, value: &CalcValue) -> Step<Option<bool>> {
not_callable(site, index, value)?;
match value.core_ref() {
CoreRef::Number(n) => site
.argument(index, coerce::operand(n))
.map(|n| Some(n != 0.0)),
CoreRef::Logical(b) => Ok(Some(b)),
CoreRef::Text(text) => Ok(coerce::spelled_logical(text)),
CoreRef::Missing | CoreRef::Empty => Ok(Some(false)),
CoreRef::Error(code) => Err(Exit::Error(code)),
CoreRef::Array(_) | CoreRef::Reference(_) => Err(site.not_modelled(Some(index))),
}
}
Used by 3 functions.
held · 14 lines · calc-func/src/catalogue/logical.rs on GitHub/// A value that a reference or an array at `index` holds, as a logical, or `None` when it is
/// skipped.
fn held(site: &Site<'_>, index: usize, value: &CalcValue) -> Step<Option<bool>> {
not_callable(site, index, value)?;
match value.core_ref() {
CoreRef::Number(n) => site
.argument(index, coerce::operand(n))
.map(|n| Some(n != 0.0)),
CoreRef::Logical(b) => Ok(Some(b)),
CoreRef::Text(_) | CoreRef::Empty | CoreRef::Missing => Ok(None),
CoreRef::Error(code) => Err(Exit::Error(code)),
CoreRef::Array(_) | CoreRef::Reference(_) => Err(site.not_modelled(Some(index))),
}
}
Used by 3 functions.
not_callable · 9 lines · calc-func/src/catalogue/logical.rs on GitHub/// Refuses a callable at `index` as not modelled: its worksheet-visible core is #CALC!, but it is
/// no worksheet error until it reaches a cell.
fn not_callable(site: &Site<'_>, index: usize, value: &CalcValue) -> Step<()> {
if value.callable_value().is_some() {
Err(site.not_modelled(Some(index)))
} else {
Ok(())
}
}
Used by 4 functions.