use super::format_arg;
use endbasic_core::*;
use std::borrow::Cow;
use std::cell::RefCell;
use std::rc::Rc;
pub(super) struct OutCommand {
metadata: Rc<CallableMetadata>,
output: Rc<RefCell<String>>,
}
impl OutCommand {
pub(super) fn new(output: Rc<RefCell<String>>) -> Rc<Self> {
Rc::from(Self {
metadata: CallableMetadataBuilder::new("OUT")
.with_syntax(&[(
&[],
Some(&RepeatedSyntax {
name: Cow::Borrowed("arg"),
type_syn: RepeatedTypeSyntax::AnyValue,
sep: ArgSepSyntax::OneOf(&[ArgSep::As, ArgSep::Long, ArgSep::Short]),
require_one: false,
allow_missing: true,
}),
)])
.test_build(),
output,
})
}
}
impl Callable for OutCommand {
fn metadata(&self) -> Rc<CallableMetadata> {
self.metadata.clone()
}
fn exec(&self, scope: Scope<'_>) -> CallResult<()> {
let mut line = String::new();
let mut argi = 0;
let mut reg = 0;
loop {
let sep = match scope.get_type(reg) {
VarArgTag::Immediate(sep, etype) => {
reg += 1;
let formatted = format_arg(&scope, reg, etype);
line.push_str(&format!("{}={}{}", argi, formatted, etype.annotation()));
sep
}
VarArgTag::Missing(sep) => {
line.push_str(&format!("{}=()", argi));
sep
}
VarArgTag::Pointer(sep) => {
reg += 1;
let typed_ptr = scope.get_ref(reg);
line.push_str(&format!("{}={}", argi, typed_ptr));
sep
}
};
argi += 1;
reg += 1;
if sep == ArgSep::End {
break;
}
line.push(' ');
line.push_str(&sep.to_string());
line.push(' ');
}
let mut output = self.output.borrow_mut();
output.push_str(&line);
output.push('\n');
Ok(())
}
}