use crate::data::{
ast::*, literal::ContentType, message::*, msg::send_msg, primitive::null::PrimitiveNull, Data,
Literal, Memories, MemoryType, MessageData, MSG,
};
use crate::error_format::*;
use crate::interpreter::{
interpret_scope,
variable_handler::{
exec_path_actions, expr_to_literal, get_var_from_mem, interval::*, memory::*,
},
};
use crate::parser::ExitCondition;
use std::sync::mpsc;
fn get_var_info<'a>(
expr: &'a Expr,
path: Option<&[(Interval, PathState)]>,
data: &'a mut Data,
root: &mut MessageData,
sender: &Option<mpsc::Sender<MSG>>,
) -> Result<
(
&'a mut Literal,
String,
MemoryType,
Option<Vec<(Interval, PathLiteral)>>,
),
ErrorInfo,
> {
match expr {
Expr::PathExpr { literal, path } => get_var_info(literal, Some(path), data, root, sender),
Expr::IdentExpr(var) => match search_in_memory_type(var, data) {
Ok(_) => get_var_from_mem(var.to_owned(), path, data, root, sender),
Err(_) => {
let lit = PrimitiveNull::get_literal(var.interval.to_owned());
data.step_vars.insert(var.ident.to_owned(), lit);
get_var_from_mem(var.to_owned(), path, data, root, sender)
}
},
e => Err(gen_error_info(
interval_from_expr(e),
ERROR_GET_VAR_INFO.to_owned(),
)),
}
}
pub fn match_actions(
function: &ObjectType,
mut root: MessageData,
data: &mut Data,
instruction_index: Option<usize>,
sender: &Option<mpsc::Sender<MSG>>,
) -> Result<MessageData, ErrorInfo> {
match function {
ObjectType::Say(arg) => {
let msg = Message::new(expr_to_literal(arg, None, data, &mut root, sender)?);
send_msg(&sender, MSG::Message(msg.clone()));
Ok(Message::add_to_message(root, MessageType::Msg(msg)))
}
ObjectType::Use(arg) => {
expr_to_literal(arg, None, data, &mut root, sender)?;
Ok(root)
}
ObjectType::Do(DoType::Update(old, new)) => {
let new_value = expr_to_literal(new, None, data, &mut root, sender)?;
let (lit, name, mem_type, path) = get_var_info(old, None, data, &mut root, sender)?;
exec_path_actions(lit, Some(new_value), &path, &ContentType::get(&lit))?;
save_literal_in_mem(
lit.to_owned(),
name,
&mem_type,
true,
data,
&mut root,
sender,
);
Ok(root)
}
ObjectType::Do(DoType::Exec(expr)) => {
expr_to_literal(expr, None, data, &mut root, sender)?;
Ok(root)
}
ObjectType::Goto(GotoType::Step, step_name) => {
send_msg(&sender, MSG::NextStep(step_name.ident.clone()));
root.exit_condition = Some(ExitCondition::Goto);
Ok(root.add_next_step(&step_name.ident))
}
ObjectType::Goto(GotoType::Flow, flow_name) => {
send_msg(&sender, MSG::NextFlow(flow_name.ident.clone()));
root.exit_condition = Some(ExitCondition::Goto);
Ok(root.add_next_flow(&flow_name.ident))
}
ObjectType::Remember(name, variable) => {
let lit = expr_to_literal(variable, None, data, &mut root, sender)?;
root.add_to_memory(&name.ident, lit.clone());
send_msg(
&sender,
MSG::Memorie(Memories::new(name.ident.to_owned(), lit.clone())),
);
data.context.current.insert(name.ident.to_owned(), lit);
Ok(root)
}
ObjectType::Import {
step_name: name, ..
} => {
if let Some(Expr::Scope { scope: actions, .. }) = data
.ast
.flow_instructions
.get(&InstructionType::NormalStep(name.ident.to_owned()))
{
match interpret_scope(actions, data, instruction_index, sender) {
Ok(root2) => Ok(root + root2),
Err(err) => Err(gen_error_info(
interval_from_reserved_fn(function),
format!("{} {:?}", ERROR_IMPORT_FAIL, err),
)),
}
} else {
Err(gen_error_info(
interval_from_reserved_fn(function),
format!("{} {}", name.ident, ERROR_IMPORT_STEP_FLOW),
))
}
}
reserved => Err(gen_error_info(
interval_from_reserved_fn(reserved),
ERROR_START_INSTRUCTIONS.to_owned(),
)),
}
}