use crate::builder::*;
use crate::handler::*;
use crate::*;
use std::cell::{Ref, RefCell};
use std::collections::{BTreeMap, BTreeSet};
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
#[derive(Clone, Debug, thiserror::Error)]
pub enum HandlerBuilderError<CE> {
#[error("BuilderHandler: Routine {0} already exists")]
RoutineAlreadyExists(String),
#[error("BuilderHandler: Routine {0} not found")]
RoutineNotFound(String),
#[error("BuilderHandler: IndirectJump {0} already exists")]
IndJumpAlreadyExists(String),
#[error("BuilderHandler: IndirectJump {0} not found")]
IndJumpNotFound(String),
#[error("BuilderHandler: LongDataHandler {0} already exists")]
LongDataHandlerAlreadyExists(String),
#[error("BuilderHandler: LongDataHandler {0} not found")]
LongDataHandlerNotFound(String),
#[error("BuilderHandler: LongDataError: {0}")]
LongDataError(LongDataSetError),
#[error("BuilderHandler: DataHandler {0} already exists")]
DataHandlerAlreadyExists(String),
#[error("BuilderHandler: DataHandler {0} not found")]
DataHandlerNotFound(String),
#[error("LDHStartsDefined")]
LDHStartsDefined,
#[error("BuilderHandler: Internal: {0}")]
Internal(#[from] CE),
}
pub struct HandlerBuilder<Builder, Label, Instr, PutInstr> {
pub b: Builder,
routine_map: Rc<RefCell<BTreeMap<String, (RefCell<RoutineHandler<Label>>, Rc<RefCell<Self>>)>>>,
ma_return_bits: Option<usize>,
tb_return_bits: Option<usize>,
indjump_map: Rc<RefCell<BTreeMap<String, IndirectJumpHandler<Label>>>>,
longdata_handler_map: Rc<RefCell<BTreeMap<String, RefCell<LongDataHandler<Label>>>>>,
data_handler_map: Rc<RefCell<BTreeMap<String, DataHandler<Label>>>>,
ma_ldh_check_name_base: Option<Label>,
tb_ldh_check_name_base: Option<Label>,
ldh_usage: BTreeSet<String>,
ldh_starts: Vec<Label>,
sep: Label,
_phpi: std::marker::PhantomData<PutInstr>,
_phi: std::marker::PhantomData<Instr>,
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum HandlerBuilderSkipError<BAE> {
#[error("HandlerBuilder: No return bits set")]
NoReturnBitsSet,
#[error("HandlerBuilder: BuilderError {0}")]
BuilderError(#[from] BAE),
}
impl<Builder: Default, Label, Instr, PutInstr> Default
for HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<Label> + From<String> + DefaultSep + std::fmt::Display,
MinInfRel<Label>: From<Label>,
{
fn default() -> Self {
Self::new(Builder::default(), None, None)
}
}
fn ldh_check_name<Label>(
ldh: &LongDataHandler<Label>,
sep: &Label,
ldh_check_name_base: &Label,
) -> Label
where
Label: Clone + From<Label> + From<String> + std::fmt::Display + LabelJoin,
{
let mut name = ldh_check_name_base.clone();
name.label_join(&sep);
name.label_join(ldh.name());
name
}
fn ldh_check_name2<Label>(ldh_name: &String, sep: &Label, ldh_check_name_base: &Label) -> Label
where
Label: Clone + From<Label> + From<String> + std::fmt::Display + LabelJoin,
{
let mut name = ldh_check_name_base.clone();
name.label_join(&sep);
name.label_join(&Label::from(ldh_name.clone()));
name
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<Label> + From<String> + DefaultSep + std::fmt::Display,
MinInfRel<Label>: From<Label>,
{
pub fn new(b: Builder, ma_return_bits: Option<usize>, tb_return_bits: Option<usize>) -> Self {
Self {
b,
routine_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_return_bits,
tb_return_bits,
indjump_map: Rc::new(RefCell::new(BTreeMap::new())),
longdata_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
data_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_ldh_check_name_base: None,
tb_ldh_check_name_base: None,
ldh_usage: BTreeSet::new(),
ldh_starts: vec![],
sep: Label::default_sep(),
_phpi: std::marker::PhantomData,
_phi: std::marker::PhantomData,
}
}
pub fn new_safe_ldh<L>(
b: Builder,
ma_return_bits: Option<usize>,
tb_return_bits: Option<usize>,
ma_ldh_check_name_base: Option<L>,
tb_ldh_check_name_base: Option<L>,
) -> Self
where
Label: From<L>,
{
Self {
b,
routine_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_return_bits,
tb_return_bits,
indjump_map: Rc::new(RefCell::new(BTreeMap::new())),
longdata_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
data_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_ldh_check_name_base: ma_ldh_check_name_base.map(|l| l.into()),
tb_ldh_check_name_base: tb_ldh_check_name_base.map(|l| l.into()),
ldh_usage: BTreeSet::new(),
ldh_starts: vec![],
sep: Label::default_sep(),
_phpi: std::marker::PhantomData,
_phi: std::marker::PhantomData,
}
}
pub fn new_1(b: Builder, return_bits: Option<usize>) -> Self {
Self {
b,
routine_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_return_bits: return_bits,
tb_return_bits: return_bits,
indjump_map: Rc::new(RefCell::new(BTreeMap::new())),
longdata_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
data_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_ldh_check_name_base: None,
tb_ldh_check_name_base: None,
ldh_usage: BTreeSet::new(),
ldh_starts: vec![],
sep: Label::default_sep(),
_phpi: std::marker::PhantomData,
_phi: std::marker::PhantomData,
}
}
pub fn new_1_safe_ldh<L>(
b: Builder,
return_bits: Option<usize>,
ma_ldh_check_name_base: Option<L>,
tb_ldh_check_name_base: Option<L>,
) -> Self
where
Label: From<L>,
{
Self {
b,
routine_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_return_bits: return_bits,
tb_return_bits: return_bits,
indjump_map: Rc::new(RefCell::new(BTreeMap::new())),
longdata_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
data_handler_map: Rc::new(RefCell::new(BTreeMap::new())),
ma_ldh_check_name_base: ma_ldh_check_name_base.map(|l| l.into()),
tb_ldh_check_name_base: tb_ldh_check_name_base.map(|l| l.into()),
ldh_usage: BTreeSet::new(),
ldh_starts: vec![],
sep: Label::default_sep(),
_phpi: std::marker::PhantomData,
_phi: std::marker::PhantomData,
}
}
fn new_with_routine_map(&self, b: Builder, routine_labels: Vec<Label>) -> Self {
Self {
b,
routine_map: self.routine_map.clone(),
ma_return_bits: self.ma_return_bits,
tb_return_bits: self.tb_return_bits,
indjump_map: self.indjump_map.clone(),
longdata_handler_map: self.longdata_handler_map.clone(),
data_handler_map: self.data_handler_map.clone(),
ma_ldh_check_name_base: self.ma_ldh_check_name_base.clone(),
tb_ldh_check_name_base: self.tb_ldh_check_name_base.clone(),
ldh_usage: BTreeSet::new(),
ldh_starts: routine_labels.to_vec(),
sep: Label::default_sep(),
_phpi: std::marker::PhantomData,
_phi: std::marker::PhantomData,
}
}
fn new_with_builder(&self, b: Builder) -> Self {
Self {
b,
routine_map: self.routine_map.clone(),
ma_return_bits: self.ma_return_bits,
tb_return_bits: self.tb_return_bits,
indjump_map: self.indjump_map.clone(),
longdata_handler_map: self.longdata_handler_map.clone(),
data_handler_map: self.data_handler_map.clone(),
ma_ldh_check_name_base: self.ma_ldh_check_name_base.clone(),
tb_ldh_check_name_base: self.tb_ldh_check_name_base.clone(),
ldh_usage: BTreeSet::new(),
ldh_starts: vec![],
sep: Label::default_sep(),
_phpi: std::marker::PhantomData,
_phi: std::marker::PhantomData,
}
}
pub fn ma_return_bits(&self) -> Option<usize> {
self.ma_return_bits
}
pub fn tb_return_bits(&self) -> Option<usize> {
self.tb_return_bits
}
pub fn routine_map(
&self,
) -> Ref<'_, BTreeMap<String, (RefCell<RoutineHandler<Label>>, Rc<RefCell<Self>>)>> {
self.routine_map.borrow()
}
pub fn indjump_map(&self) -> Ref<'_, BTreeMap<String, IndirectJumpHandler<Label>>> {
self.indjump_map.borrow()
}
pub fn longdata_handler_map(
&self,
) -> Ref<'_, BTreeMap<String, RefCell<LongDataHandler<Label>>>> {
self.longdata_handler_map.borrow()
}
pub fn data_handler_map(&self) -> Ref<'_, BTreeMap<String, DataHandler<Label>>> {
self.data_handler_map.borrow()
}
pub fn try_routine_handler(
&self,
name: &str,
) -> Result<Ref<'_, RefCell<RoutineHandler<Label>>>, HandlerBuilderError<()>> {
if let Some(rh) = Ref::filter_map(self.routine_map.borrow(), |rm| {
rm.get(name).map(|(rh, _)| rh)
})
.ok()
{
Ok(rh)
} else {
Err(HandlerBuilderError::RoutineNotFound(name.to_string()))
}
}
pub fn routine_handler(&self, name: &str) -> Ref<'_, RefCell<RoutineHandler<Label>>> {
self.try_routine_handler(name).unwrap()
}
pub fn try_longdata_handler(
&self,
name: &str,
) -> Result<Ref<'_, RefCell<LongDataHandler<Label>>>, HandlerBuilderError<()>> {
if let Some(ldh) =
Ref::filter_map(self.longdata_handler_map.borrow(), |ldm| ldm.get(name)).ok()
{
Ok(ldh)
} else {
Err(HandlerBuilderError::LongDataHandlerNotFound(
name.to_string(),
))
}
}
pub fn longdata_handler(&self, name: &str) -> Ref<'_, RefCell<LongDataHandler<Label>>> {
self.try_longdata_handler(name).unwrap()
}
pub fn try_add_indjump<I: IntoIterator<Item = Label>>(
&mut self,
name: &str,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Result<(), HandlerBuilderError<()>> {
let mut indjump_map = self.indjump_map.borrow_mut();
if indjump_map.contains_key(name) {
return Err(HandlerBuilderError::IndJumpAlreadyExists(name.to_string()));
}
indjump_map.insert(
name.to_string(),
IndirectJumpHandler::new(name, labels, temp_buffer, reuse),
);
Ok(())
}
pub fn add_indjump<I: IntoIterator<Item = Label>>(
&mut self,
name: &str,
labels: I,
temp_buffer: bool,
reuse: bool,
) {
self.try_add_indjump(name, labels, temp_buffer, reuse)
.unwrap();
}
pub fn try_add_indjump_l<L: Clone, I: IntoIterator<Item = Label>>(
&mut self,
name: L,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Result<(), HandlerBuilderError<()>>
where
Label: Clone + std::fmt::Display + From<L>,
{
let name_s = Label::from(name.clone()).to_string();
let mut indjump_map = self.indjump_map.borrow_mut();
if indjump_map.contains_key(&name_s) {
return Err(HandlerBuilderError::IndJumpAlreadyExists(name_s));
}
indjump_map.insert(
name_s,
IndirectJumpHandler::new_l(name, labels, temp_buffer, reuse),
);
Ok(())
}
pub fn add_indjump_l<L: Clone, I: IntoIterator<Item = Label>>(
&mut self,
name: L,
labels: I,
temp_buffer: bool,
reuse: bool,
) where
Label: Clone + std::fmt::Display + From<L>,
{
self.try_add_indjump_l(name, labels, temp_buffer, reuse)
.unwrap();
}
pub fn try_add_indjump_ll<L: Clone, L2, I: IntoIterator<Item = L2>>(
&mut self,
name: L,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Result<(), HandlerBuilderError<()>>
where
Label: Clone + std::fmt::Display + From<L> + From<L2>,
{
let name_s = Label::from(name.clone()).to_string();
let mut indjump_map = self.indjump_map.borrow_mut();
if indjump_map.contains_key(&name_s) {
return Err(HandlerBuilderError::IndJumpAlreadyExists(name_s));
}
indjump_map.insert(
name_s,
IndirectJumpHandler::new_ll(name, labels, temp_buffer, reuse),
);
Ok(())
}
pub fn add_indjump_ll<L: Clone, L2, I: IntoIterator<Item = L2>>(
&mut self,
name: L,
labels: I,
temp_buffer: bool,
reuse: bool,
) where
Label: Clone + std::fmt::Display + From<L> + From<L2>,
{
self.try_add_indjump_ll(name, labels, temp_buffer, reuse)
.unwrap();
}
pub fn try_indjump(&self, name: &str) -> Result<Label, HandlerBuilderError<()>> {
if let Some(indjump) = self.indjump_map.borrow().get(name) {
Ok(indjump.ind_jump())
} else {
Err(HandlerBuilderError::IndJumpNotFound(name.to_string()))
}
}
pub fn indjump(&self, name: &str) -> Label {
self.try_indjump(name).unwrap()
}
pub fn has_indjump(&self, name: &str) -> bool {
self.indjump_map.borrow().contains_key(name)
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<Label> + From<String> + std::fmt::Display,
MinInfRel<Label>: From<Label>,
Builder: MinInfBuilderTrait<Label, PutInstr>
+ MinInfLabelTrait<Label>
+ MinInfCodeTrait<Label, Instr>,
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
pub fn try_once_indjump_jb<I: IntoIterator<Item = Label>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
jump_bits: Option<usize>,
) -> Result<
(),
HandlerBuilderError<
IndirectJumpHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let name = format!("__hb_once_indjump_{}", self.b.get_code().len());
let indjump = IndirectJumpHandler::new(&name, labels, temp_buffer, reuse);
indjump.try_install::<_, PutInstr>(jump_bits, &mut self.b)?;
Ok(())
}
pub fn try_once_indjump_jb_l<L, I: IntoIterator<Item = L>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
jump_bits: Option<usize>,
) -> Result<
(),
HandlerBuilderError<
IndirectJumpHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
Label: From<L>,
{
let name = format!("__hb_once_indjump_{}", self.b.get_code().len());
let indjump = IndirectJumpHandler::new_ll(name, labels, temp_buffer, reuse);
indjump.try_install::<_, PutInstr>(jump_bits, &mut self.b)?;
Ok(())
}
pub fn once_indjump_jb<I: IntoIterator<Item = Label>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
jump_bits: Option<usize>,
) where
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error: Debug,
{
self.try_once_indjump_jb(labels, temp_buffer, reuse, jump_bits)
.unwrap();
}
pub fn once_indjump_jb_l<L, I: IntoIterator<Item = L>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
jump_bits: Option<usize>,
) where
Label: From<L>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error: Debug,
{
self.try_once_indjump_jb_l(labels, temp_buffer, reuse, jump_bits)
.unwrap();
}
pub fn try_once_indjump<I: IntoIterator<Item = Label>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Result<
(),
HandlerBuilderError<
IndirectJumpHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
self.try_once_indjump_jb(labels, temp_buffer, reuse, None)
}
pub fn try_once_indjump_l<L, I: IntoIterator<Item = L>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Result<
(),
HandlerBuilderError<
IndirectJumpHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
Label: From<L>,
{
self.try_once_indjump_jb_l(labels, temp_buffer, reuse, None)
}
pub fn once_indjump<I: IntoIterator<Item = Label>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
) where
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error: Debug,
{
self.try_once_indjump(labels, temp_buffer, reuse).unwrap();
}
pub fn once_indjump_l<L, I: IntoIterator<Item = L>>(
&mut self,
labels: I,
temp_buffer: bool,
reuse: bool,
) where
Label: From<L>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error: Debug,
{
self.try_once_indjump_l(labels, temp_buffer, reuse).unwrap();
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<Label> + From<String> + std::fmt::Display + DefaultSep + LabelJoin,
MinInfRel<Label>: From<Label>,
Builder: Default + MinInfLabelTrait<Label>,
<Builder as builder::MinInfLabelTrait<Label>>::Error: std::fmt::Debug,
{
fn add_longdata_handler_check(
&mut self,
name: &str,
temp_buffer: bool,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>> {
let lname = name.to_string().into();
let name = if !temp_buffer && self.ma_ldh_check_name_base.is_some() {
ldh_check_name2(
&lname,
&self.sep,
self.ma_ldh_check_name_base.as_ref().unwrap(),
)
} else if temp_buffer && self.tb_ldh_check_name_base.is_some() {
ldh_check_name2(
&lname,
&self.sep,
self.tb_ldh_check_name_base.as_ref().unwrap(),
)
} else {
return Ok(());
};
self.try_add_routine_l(name, !temp_buffer)?;
Ok(())
}
pub fn try_add_longdata_handler(
&mut self,
name: &str,
temp_buffer: bool,
per_bits: usize,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>> {
{
let mut longdata_handler_map = self.longdata_handler_map.borrow_mut();
if longdata_handler_map.contains_key(name) {
return Err(HandlerBuilderError::LongDataHandlerAlreadyExists(
name.to_string(),
));
}
longdata_handler_map.insert(
name.to_string(),
RefCell::new(LongDataHandler::new(name, temp_buffer, per_bits)),
);
}
self.add_longdata_handler_check(name, temp_buffer)?;
Ok(())
}
pub fn add_longdata_handler(&mut self, name: &str, temp_buffer: bool, per_bits: usize) {
self.try_add_longdata_handler(name, temp_buffer, per_bits)
.unwrap();
}
pub fn try_add_longdata<L>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
jump: L,
) -> Result<Label, HandlerBuilderError<()>>
where
Label: From<L>,
{
if let Some(lh) = self.longdata_handler_map.borrow_mut().get_mut(hname) {
lh.borrow_mut()
.try_add_data(data, jump)
.map_err(|e| HandlerBuilderError::LongDataError(e))
} else {
Err(HandlerBuilderError::LongDataHandlerNotFound(
hname.to_string(),
))
}
}
pub fn add_longdata<L>(&mut self, hname: &str, data: (&[u8], u8, u8), jump: L) -> Label
where
Label: From<L>,
{
self.ldh_usage.insert(hname.to_string());
self.try_add_longdata(hname, data, jump).unwrap()
}
pub fn try_ldh_check_fix_name(
&self,
name: &str,
) -> Result<Option<Label>, HandlerBuilderError<()>> {
if let Some(ldh) =
Ref::filter_map(self.longdata_handler_map.borrow(), |ldm| ldm.get(name)).ok()
{
let ldh = ldh.borrow();
if ldh.temp_buffer() {
if let Some(ldh_check_name_base) = self.tb_ldh_check_name_base.as_ref() {
Ok(Some(ldh_check_name(&ldh, &self.sep, ldh_check_name_base)))
} else {
Ok(None)
}
} else {
if let Some(ldh_check_name_base) = self.ma_ldh_check_name_base.as_ref() {
Ok(Some(ldh_check_name(&ldh, &self.sep, ldh_check_name_base)))
} else {
Ok(None)
}
}
} else {
Err(HandlerBuilderError::LongDataHandlerNotFound(
name.to_string(),
))
}
}
pub fn ldh_check_fix_name(&self, name: &str) -> Option<Label> {
self.try_ldh_check_fix_name(name).unwrap()
}
pub fn try_ldh_start<L>(&mut self, label: L) -> Result<(), HandlerBuilderError<()>>
where
Label: From<L>,
{
if self.ldh_starts.is_empty() {
self.ldh_starts = vec![label.into()];
Ok(())
} else {
Err(HandlerBuilderError::LDHStartsDefined)
}
}
pub fn ldh_start<L>(&mut self, label: L)
where
Label: From<L>,
{
self.try_ldh_start(label).unwrap()
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<Label> + From<String> + std::fmt::Display,
MinInfRel<Label>: From<Label>,
{
pub fn try_add_data_handler(
&mut self,
name: &str,
data_bits: usize,
per_bits: usize,
jump: Label,
temp_buffer: bool,
) -> Result<(), HandlerBuilderError<()>> {
let mut data_handler_map = self.data_handler_map.borrow_mut();
if data_handler_map.contains_key(name) {
return Err(HandlerBuilderError::DataHandlerAlreadyExists(
name.to_string(),
));
}
data_handler_map.insert(
name.to_string(),
DataHandler::new(name, data_bits, per_bits, jump, temp_buffer),
);
Ok(())
}
pub fn add_data_handler(
&mut self,
name: &str,
data_bits: usize,
per_bits: usize,
jump: Label,
temp_buffer: bool,
) {
self.try_add_data_handler(name, data_bits, per_bits, jump, temp_buffer)
.unwrap();
}
pub fn try_add_data_handler_l<L: Clone>(
&mut self,
name: L,
data_bits: usize,
per_bits: usize,
jump: Label,
temp_buffer: bool,
) -> Result<(), HandlerBuilderError<()>>
where
Label: From<L>,
{
let name_s = Label::from(name.clone()).to_string();
let mut data_handler_map = self.data_handler_map.borrow_mut();
if data_handler_map.contains_key(&name_s) {
return Err(HandlerBuilderError::DataHandlerAlreadyExists(name_s));
}
data_handler_map.insert(
name_s,
DataHandler::new_l(name, data_bits, per_bits, jump, temp_buffer),
);
Ok(())
}
pub fn add_data_handler_l<L: Clone>(
&mut self,
name: L,
data_bits: usize,
per_bits: usize,
jump: Label,
temp_buffer: bool,
) where
Label: From<L>,
{
self.try_add_data_handler_l(name, data_bits, per_bits, jump, temp_buffer)
.unwrap();
}
pub fn try_add_data_handler_ll<L: Clone, L2>(
&mut self,
name: L,
data_bits: usize,
per_bits: usize,
jump: L2,
temp_buffer: bool,
) -> Result<(), HandlerBuilderError<()>>
where
Label: From<L> + From<L2>,
{
let name_s = Label::from(name.clone()).to_string();
let mut data_handler_map = self.data_handler_map.borrow_mut();
if data_handler_map.contains_key(&name_s) {
return Err(HandlerBuilderError::DataHandlerAlreadyExists(name_s));
}
data_handler_map.insert(
name_s,
DataHandler::new_ll(name, data_bits, per_bits, jump, temp_buffer),
);
Ok(())
}
pub fn add_data_handler_ll<L: Clone, L2>(
&mut self,
name: L,
data_bits: usize,
per_bits: usize,
jump: L2,
temp_buffer: bool,
) where
Label: From<L> + From<L2>,
{
self.try_add_data_handler_ll(name, data_bits, per_bits, jump, temp_buffer)
.unwrap();
}
pub fn has_longdata_handler(&self, name: &str) -> bool {
self.longdata_handler_map.borrow().contains_key(name)
}
pub fn has_data_handler(&self, name: &str) -> bool {
self.data_handler_map.borrow().contains_key(name)
}
pub fn try_put_data(
&mut self,
name: &str,
data: usize,
) -> Result<Label, HandlerBuilderError<()>> {
if let Some(dh) = self.data_handler_map.borrow_mut().get_mut(name) {
Ok(dh.put_data(data))
} else {
Err(HandlerBuilderError::DataHandlerNotFound(name.to_string()))
}
}
pub fn put_data(&mut self, name: &str, data: usize) -> Label {
self.try_put_data(name, data).unwrap()
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<Label> + From<String> + DefaultSep + std::fmt::Display,
MinInfRel<Label>: From<Label>,
Builder: MinInfLabelTrait<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
pub fn try_add_routine_x(
&mut self,
name: &str,
temp_buffer: bool,
rb: Builder,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
> {
let ret_label = {
let mut rm = self.routine_map.borrow_mut();
if rm.contains_key(name) {
return Err(HandlerBuilderError::RoutineAlreadyExists(name.to_string()));
}
let rh = RoutineHandler::new(name, temp_buffer, true);
let ret_label = rh.jump_to_return();
let routine_labels = rh.routine_labels().to_vec();
rm.insert(
name.to_string(),
(
RefCell::new(rh),
Rc::new(RefCell::new(self.new_with_routine_map(rb, routine_labels))),
),
);
ret_label
};
let newrb = self.routine_map.borrow().get(name).unwrap().1.clone();
newrb.borrow_mut().try_add_label(name.to_string())?;
Ok((newrb, ret_label))
}
pub fn add_routine_x(
&mut self,
name: &str,
temp_buffer: bool,
rb: Builder,
) -> (Rc<RefCell<Self>>, Label) {
self.try_add_routine_x(name, temp_buffer, rb).unwrap()
}
pub fn try_add_routine_x_l<L: Clone>(
&mut self,
name: L,
temp_buffer: bool,
rb: Builder,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
>
where
Label: From<L>,
{
let name_s = Label::from(name.clone()).to_string();
let ret_label = {
let mut rm = self.routine_map.borrow_mut();
if rm.contains_key(&name_s) {
return Err(HandlerBuilderError::RoutineAlreadyExists(name_s.clone()));
}
let rh = RoutineHandler::new_l(name, temp_buffer, true);
let ret_label = rh.jump_to_return();
let routine_labels = rh.routine_labels().to_vec();
rm.insert(
name_s.clone(),
(
RefCell::new(rh),
Rc::new(RefCell::new(self.new_with_routine_map(rb, routine_labels))),
),
);
ret_label
};
let newrb = self.routine_map.borrow().get(&name_s).unwrap().1.clone();
newrb.borrow_mut().try_add_label(name_s)?;
Ok((newrb, ret_label))
}
pub fn add_routine_x_l<L: Clone>(
&mut self,
name: L,
temp_buffer: bool,
rb: Builder,
) -> (Rc<RefCell<Self>>, Label)
where
Label: From<L>,
{
self.try_add_routine_x_l(name, temp_buffer, rb).unwrap()
}
pub fn try_add_routine_x_ll(
&mut self,
name: Label,
temp_buffer: bool,
rb: Builder,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
> {
let name_s = name.clone().to_string();
let ret_label = {
let mut rm = self.routine_map.borrow_mut();
if rm.contains_key(&name_s) {
return Err(HandlerBuilderError::RoutineAlreadyExists(name_s.clone()));
}
let rh = RoutineHandler::new_l(name, temp_buffer, true);
let ret_label = rh.jump_to_return();
let routine_labels = rh.routine_labels().to_vec();
rm.insert(
name_s.clone(),
(
RefCell::new(rh),
Rc::new(RefCell::new(self.new_with_routine_map(rb, routine_labels))),
),
);
ret_label
};
let newrb = self.routine_map.borrow().get(&name_s).unwrap().1.clone();
newrb.borrow_mut().try_add_label(name_s)?;
Ok((newrb, ret_label))
}
pub fn add_routine_x_ll(
&mut self,
name: Label,
temp_buffer: bool,
rb: Builder,
) -> (Rc<RefCell<Self>>, Label) {
self.try_add_routine_x_ll(name, temp_buffer, rb).unwrap()
}
pub fn try_add_routine_x_with_labels<I: IntoIterator<Item = Label>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
rb: Builder,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
> {
let ret_label = {
let mut rm = self.routine_map.borrow_mut();
if rm.contains_key(name) {
return Err(HandlerBuilderError::RoutineAlreadyExists(name.to_string()));
}
let rh = RoutineHandler::new_with_labels(name, rlabels, temp_buffer, true);
let ret_label = rh.jump_to_return();
let routine_labels = rh.routine_labels().to_vec();
rm.insert(
name.to_string(),
(
RefCell::new(rh),
Rc::new(RefCell::new(self.new_with_routine_map(rb, routine_labels))),
),
);
ret_label
};
let newrb = self.routine_map.borrow().get(name).unwrap().1.clone();
newrb.borrow_mut().try_add_label(name.to_string())?;
Ok((newrb, ret_label))
}
pub fn add_routine_x_with_labels<I: IntoIterator<Item = Label>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
rb: Builder,
) -> (Rc<RefCell<Self>>, Label) {
self.try_add_routine_x_with_labels(name, rlabels, temp_buffer, rb)
.unwrap()
}
pub fn try_add_routine_x_with_labels_l<L, I: IntoIterator<Item = L>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
rb: Builder,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
>
where
Label: From<L>,
{
let ret_label = {
let mut rm = self.routine_map.borrow_mut();
if rm.contains_key(name) {
return Err(HandlerBuilderError::RoutineAlreadyExists(name.to_string()));
}
let rh = RoutineHandler::new_with_labels_l(name, rlabels, temp_buffer, true);
let ret_label = rh.jump_to_return();
let routine_labels = rh.routine_labels().to_vec();
rm.insert(
name.to_string(),
(
RefCell::new(rh),
Rc::new(RefCell::new(self.new_with_routine_map(rb, routine_labels))),
),
);
ret_label
};
let newrb = self.routine_map.borrow().get(name).unwrap().1.clone();
newrb.borrow_mut().try_add_label(name.to_string())?;
Ok((newrb, ret_label))
}
pub fn add_routine_x_with_labels_l<L, I: IntoIterator<Item = L>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
rb: Builder,
) -> (Rc<RefCell<Self>>, Label)
where
Label: From<L>,
{
self.try_add_routine_x_with_labels_l(name, rlabels, temp_buffer, rb)
.unwrap()
}
pub fn try_add_routine_x_local<
Body: FnMut(
LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>,
Label,
)
-> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>,
>(
&mut self,
name: &str,
temp_buffer: bool,
rb: Builder,
mut body: Body,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>> {
let (mut fb, ret) = self.try_add_routine_x(name, temp_buffer, rb)?;
use std::borrow::BorrowMut;
let fb = fb.borrow_mut();
let mut fb = fb.deref().deref().borrow_mut();
let fb = fb.deref_mut();
let loc = LocalLabels::new(fb, name.to_string());
body(loc, ret)
}
pub fn add_routine_x_local<
Body: FnMut(LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>, Label),
>(
&mut self,
name: &str,
temp_buffer: bool,
rb: Builder,
mut body: Body,
) {
self.try_add_routine_x_local(name, temp_buffer, rb, |loc, ret| {
body(loc, ret);
Ok(())
})
.unwrap();
}
pub fn try_add_routine_x_l_local<
L: Clone,
Body: FnMut(
LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>,
Label,
)
-> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>,
>(
&mut self,
name: L,
temp_buffer: bool,
rb: Builder,
mut body: Body,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>
where
Label: From<L>,
{
let (mut fb, ret) = self.try_add_routine_x_l(name.clone(), temp_buffer, rb)?;
use std::borrow::BorrowMut;
let fb = fb.borrow_mut();
let mut fb = fb.deref().deref().borrow_mut();
let fb = fb.deref_mut();
let loc = LocalLabels::new::<L>(fb, name);
body(loc, ret)
}
pub fn add_routine_x_l_local<
L: Clone,
Body: FnMut(LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>, Label),
>(
&mut self,
name: L,
temp_buffer: bool,
rb: Builder,
mut body: Body,
) where
Label: From<L>,
{
self.try_add_routine_x_l_local(name, temp_buffer, rb, |loc, ret| {
body(loc, ret);
Ok(())
})
.unwrap();
}
pub fn try_add_routine_x_ll_local<
Body: FnMut(
LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>,
Label,
)
-> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>,
>(
&mut self,
name: Label,
temp_buffer: bool,
rb: Builder,
mut body: Body,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>> {
let (mut fb, ret) = self.try_add_routine_x_ll(name.clone(), temp_buffer, rb)?;
use std::borrow::BorrowMut;
let fb = fb.borrow_mut();
let mut fb = fb.deref().deref().borrow_mut();
let fb = fb.deref_mut();
let loc = LocalLabels::new(fb, name);
body(loc, ret)
}
pub fn add_routine_x_ll_local<
Body: FnMut(LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>, Label),
>(
&mut self,
name: Label,
temp_buffer: bool,
rb: Builder,
mut body: Body,
) {
self.try_add_routine_x_ll_local(name, temp_buffer, rb, |loc, ret| {
body(loc, ret);
Ok(())
})
.unwrap();
}
pub fn has_routine(&self, name: &str) -> bool {
self.routine_map.borrow().contains_key(name)
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<Label> + From<String> + DefaultSep + std::fmt::Display,
MinInfRel<Label>: From<Label>,
Builder: Default + MinInfLabelTrait<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
pub fn try_add_routine(
&mut self,
name: &str,
temp_buffer: bool,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
> {
self.try_add_routine_x(name, temp_buffer, Builder::default())
}
pub fn add_routine(&mut self, name: &str, temp_buffer: bool) -> (Rc<RefCell<Self>>, Label) {
self.add_routine_x(name, temp_buffer, Builder::default())
}
pub fn try_add_routine_l<L: Clone>(
&mut self,
name: L,
temp_buffer: bool,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
>
where
Label: From<L>,
{
self.try_add_routine_x_l(name, temp_buffer, Builder::default())
}
pub fn add_routine_l<L: Clone>(
&mut self,
name: L,
temp_buffer: bool,
) -> (Rc<RefCell<Self>>, Label)
where
Label: From<L>,
{
self.add_routine_x_l(name, temp_buffer, Builder::default())
}
pub fn try_add_routine_ll(
&mut self,
name: Label,
temp_buffer: bool,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
> {
self.try_add_routine_x_ll(name, temp_buffer, Builder::default())
}
pub fn add_routine_ll(&mut self, name: Label, temp_buffer: bool) -> (Rc<RefCell<Self>>, Label) {
self.add_routine_x_ll(name, temp_buffer, Builder::default())
}
pub fn try_add_routine_with_labels<I: IntoIterator<Item = Label>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
> {
self.try_add_routine_x_with_labels(name, rlabels, temp_buffer, Builder::default())
}
pub fn add_routine_with_labels<I: IntoIterator<Item = Label>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
) -> (Rc<RefCell<Self>>, Label) {
self.add_routine_x_with_labels(name, rlabels, temp_buffer, Builder::default())
}
pub fn try_add_routine_with_labels_l<L, I: IntoIterator<Item = L>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
) -> Result<
(Rc<RefCell<Self>>, Label),
HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>,
>
where
Label: From<L>,
{
self.try_add_routine_x_with_labels_l(name, rlabels, temp_buffer, Builder::default())
}
pub fn add_routine_with_labels_l<L, I: IntoIterator<Item = L>>(
&mut self,
name: &str,
rlabels: I,
temp_buffer: bool,
) -> (Rc<RefCell<Self>>, Label)
where
Label: From<L>,
{
self.add_routine_x_with_labels_l::<L, I>(name, rlabels, temp_buffer, Builder::default())
}
pub fn try_add_routine_local<
Body: FnMut(
LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>,
Label,
)
-> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>,
>(
&mut self,
name: &str,
temp_buffer: bool,
body: Body,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>> {
self.try_add_routine_x_local(name, temp_buffer, Builder::default(), body)
}
pub fn add_routine_local<
Body: FnMut(LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>, Label),
>(
&mut self,
name: &str,
temp_buffer: bool,
mut body: Body,
) {
self.try_add_routine_local(name, temp_buffer, |loc, ret| {
body(loc, ret);
Ok(())
})
.unwrap();
}
pub fn try_add_routine_l_local<
L: Clone,
Body: FnMut(
LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>,
Label,
)
-> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>,
>(
&mut self,
name: L,
temp_buffer: bool,
body: Body,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>
where
Label: From<L>,
{
self.try_add_routine_x_l_local(name, temp_buffer, Builder::default(), body)
}
pub fn add_routine_l_local<
L: Clone,
Body: FnMut(LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>, Label),
>(
&mut self,
name: L,
temp_buffer: bool,
mut body: Body,
) where
Label: From<L>,
{
self.try_add_routine_l_local(name, temp_buffer, |loc, ret| {
body(loc, ret);
Ok(())
})
.unwrap();
}
pub fn try_add_routine_ll_local<
Body: FnMut(
LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>,
Label,
)
-> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>>,
>(
&mut self,
name: Label,
temp_buffer: bool,
body: Body,
) -> Result<(), HandlerBuilderError<<Builder as MinInfLabelTrait<Label>>::Error>> {
self.try_add_routine_x_ll_local(name, temp_buffer, Builder::default(), body)
}
pub fn add_routine_ll_local<
Body: FnMut(LocalLabels<HandlerBuilder<Builder, Label, Instr, PutInstr>, Label>, Label),
>(
&mut self,
name: Label,
temp_buffer: bool,
mut body: Body,
) {
self.try_add_routine_ll_local(name, temp_buffer, |loc, ret| {
body(loc, ret);
Ok(())
})
.unwrap();
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfBuilderTrait<Label, PutInstr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
fn rh_mut_helper(
&mut self,
name: &str,
) -> Result<
(&mut Builder, Ref<'_, RefCell<RoutineHandler<Label>>>),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
if let Some(rh) = Ref::filter_map(self.routine_map.borrow(), |rm| {
rm.get(name).map(|(rh, _)| rh)
})
.ok()
{
Ok((&mut self.b, rh))
} else {
Err(HandlerBuilderError::RoutineNotFound(name.to_string()))
}
}
fn rh2_mut_helper(
&mut self,
name: &str,
name2: &str,
) -> Result<
(
&mut Builder,
Ref<'_, RefCell<RoutineHandler<Label>>>,
Ref<'_, RefCell<RoutineHandler<Label>>>,
),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
if let Some(rh) = Ref::filter_map(self.routine_map.borrow(), |rm| {
rm.get(name).map(|(rh, _)| rh)
})
.ok()
{
if let Some(rh2) = Ref::filter_map(self.routine_map.borrow(), |rm| {
rm.get(name2).map(|(rh, _)| rh)
})
.ok()
{
Ok((&mut self.b, rh, rh2))
} else {
Err(HandlerBuilderError::RoutineNotFound(name2.to_string()))
}
} else {
Err(HandlerBuilderError::RoutineNotFound(name.to_string()))
}
}
pub fn try_call_01(
&mut self,
name: &str,
func: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, rh) = self.rh_mut_helper(name)?;
Ok(try_routine_call_01(
rh.deref().borrow_mut().deref_mut(),
b,
func,
)?)
}
pub fn try_call(
&mut self,
name: &str,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, rh) = self.rh_mut_helper(name)?;
Ok(try_routine_call(
rh.deref().borrow_mut().deref_mut(),
b,
func_fr0,
func_fr1,
)?)
}
pub fn try_call_fr0_01<IntoRel>(
&mut self,
name: &str,
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, rh) = self.rh_mut_helper(name)?;
Ok(try_routine_call_fr0_01(
rh.deref().borrow_mut().deref_mut(),
b,
func,
rel,
)?)
}
pub fn try_call_fr0<IntoRel>(
&mut self,
name: &str,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, rh) = self.rh_mut_helper(name)?;
Ok(try_routine_call_fr0(
rh.deref().borrow_mut().deref_mut(),
b,
func_fr0,
func_fr1,
rel,
)?)
}
pub fn try_call_fr1_01<IntoRel>(
&mut self,
name: &str,
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, rh) = self.rh_mut_helper(name)?;
Ok(try_routine_call_fr1_01(
rh.deref().borrow_mut().deref_mut(),
b,
func,
rel,
)?)
}
pub fn try_call_fr1<IntoRel>(
&mut self,
name: &str,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, rh) = self.rh_mut_helper(name)?;
Ok(try_routine_call_fr1(
rh.deref().borrow_mut().deref_mut(),
b,
func_fr0,
func_fr1,
rel,
)?)
}
pub fn try_call_2_01(
&mut self,
name: &str,
name2: &str,
func: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, rh, rh2) = self.rh2_mut_helper(name, name2)?;
Ok(try_routine_call_2_01(
rh.deref().borrow_mut().deref_mut(),
rh2.deref().borrow_mut().deref_mut(),
b,
func,
)?)
}
pub fn try_call_2(
&mut self,
name: &str,
name2: &str,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, rh, rh2) = self.rh2_mut_helper(name, name2)?;
Ok(try_routine_call_2(
rh.deref().borrow_mut().deref_mut(),
rh2.deref().borrow_mut().deref_mut(),
b,
func_fr0,
func_fr1,
)?)
}
#[inline]
fn b_instr<I>(
&mut self,
instr: I,
) -> Result<(), HandlerBuilderSkipError<<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error>>
where
PutInstr: From<I>,
{
Ok(self.b.try_add_instr(instr)?)
}
pub fn try_skip_ret(
&mut self,
temp_buffer: bool,
) -> Result<(), HandlerBuilderSkipError<<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error>>
{
if temp_buffer {
if let Some(tb_return_bits) = self.tb_return_bits {
for _ in 0..tb_return_bits {
self.b_instr((MINF_TBRF, MINF_TBRF, 1isize.into(), 1isize.into()))?;
}
} else {
return Err(HandlerBuilderSkipError::NoReturnBitsSet);
}
} else {
if let Some(ma_return_bits) = self.ma_return_bits {
for _ in 0..ma_return_bits {
self.b_instr((MINF_MARF, MINF_MARF, 1isize.into(), 1isize.into()))?;
}
} else {
return Err(HandlerBuilderSkipError::NoReturnBitsSet);
}
}
Ok(())
}
pub fn try_back_ret(
&mut self,
temp_buffer: bool,
) -> Result<(), HandlerBuilderSkipError<<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error>>
{
if temp_buffer {
if let Some(tb_return_bits) = self.tb_return_bits {
for _ in 0..tb_return_bits {
self.b_instr((MINF_TBB, MINF_TBB, 1isize.into(), 1isize.into()))?;
}
} else {
return Err(HandlerBuilderSkipError::NoReturnBitsSet);
}
} else {
if let Some(ma_return_bits) = self.ma_return_bits {
for _ in 0..ma_return_bits {
self.b_instr((MINF_MAB, MINF_MAB, 1isize.into(), 1isize.into()))?;
}
} else {
return Err(HandlerBuilderSkipError::NoReturnBitsSet);
}
}
Ok(())
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfBuilderTrait<Label, PutInstr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
pub fn call_01(&mut self, name: &str, func: MinInfFunc) {
self.try_call_01(name, func).unwrap();
}
pub fn call(&mut self, name: &str, func_fr0: MinInfFunc, func_fr1: MinInfFunc) {
self.try_call(name, func_fr0, func_fr1).unwrap();
}
pub fn call_fr0_01<IntoRel>(&mut self, name: &str, func: MinInfFunc, rel: IntoRel)
where
PutInstr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_call_fr0_01(name, func, rel).unwrap();
}
pub fn call_fr0<IntoRel>(
&mut self,
name: &str,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
PutInstr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_call_fr0(name, func_fr0, func_fr1, rel).unwrap();
}
pub fn call_fr1_01<IntoRel>(&mut self, name: &str, func: MinInfFunc, rel: IntoRel)
where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_call_fr1_01(name, func, rel).unwrap();
}
pub fn call_fr1<IntoRel>(
&mut self,
name: &str,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_call_fr1(name, func_fr0, func_fr1, rel).unwrap();
}
pub fn call_2_01(&mut self, name: &str, name2: &str, func: MinInfFunc) {
self.try_call_2_01(name, name2, func).unwrap()
}
pub fn call_2(&mut self, name: &str, name2: &str, func_fr0: MinInfFunc, func_fr1: MinInfFunc) {
self.try_call_2(name, name2, func_fr0, func_fr1).unwrap()
}
pub fn skip_ret(&mut self, temp_buffer: bool) {
self.try_skip_ret(temp_buffer).unwrap();
}
pub fn back_ret(&mut self, temp_buffer: bool) {
self.try_back_ret(temp_buffer).unwrap();
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfBuilderTrait<Label, PutInstr> + MinInfLabelTrait<Label>,
Label: Clone + Debug + std::fmt::Display + From<String>,
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
fn ldh_mut_helper(
&mut self,
hname: &str,
) -> Result<
(&mut Builder, Ref<'_, RefCell<LongDataHandler<Label>>>),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
if let Some(ldh) =
Ref::filter_map(self.longdata_handler_map.borrow(), |ldhm| ldhm.get(hname)).ok()
{
self.ldh_usage.insert(hname.to_string());
Ok((&mut self.b, ldh))
} else {
Err(HandlerBuilderError::LongDataHandlerNotFound(
hname.to_string(),
))
}
}
fn ldh2_mut_helper(
&mut self,
hname: &str,
hname2: &str,
) -> Result<
(
&mut Builder,
Ref<'_, RefCell<LongDataHandler<Label>>>,
Ref<'_, RefCell<LongDataHandler<Label>>>,
),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
if let Some(ldh) =
Ref::filter_map(self.longdata_handler_map.borrow(), |ldhm| ldhm.get(hname)).ok()
{
if let Some(ldh2) =
Ref::filter_map(self.longdata_handler_map.borrow(), |ldhm| ldhm.get(hname2)).ok()
{
self.ldh_usage.insert(hname.to_string());
self.ldh_usage.insert(hname2.to_string());
Ok((&mut self.b, ldh, ldh2))
} else {
Err(HandlerBuilderError::LongDataHandlerNotFound(
hname2.to_string(),
))
}
} else {
Err(HandlerBuilderError::LongDataHandlerNotFound(
hname.to_string(),
))
}
}
pub fn try_ld_call_01(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call_01(b, data, func)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call(b, data, func_fr0, func_fr1)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_fr0_01<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call_fr0_01(b, data, func, rel)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_fr0<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call_fr0(b, data, func_fr0, func_fr1, rel)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_fr1_01<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call_fr1_01(b, data, func, rel)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_fr1<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
>
where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
{
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call_fr1(b, data, func_fr0, func_fr1, rel)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_2_01(
&mut self,
hname: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call_2_01(b, data_fr0, data_fr1, func)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_2(
&mut self,
hname: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, ldh) = self.ldh_mut_helper(hname)?;
ldh.borrow_mut()
.try_call_2(b, data_fr0, data_fr1, func_fr0, func_fr1)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_2x_01(
&mut self,
hname: &str,
hname2: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, ldh, ldh2) = self.ldh2_mut_helper(hname, hname2)?;
ldh.borrow_mut()
.try_call_2x_01(&mut ldh2.borrow_mut(), b, data_fr0, data_fr1, func)
.map_err(|e| HandlerBuilderError::Internal(e))
}
pub fn try_ld_call_2x(
&mut self,
hname: &str,
hname2: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
HandlerBuilderError<
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
>,
>,
> {
let (b, ldh, ldh2) = self.ldh2_mut_helper(hname, hname2)?;
ldh.borrow_mut()
.try_call_2x(
&mut ldh2.borrow_mut(),
b,
data_fr0,
data_fr1,
func_fr0,
func_fr1,
)
.map_err(|e| HandlerBuilderError::Internal(e))
}
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfBuilderTrait<Label, PutInstr> + MinInfLabelTrait<Label>,
Label: Clone + Debug + std::fmt::Display + From<String>,
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
pub fn ld_call_01(&mut self, hname: &str, data: (&[u8], u8, u8), func: MinInfFunc) {
self.try_ld_call_01(hname, data, func).unwrap();
}
pub fn ld_call(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) {
self.try_ld_call(hname, data, func_fr0, func_fr1).unwrap();
}
pub fn ld_call_fr0_01<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) where
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_ld_call_fr0_01(hname, data, func, rel).unwrap();
}
pub fn ld_call_fr0<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_ld_call_fr0(hname, data, func_fr0, func_fr1, rel)
.unwrap();
}
pub fn ld_call_fr1_01<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_ld_call_fr1_01(hname, data, func, rel).unwrap();
}
pub fn ld_call_fr1<IntoRel>(
&mut self,
hname: &str,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
PutInstr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_ld_call_fr1(hname, data, func_fr0, func_fr1, rel)
.unwrap();
}
pub fn ld_call_2_01(
&mut self,
hname: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) {
self.try_ld_call_2_01(hname, data_fr0, data_fr1, func)
.unwrap();
}
pub fn ld_call_2(
&mut self,
hname: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) {
self.try_ld_call_2(hname, data_fr0, data_fr1, func_fr0, func_fr1)
.unwrap();
}
pub fn ld_call_2x_01(
&mut self,
hname: &str,
hname2: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) {
self.try_ld_call_2x_01(hname, hname2, data_fr0, data_fr1, func)
.unwrap();
}
pub fn ld_call_2x(
&mut self,
hname: &str,
hname2: &str,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) {
self.try_ld_call_2x(hname, hname2, data_fr0, data_fr1, func_fr0, func_fr1)
.unwrap();
}
}
impl<Builder, Label, Instr, PutInstr> MinInfLabelTrait<Label>
for HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfLabelTrait<Label>,
{
type Error = <Builder as MinInfLabelTrait<Label>>::Error;
fn try_add_label<L: Clone + Debug>(&mut self, label: L) -> Result<(), Self::Error>
where
Label: From<L>,
{
self.b.try_add_label(label)
}
fn get_label_map(&self) -> &BTreeMap<Label, usize> {
self.b.get_label_map()
}
}
impl<Builder, Label, Instr, PutInstr> MinInfBuilderTrait<Label, PutInstr>
for HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfBuilderTrait<Label, PutInstr>,
{
type Error = <Builder as MinInfBuilderTrait<Label, PutInstr>>::Error;
fn try_add_instr<I>(&mut self, instr: I) -> Result<(), Self::Error>
where
PutInstr: From<I>,
{
self.b.try_add_instr(instr)
}
}
impl<'a, Builder, Label, Instr, PutInstr> MinInfCodeTrait<Label, Instr>
for HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfCodeTrait<Label, Instr>,
{
fn get_code(&self) -> &Vec<Instr> {
self.b.get_code()
}
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum HandlerBuilderToCodeError<CAE, LAE, BAE, JAE, MAE> {
#[error("LabelNotFound: {0}")]
LabelNotFound(String),
#[error("LabelError: {0}")]
LabelError(LAE),
#[error("BuildError: {0}")]
BuildError(BAE),
#[error("ToCode: {0}")]
ToCode(CAE),
#[error("RH: {0}")]
RoutineHandler(RoutineHandlerError<LAE, BAE>),
#[error("IndJH: {0}")]
IndJumpHandler(IndirectJumpHandlerError<LAE, BAE>),
#[error("LDH: {0}")]
LongDataHandler(LongDataHandlerError<LAE, BAE>),
#[error("DH: {0}")]
DataHandler(DataHandlerError<LAE, BAE>),
#[error("Join {0}: {1}")]
Join(String, JAE),
#[error("CallError: {0}")]
CallError(HandlerBuilderError<RoutineHandlerError<LAE, BAE>>),
#[error("MultiAppend: {0}")]
MultiAppend(MAE),
}
impl<Builder, Label, Instr, PutInstr> HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: Default
+ MinInfToCodeTrait<Label, MinInfInstr>
+ MinInfBuilderTrait<Label, PutInstr>
+ MinInfLabelTrait<Label>
+ MinInfJoinTrait
+ MinInfMultiAppendTrait,
Label: Clone + From<String> + std::fmt::Display + PartialOrd + Ord + LabelJoin + DefaultSep,
MinInfRel<Label>: From<Label>,
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
fn call_ldh_check_fix(
&mut self,
) -> Result<
(),
HandlerBuilderToCodeError<
<Builder as MinInfToCodeTrait<Label, MinInfInstr>>::Error,
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
<Builder as MinInfJoinTrait>::Error,
<Builder as MinInfMultiAppendTrait>::Error,
>,
> {
let ldh_map = self.longdata_handler_map.borrow();
let used_ldhs = self
.ldh_usage
.iter()
.filter_map(|ldh_name| {
let ldh = ldh_map.get(ldh_name.as_str()).unwrap();
let ldh_tb = ldh.borrow().temp_buffer();
if (self.ma_ldh_check_name_base.is_some() && !ldh_tb)
|| (self.tb_ldh_check_name_base.is_some() && ldh_tb)
{
Some((ldh_name.clone(), ldh_tb))
} else {
None
}
})
.collect::<Vec<_>>();
if !used_ldhs.is_empty() {
let label_map = self.b.get_label_map();
let ldh_pos_list = if !self.ldh_starts.is_empty() {
self.ldh_starts
.iter()
.map(|label| {
label_map.get(label).copied().ok_or(
HandlerBuilderToCodeError::LabelNotFound(label.clone().to_string()),
)
})
.collect::<Result<Vec<_>, _>>()?
} else {
vec![0]
};
let callbs = ldh_pos_list
.iter()
.map(|_| {
let mut callb = self.new_with_builder(Builder::default());
for (ldh_name, tb) in &used_ldhs {
let check_fix_name = ldh_check_name2(
&ldh_name,
&self.sep,
if *tb {
self.tb_ldh_check_name_base.as_ref().unwrap()
} else {
self.ma_ldh_check_name_base.as_ref().unwrap()
},
);
callb
.try_call_01(&check_fix_name.to_string(), MINF_MR)
.map_err(|e| HandlerBuilderToCodeError::CallError(e))?;
}
Ok(callb)
})
.collect::<Result<Vec<_>, _>>()?;
self.b
.try_multi_append(
ldh_pos_list
.into_iter()
.enumerate()
.map(|(i, pos)| (pos, &callbs[i].b)),
)
.map_err(|e| HandlerBuilderToCodeError::MultiAppend(e))?;
}
Ok(())
}
}
impl<Builder, Label, Instr, PutInstr> MinInfToCodeTrait<Label, MinInfInstr>
for HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Label: Clone + From<String> + std::fmt::Display + LabelJoin + DefaultSep + PartialOrd + Ord,
MinInfRel<Label>: From<Label>,
Builder: Default
+ MinInfToCodeTrait<Label, MinInfInstr>
+ MinInfBuilderTrait<Label, PutInstr>
+ MinInfLabelTrait<Label>
+ MinInfMultiAppendTrait,
PutInstr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error: Debug,
Builder: MinInfJoinTrait,
{
type Error = HandlerBuilderToCodeError<
<Builder as MinInfToCodeTrait<Label, MinInfInstr>>::Error,
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, PutInstr>>::Error,
<Builder as MinInfJoinTrait>::Error,
<Builder as MinInfMultiAppendTrait>::Error,
>;
fn try_to_code(mut self) -> Result<(Vec<MinInfInstr>, Vec<(Label, usize)>), Self::Error> {
self.call_ldh_check_fix()?;
let mut ld_max_ret_bits_map = BTreeMap::new();
for (_, indjump) in self.indjump_map.take() {
indjump
.try_install(None, &mut self.b)
.map_err(|e| HandlerBuilderToCodeError::IndJumpHandler(e))?;
}
for (_, (_, rb)) in self.routine_map.borrow().deref() {
rb.borrow_mut().call_ldh_check_fix()?;
}
for (ldh_name, longdata_handler) in self.longdata_handler_map.take() {
let longdata_handler = longdata_handler.into_inner();
let ldh_tb = longdata_handler.temp_buffer();
let max_ret_bits = longdata_handler
.try_install(&mut self.b)
.map_err(|e| HandlerBuilderToCodeError::LongDataHandler(e))?;
ld_max_ret_bits_map.insert(ldh_name, (max_ret_bits, ldh_tb));
}
if let Some(ma_ldh_check_name_base) = self.ma_ldh_check_name_base.clone() {
for (ldh_name, (max_ret_bits, _)) in
ld_max_ret_bits_map.iter().filter(|(_, (_, tb))| !*tb)
{
let rname = ldh_check_name2(&ldh_name, &self.sep, &ma_ldh_check_name_base);
let rname_s = rname.clone().to_string();
let rm = self.routine_map.borrow();
let (rh, rb) = rm.get(&rname_s).unwrap();
let tb_ret_bits = self.tb_return_bits.unwrap_or(0);
let check_bits = if 2 * tb_ret_bits <= *max_ret_bits {
max_ret_bits - 2 * tb_ret_bits
} else {
0
};
let check_bits_bits = std::cmp::max(1, usize::BITS - check_bits.leading_zeros());
let mut rb = rb.borrow_mut();
let ret = rh.borrow().jump_to_return();
rb.try_add_instr((MINF_MARW1, MINF_MARW1, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
rb.try_add_instr((MINF_MARF, MINF_MARF, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
for b in 0..check_bits_bits {
let drw = minf_marw(((check_bits >> b) & 1) != 0);
rb.try_add_instr((drw, drw, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
rb.try_add_instr((MINF_MARF, MINF_MARF, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
let drw = minf_marw(b + 1 >= check_bits_bits);
rb.try_add_instr((drw, drw, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
rb.try_add_instr((MINF_MARF, MINF_MARF, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
}
rb.try_call_01(&ma_ldh_check_name_base.to_string(), MINF_MR)
.map_err(|e| HandlerBuilderToCodeError::CallError(e))?;
rb.i((MINF_MR, MINF_MR, ret.clone().into(), ret.clone().into()));
}
}
if let Some(tb_ldh_check_name_base) = self.tb_ldh_check_name_base.clone() {
for (ldh_name, (max_ret_bits, _)) in
ld_max_ret_bits_map.iter().filter(|(_, (_, tb))| *tb)
{
let rname = ldh_check_name2(&ldh_name, &self.sep, &tb_ldh_check_name_base);
let rname_s = rname.clone().to_string();
let rm = self.routine_map.borrow();
let (rh, rb) = rm.get(&rname_s).unwrap();
let ma_ret_bits = self.ma_return_bits.unwrap_or(0);
let check_bits = if 2 * ma_ret_bits <= *max_ret_bits {
max_ret_bits - 2 * ma_ret_bits
} else {
0
};
let check_bits_bits = std::cmp::max(1, usize::BITS - check_bits.leading_zeros());
let mut rb = rb.borrow_mut();
let ret = rh.borrow().jump_to_return();
rb.try_add_instr((MINF_TBRW1, MINF_TBRW1, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
rb.try_add_instr((MINF_TBRF, MINF_TBRF, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
for b in 0..check_bits_bits {
let drw = minf_tbrw(((check_bits >> b) & 1) != 0);
rb.try_add_instr((drw, drw, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
rb.try_add_instr((MINF_TBRF, MINF_TBRF, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
let drw = minf_tbrw(b + 1 >= check_bits_bits);
rb.try_add_instr((drw, drw, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
rb.try_add_instr((MINF_TBRF, MINF_TBRF, 1isize.into(), 1isize.into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
}
rb.try_call_01(&tb_ldh_check_name_base.to_string(), MINF_MR)
.map_err(|e| HandlerBuilderToCodeError::CallError(e))?;
rb.try_add_instr((MINF_MR, MINF_MR, ret.clone().into(), ret.clone().into()))
.map_err(|e| HandlerBuilderToCodeError::BuildError(e))?;
}
}
let mut rbs = vec![];
for (_, (rh, rb)) in self.routine_map.take() {
let rh = rh.into_inner();
let name = rh.name().clone().to_string();
let rbits = if rh.temp_buffer() {
self.tb_return_bits
} else {
self.ma_return_bits
};
rh.try_install(rbits, &mut self.b)
.map_err(|e| HandlerBuilderToCodeError::RoutineHandler(e))?;
rbs.push((name, rb));
}
for (_, data_handler) in self.data_handler_map.take() {
data_handler
.try_install(&mut self.b)
.map_err(|e| HandlerBuilderToCodeError::DataHandler(e))?;
}
for (name, rb) in rbs {
self.b
.join(Rc::into_inner(rb).unwrap().into_inner().b)
.map_err(|e| HandlerBuilderToCodeError::Join(name, e))?;
}
self.b
.try_to_code()
.map_err(|e| HandlerBuilderToCodeError::ToCode(e))
}
}
impl<Builder, Label, Instr, PutInstr> MinInfStateNumTrait
for HandlerBuilder<Builder, Label, Instr, PutInstr>
where
Builder: MinInfStateNumTrait,
{
fn state_num(&self) -> usize {
self.b.state_num()
}
fn switch(&mut self, state_num: usize) -> usize {
self.b.switch(state_num)
}
}
pub type MISimpleHBuilder = HandlerBuilder<
MinInfBuilder<String, MinInfBuildInstr<String>>,
String,
MinInfBuildInstr<String>,
MinInfBuildInstr<String>,
>;
pub fn mi_simple_hbuilder_new(
ma_return_bits: Option<usize>,
tb_return_bits: Option<usize>,
) -> MISimpleHBuilder {
MISimpleHBuilder::new(MinInfBuilder::new(), ma_return_bits, tb_return_bits)
}
pub fn mi_simple_hbuilder_new_1(return_bits: Option<usize>) -> MISimpleHBuilder {
MISimpleHBuilder::new_1(MinInfBuilder::new(), return_bits)
}
pub fn mi_simple_hbuilder_new_safe_ldh<L>(
ma_return_bits: Option<usize>,
tb_return_bits: Option<usize>,
ma_ldh_check_name_base: Option<L>,
tb_ldh_check_name_base: Option<L>,
) -> MISimpleHBuilder
where
String: From<L>,
{
MISimpleHBuilder::new_safe_ldh(
MinInfBuilder::new(),
ma_return_bits,
tb_return_bits,
ma_ldh_check_name_base,
tb_ldh_check_name_base,
)
}
pub fn mi_simple_hbuilder_new_1_safe_ldh<L>(
return_bits: Option<usize>,
ma_ldh_check_name_base: Option<L>,
tb_ldh_check_name_base: Option<L>,
) -> MISimpleHBuilder
where
String: From<L>,
{
MISimpleHBuilder::new_1_safe_ldh(
MinInfBuilder::new(),
return_bits,
ma_ldh_check_name_base,
tb_ldh_check_name_base,
)
}
pub type MIStdSVHBuilder =
HandlerBuilder<MIStdSVBuilder, String, MinInfBInstrSingleSVInt<String>, MinInfBInstrSV<String>>;
pub fn mi_std_sv_hbuilder_new(
ma_return_bits: Option<usize>,
tb_return_bits: Option<usize>,
state_num: usize,
) -> MIStdSVHBuilder {
MIStdSVHBuilder::new(
MIStdSVBuilder::new(MIStdSVRootBuilder::new(), state_num),
ma_return_bits,
tb_return_bits,
)
}
pub fn mi_std_sv_hbuilder_new_safe_ldh<L>(
ma_return_bits: Option<usize>,
tb_return_bits: Option<usize>,
ma_ldh_check_name_base: Option<L>,
tb_ldh_check_name_base: Option<L>,
state_num: usize,
) -> MIStdSVHBuilder
where
String: From<L>,
{
MIStdSVHBuilder::new_safe_ldh(
MIStdSVBuilder::new(MIStdSVRootBuilder::new(), state_num),
ma_return_bits,
tb_return_bits,
ma_ldh_check_name_base,
tb_ldh_check_name_base,
)
}
pub fn mi_std_sv_hbuilder_new_1(return_bits: Option<usize>, state_num: usize) -> MIStdSVHBuilder {
MIStdSVHBuilder::new_1(
MIStdSVBuilder::new(MIStdSVRootBuilder::new(), state_num),
return_bits,
)
}
pub fn mi_std_sv_hbuilder_new_1_safe_ldh<L>(
return_bits: Option<usize>,
state_num: usize,
ma_ldh_check_name_base: Option<L>,
tb_ldh_check_name_base: Option<L>,
) -> MIStdSVHBuilder
where
String: From<L>,
{
MIStdSVHBuilder::new_1_safe_ldh(
MIStdSVBuilder::new(MIStdSVRootBuilder::new(), state_num),
return_bits,
ma_ldh_check_name_base,
tb_ldh_check_name_base,
)
}