use endbasic_core::*;
use std::borrow::Cow;
use std::rc::Rc;
pub(super) struct SumDoublesFunction {
metadata: Rc<CallableMetadata>,
}
impl SumDoublesFunction {
pub(super) fn new() -> Rc<Self> {
Rc::from(Self {
metadata: CallableMetadataBuilder::new("SUM_DOUBLES")
.with_return_type(ExprType::Double)
.with_syntax(&[(
&[],
Some(&RepeatedSyntax {
name: Cow::Borrowed("arg"),
type_syn: RepeatedTypeSyntax::AnyValue,
sep: ArgSepSyntax::Exactly(ArgSep::Long),
require_one: false,
allow_missing: true,
}),
)])
.test_build(),
})
}
}
impl Callable for SumDoublesFunction {
fn metadata(&self) -> Rc<CallableMetadata> {
self.metadata.clone()
}
fn exec(&self, scope: Scope<'_>) -> CallResult<()> {
let mut total = 0.0;
let mut reg = 0;
loop {
let sep = match scope.get_type(reg) {
VarArgTag::Immediate(sep, etype) => {
reg += 1;
match etype {
ExprType::Double => total += scope.get_double(reg),
ExprType::Integer => total += f64::from(scope.get_integer(reg)),
_ => {
return Err(CallError::Argument(
"Only accepts numerical values".to_owned(),
));
}
}
sep
}
_ => {
return Err(CallError::Argument("Only accepts numerical values".to_owned()));
}
};
reg += 1;
if sep == ArgSep::End {
break;
}
}
scope.return_double(total)
}
}