use crate::error::Result;
use crate::format::*;
use super::RuntimeContext;
pub trait RuntimeExecutor: Send + Sync {
fn handle_marker(
&mut self,
_ctx: &mut RuntimeContext,
_marker: &LineMarker,
) -> Result<()> {
Ok(())
}
fn handle_command(
&mut self,
ctx: &mut RuntimeContext,
command_line: &ResolvedCommandLine,
) -> Result<bool>;
fn handle_extra_system_call(
&mut self,
ctx: &mut RuntimeContext,
systemcall_line: &ResolvedSystemCallLine,
) -> Result<bool>;
fn handle_text(
&mut self,
ctx: &mut RuntimeContext,
leading: Option<&str>,
text: Option<&str>,
tailing: Option<&str>,
) -> Result<bool>;
fn finished(&mut self, ctx: &mut RuntimeContext);
fn get_variable<'a>(
&self,
ctx: &'a RuntimeContext,
value: &'a Variable,
) -> Result<&'a Literal> {
if value.chain.len() == 1 {
let name = &value.chain[0];
if let Some(value) = ctx.get_local(name) {
return Ok(value);
}
if let Some(value) = ctx.archive_variables().as_object()?.get(name) {
return Ok(value);
}
if let Some(value) = ctx.global_variables().as_object()?.get(name) {
return Ok(value);
}
} else {
log::warn!(
"Variable chain with more than one element is not supported: {:?}",
value.chain
);
}
Ok(&Literal::Null)
}
fn calculate_template_literal<'a>(
&self,
ctx: &'a RuntimeContext,
template: &'a crate::format::TemplateLiteral,
) -> Result<String> {
let text = template
.parts
.iter()
.map(|part| match part {
crate::format::TemplateLiteralPart::Text(text) => text.to_owned(),
crate::format::TemplateLiteralPart::Value(value) => {
match self.get_rvalue(ctx, value) {
Ok(v) => v.to_string(),
Err(err) => {
log::error!(
"Failed to get rvalue from template literal: {:?}.\
Error: {:?}",
value,
err
);
"[Error]".to_string()
}
}
}
})
.collect::<String>();
Ok(text)
}
fn get_rvalue<'a>(&self, ctx: &'a RuntimeContext, value: &'a RValue) -> Result<&'a Literal> {
match value {
RValue::Literal(s) => Ok(s),
RValue::Variable(v) => self.get_variable(ctx, v),
}
}
}