use std::collections::{HashSet, BTreeMap};
use std::vec::Vec;
use std::fmt::{Formatter, Result, Display};
use crate::data::Event::*;
use crate::hover_messages;
pub static LINE_SPACE: i64 = 30;
pub trait Visualizable {
fn get_name_from_hash(&self, hash: &u64) -> Option<String>;
fn get_state(&self, hash: &u64, line_number: &usize) -> Option<State>;
fn get_states(&self, hash: &u64) -> Vec::<(usize, usize, State)>;
fn _append_event(&mut self, resource_access_point: &ResourceAccessPoint, event: Event, line_number: &usize);
fn append_processed_external_event(&mut self, event: ExternalEvent, line_number: usize);
fn append_external_event(&mut self, event: ExternalEvent, line_number: &usize);
fn is_mut(&self, hash: &u64 ) -> bool;
fn is_mutref(&self, hash: &u64) -> bool;
fn calc_state(&self, previous_state: & State, event: & Event, event_line: usize, hash: &u64) -> State;
}
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub enum ResourceAccessPoint {
Owner(Owner),
MutRef(MutRef),
StaticRef(StaticRef),
Function(Function),
Struct(Struct),
}
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Owner {
pub name: String,
pub hash: u64,
pub is_mut: bool, }
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Struct {
pub name: String,
pub hash: u64,
pub owner: u64,
pub is_mut: bool,
pub is_member: bool
}
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct MutRef { pub name: String,
pub hash: u64,
pub is_mut: bool,
}
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct StaticRef { pub name: String,
pub hash: u64,
pub is_mut: bool,
}
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Function {
pub name: String,
pub hash: u64,
}
impl ResourceAccessPoint {
pub fn hash(&self) -> &u64 {
match self {
ResourceAccessPoint::Owner(Owner{hash, ..}) => hash,
ResourceAccessPoint::Struct(Struct{hash, ..}) => hash,
ResourceAccessPoint::MutRef(MutRef{hash, ..}) => hash,
ResourceAccessPoint::StaticRef(StaticRef{hash, ..}) => hash,
ResourceAccessPoint::Function(Function{hash, ..}) => hash,
}
}
pub fn name(&self) -> &String {
match self {
ResourceAccessPoint::Owner(Owner{name, ..}) => name,
ResourceAccessPoint::Struct(Struct{name, ..}) => name,
ResourceAccessPoint::MutRef(MutRef{name, ..}) => name,
ResourceAccessPoint::StaticRef(StaticRef{name, ..}) => name,
ResourceAccessPoint::Function(Function{name, ..}) => name,
}
}
pub fn is_mut(&self) -> bool {
match self {
ResourceAccessPoint::Owner(Owner{is_mut, ..}) => is_mut.to_owned(),
ResourceAccessPoint::Struct(Struct{is_mut, ..}) => is_mut.to_owned(),
ResourceAccessPoint::MutRef(MutRef{is_mut, ..}) => is_mut.to_owned(),
ResourceAccessPoint::StaticRef(StaticRef{is_mut, ..}) => is_mut.to_owned(),
ResourceAccessPoint::Function(_) => false,
}
}
pub fn is_ref(&self) -> bool {
match self {
ResourceAccessPoint::Owner(_) => false,
ResourceAccessPoint::Struct(_) => false,
ResourceAccessPoint::MutRef(_) => true,
ResourceAccessPoint::StaticRef(_) => true,
ResourceAccessPoint::Function(_) => false,
}
}
pub fn is_mutref(&self) -> bool {
match self {
ResourceAccessPoint::MutRef(_) => true,
_ => false
}
}
pub fn is_struct_group(&self) -> bool {
match self {
ResourceAccessPoint::Owner(_) => false,
ResourceAccessPoint::Struct(_) => true,
ResourceAccessPoint::MutRef(_) => false,
ResourceAccessPoint::StaticRef(_) => false,
ResourceAccessPoint::Function(_) => false,
}
}
pub fn is_struct(&self) -> bool {
match self {
ResourceAccessPoint::Owner(_) => false,
ResourceAccessPoint::Struct(Struct{is_member, ..}) => !is_member.to_owned(),
ResourceAccessPoint::MutRef(_) => false,
ResourceAccessPoint::StaticRef(_) => false,
ResourceAccessPoint::Function(_) => false,
}
}
pub fn is_member(&self) -> bool {
match self {
ResourceAccessPoint::Owner(_) => false,
ResourceAccessPoint::Struct(Struct{is_member, ..}) => is_member.to_owned(),
ResourceAccessPoint::MutRef(_) => false,
ResourceAccessPoint::StaticRef(_) => false,
ResourceAccessPoint::Function(_) => false,
}
}
pub fn get_owner(&self) -> u64 {
match self {
ResourceAccessPoint::Owner(Owner{hash, ..}) => hash.to_owned(),
ResourceAccessPoint::Struct(Struct{owner, ..}) => owner.to_owned(),
ResourceAccessPoint::MutRef(MutRef{hash, ..}) => hash.to_owned(),
ResourceAccessPoint::StaticRef(StaticRef{hash, ..}) => hash.to_owned(),
ResourceAccessPoint::Function(Function{hash, ..}) => hash.to_owned(),
}
}
}
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub enum ExternalEvent {
Bind {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>
},
Copy {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>
},
Move {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>,
},
StaticBorrow {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>,
},
MutableBorrow {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>,
},
StaticDie {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>,
},
MutableDie {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>,
},
PassByStaticReference {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>, },
PassByMutableReference {
from: Option<ResourceAccessPoint>,
to: Option<ResourceAccessPoint>, },
GoOutOfScope {
ro: ResourceAccessPoint
},
InitRefParam {
param: ResourceAccessPoint,
},
}
#[derive(Debug)]
pub enum Event {
Acquire {
from: Option<ResourceAccessPoint>
},
Duplicate {
to: Option<ResourceAccessPoint>
},
Copy {
from: Option<ResourceAccessPoint>
},
Move {
to: Option<ResourceAccessPoint>
},
MutableLend {
to: Option<ResourceAccessPoint>
},
MutableBorrow {
from: ResourceAccessPoint
},
MutableDie {
to: Option<ResourceAccessPoint>
},
MutableReacquire {
from: Option<ResourceAccessPoint>
},
StaticLend {
to: Option<ResourceAccessPoint>
},
StaticBorrow {
from: ResourceAccessPoint
},
StaticDie {
to: Option<ResourceAccessPoint>
},
StaticReacquire {
from: Option<ResourceAccessPoint>
},
OwnerGoOutOfScope,
RefGoOutOfScope,
InitRefParam {
param: ResourceAccessPoint
},
}
#[derive(Clone)]
pub enum State {
OutOfScope,
ResourceMoved {
move_to: Option<ResourceAccessPoint>,
move_at_line: usize
},
FullPrivilege,
PartialPrivilege {
borrow_count: u32,
borrow_to: HashSet<ResourceAccessPoint>
},
RevokedPrivilege {
to: Option<ResourceAccessPoint>,
borrow_to: Option<ResourceAccessPoint>,
},
Invalid,
}
impl std::fmt::Display for State {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result {
match self {
State::OutOfScope => write!(f, "OutOfScope"),
State::ResourceMoved { move_to: _, move_at_line: _ } => write!(f, "ResourceMoved"),
State::FullPrivilege => write!(f, "FullPrivilege"),
State::PartialPrivilege { .. } => write!(f, "PartialPrivilege"),
State::RevokedPrivilege { .. } => write!(f, "RevokedPrivilege"),
State::Invalid => write!(f, "Invalid"),
}
}
}
fn safe_message(
message_functor: fn(&String, &String) -> String,
my_name: &String,
some_target: &Option<ResourceAccessPoint>
) -> String {
if let Some(target) = some_target {
message_functor(my_name, target.name())
}
else {
message_functor(my_name, &"another value".to_owned())
}
}
impl State {
pub fn print_message_with_name(&self, my_name: &String) -> String {
match self {
State::OutOfScope => {
hover_messages::state_out_of_scope(my_name)
}
State::ResourceMoved{ move_to , move_at_line: _ } => {
safe_message(hover_messages::state_resource_moved, my_name, move_to)
}
State::FullPrivilege => {
hover_messages::state_full_privilege(my_name)
}
State::PartialPrivilege { .. } => {
hover_messages::state_partial_privilege(my_name)
}
State::RevokedPrivilege { to: _, borrow_to } => {
safe_message(hover_messages::state_resource_revoked, my_name, borrow_to)
}
State::Invalid => {
hover_messages::state_invalid(my_name)
}
}
}
}
impl Display for Event {
fn fmt(&self, f: &mut Formatter) -> Result {
let mut from_ro = None;
let mut to_ro = None;
let mut display = match self {
Event::Acquire{ from } => { from_ro = from.to_owned(); "" },
Event::Duplicate{ to } => { to_ro = to.to_owned(); "Copying resource" },
Event::Copy{ from } => { from_ro = from.to_owned(); "Copying resource from some variable" },
Event::Move{ to } => { to_ro = to.to_owned(); "Moving resource" },
Event::MutableLend{ to } => { to_ro = to.to_owned(); "Mutable lend" },
Event::MutableBorrow{ from } => { from_ro = Some(from.to_owned()); "Fully borrows resource" },
Event::MutableDie{ to } => { to_ro = to.to_owned(); "Fully returns resource"},
Event::MutableReacquire{ from } => { from_ro = from.to_owned(); "Fully reacquires resource" },
Event::StaticLend{ to } => { to_ro = to.to_owned(); "Partially lends resource" },
Event::StaticBorrow{ from } => { from_ro = Some(from.to_owned()); "Partially borrows resource" },
Event::StaticDie{ to } => { to_ro = to.to_owned(); "Partially returns resource"},
Event::StaticReacquire{ from } => { from_ro = from.to_owned(); "Partially reacquires resource" },
Event::InitRefParam{ param: _ } => { "Function parameter is initialized" },
Event::OwnerGoOutOfScope => { "Goes out of Scope as an owner of resource" },
Event::RefGoOutOfScope => { "Goes out of Scope as a reference to resource" },
}.to_string();
if let Some(from_ro) = from_ro {
display = format!("{} from {}", display, &(from_ro.name()));
};
if let Some(to_ro) = to_ro {
display = format!("{} to {}", display, &(to_ro.name()));
};
write!(f, "{}", display)
}
}
impl Event {
pub fn print_message_with_name(&self, my_name: &String) -> String {
match self {
OwnerGoOutOfScope => {
hover_messages::event_dot_owner_go_out_out_scope(my_name)
}
RefGoOutOfScope => {
hover_messages::event_dot_ref_go_out_out_scope(my_name)
}
InitRefParam{ param: _ } => {
hover_messages::event_dot_init_param(my_name)
}
Duplicate{ to } => {
safe_message(hover_messages::event_dot_copy_to, my_name, to)
}
Move{ to } => {
match to {
Some(_) => safe_message(hover_messages::event_dot_move_to, my_name, to),
None => safe_message(hover_messages::event_dot_move_to_caller, my_name, to)
}
}
StaticLend{ to } => {
safe_message(hover_messages::event_dot_static_lend, my_name, to)
}
MutableLend{ to } => {
safe_message(hover_messages::event_dot_mut_lend, my_name, to)
}
StaticDie{ to } => {
safe_message(hover_messages::event_dot_static_return, my_name, to)
}
MutableDie{ to } => {
safe_message(hover_messages::event_dot_mut_return, my_name, to)
}
Acquire{ from } => {
safe_message(hover_messages::event_dot_acquire, my_name, from)
}
Copy{ from } => {
safe_message(hover_messages::event_dot_copy_from, my_name, from)
}
MutableBorrow{ from } => {
hover_messages::event_dot_mut_borrow(my_name, from.name())
}
StaticBorrow{ from } => {
hover_messages::event_dot_static_borrow(my_name, from.name())
}
StaticReacquire{ from } => {
safe_message(hover_messages::event_dot_static_reacquire, my_name, from)
}
MutableReacquire{ from } => {
safe_message(hover_messages::event_dot_mut_reacquire, my_name, from)
}
}
}
}
#[derive(Debug)]
pub struct Timeline {
pub resource_access_point: ResourceAccessPoint, pub history: Vec<(usize, Event)>,
}
#[derive(Debug)]
pub struct StructsInfo {
pub structs: Vec<(i64, i64, i64)>,
}
#[derive(Debug)]
pub struct VisualizationData {
pub timelines: BTreeMap<u64, Timeline>,
pub external_events: Vec<(usize, ExternalEvent)>,
pub preprocess_external_events: Vec<(usize, ExternalEvent)>,
pub event_line_map: BTreeMap<usize, Vec<ExternalEvent>>,
}
#[allow(non_snake_case)]
pub fn ResourceAccessPoint_extract (external_event : &ExternalEvent) -> (&Option<ResourceAccessPoint>, &Option<ResourceAccessPoint>){
let (from, to) = match external_event {
ExternalEvent::Bind{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::Copy{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::Move{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::StaticBorrow{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::StaticDie{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::MutableBorrow{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::MutableDie{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::PassByMutableReference{from: from_ro, to: to_ro} => (from_ro, to_ro),
ExternalEvent::PassByStaticReference{from: from_ro, to: to_ro} => (from_ro, to_ro),
_ => (&None, &None),
};
(from, to)
}
impl Visualizable for VisualizationData {
fn get_name_from_hash(&self, hash: &u64) -> Option<String> {
match self.timelines.get(hash) {
Some(timeline) => Some(timeline.resource_access_point.name().to_owned()),
_ => None
}
}
fn is_mut(&self, hash: &u64) -> bool {
self.timelines[hash].resource_access_point.is_mut()
}
fn is_mutref(&self, hash: &u64) -> bool {
self.timelines[hash].resource_access_point.is_mutref()
}
fn calc_state(&self, previous_state: & State, event: & Event, event_line: usize, hash: &u64) -> State {
fn event_invalid(event: & Event) -> bool {
match event {
Event::StaticBorrow{ from: ResourceAccessPoint::Function(_) } => true,
Event::MutableBorrow{ from: ResourceAccessPoint::Function(_) } => true,
Event::StaticDie{ to: Some(ResourceAccessPoint::Function(_)) } => true,
Event::MutableDie{ to: Some(ResourceAccessPoint::Function(_)) } => true,
_ => false,
}
}
if event_invalid(event) { return State::Invalid; }
match (previous_state, event) {
(State::Invalid, _) =>
State::Invalid,
(State::OutOfScope, Event::Acquire{ .. }) =>
State::FullPrivilege,
(State::OutOfScope, Event::Copy{ .. }) =>
State::FullPrivilege,
(State::OutOfScope, Event::StaticBorrow{ from: ro }) =>
State::PartialPrivilege {
borrow_count: 1,
borrow_to: [ro.to_owned()].iter().cloned().collect()
},
(State::OutOfScope, Event::MutableBorrow{ .. }) =>
State::FullPrivilege,
(State::OutOfScope, Event::InitRefParam{ param: ro }) => {
match ro {
ResourceAccessPoint::Function(..) => {
panic!("Cannot initialize function as as valid parameter!")
},
ResourceAccessPoint::Owner(..) | ResourceAccessPoint::MutRef(..) => {
State::FullPrivilege
},
ResourceAccessPoint::Struct(..) => {
State::FullPrivilege
},
ResourceAccessPoint::StaticRef(..) => {
State::PartialPrivilege {
borrow_count: 1,
borrow_to: [ro.to_owned()].iter().cloned().collect()
}
}
}
},
(State::FullPrivilege, Event::Move{to: to_ro}) =>
State::ResourceMoved{ move_to: to_ro.to_owned(), move_at_line: event_line },
(State::ResourceMoved{ .. }, Event::Acquire{ .. }) => {
if self.is_mut(hash) {
State::FullPrivilege
}
else { eprintln!("Immutable variable {} cannot reacquire resources!", self.get_name_from_hash(hash).unwrap());
std::process::exit(1);
}
},
(State::FullPrivilege, Event::MutableLend{ to: to_ro }) => {
if self.is_mut(hash) | self.is_mutref(hash) {
State::RevokedPrivilege{ to: None, borrow_to: to_ro.to_owned() }
} else {
State::Invalid
}
},
(State::FullPrivilege, Event::MutableDie{ .. }) =>
State::OutOfScope,
(State::FullPrivilege, Event::Acquire{ from: _ }) | (State::FullPrivilege, Event::Copy{ from: _ }) => {
if self.is_mut(hash) {
State::FullPrivilege
}
else {
State::Invalid
}
},
(State::FullPrivilege, Event::OwnerGoOutOfScope) =>
State::OutOfScope,
(State::FullPrivilege, Event::RefGoOutOfScope) =>
State::OutOfScope,
(State::FullPrivilege, Event::StaticLend{ to: to_ro }) =>
State::PartialPrivilege {
borrow_count: 1,
borrow_to: [(to_ro.to_owned().unwrap())].iter().cloned().collect() },
(State::PartialPrivilege{ .. }, Event::MutableLend{ .. }) =>
State::Invalid,
(State::PartialPrivilege{ borrow_count: current, borrow_to }, Event::StaticLend{ to: to_ro }) => {
let mut new_borrow_to = borrow_to.clone();
new_borrow_to.insert(to_ro.to_owned().unwrap());
State::PartialPrivilege {
borrow_count: current+1,
borrow_to: new_borrow_to,
}
}
(State::PartialPrivilege{ .. }, Event::StaticDie{ .. }) =>
State::OutOfScope,
(State::PartialPrivilege{ borrow_count, borrow_to }, Event::StaticReacquire{ from: ro }) => {
let new_borrow_count = borrow_count - 1;
if borrow_count - 1 == 0 {
State::FullPrivilege
} else {
let mut new_borrow_to = borrow_to.clone();
assert_eq!(new_borrow_to.remove(&ro.to_owned().unwrap()), true); State::PartialPrivilege{
borrow_count: new_borrow_count,
borrow_to: new_borrow_to,
}
}
}
(State::PartialPrivilege{ .. }, Event::OwnerGoOutOfScope) =>
State::OutOfScope,
(State::PartialPrivilege{ .. }, Event::RefGoOutOfScope) =>
State::OutOfScope,
(State::RevokedPrivilege{ .. }, Event::MutableReacquire{ .. }) =>
State::FullPrivilege,
(_, Event::Duplicate { .. }) =>
(*previous_state).clone(),
(_, _) => State::Invalid,
}
}
fn get_states(&self, hash: &u64) -> Vec::<(usize, usize, State)> {
let mut states = Vec::<(usize, usize, State)>::new();
let mut previous_line_number: usize = 1;
let mut prev_state = State::OutOfScope;
for (line_number, event) in self.timelines[hash].history.iter() {
states.push(
(previous_line_number, *line_number, prev_state.clone())
);
prev_state = self.calc_state(&prev_state, &event, *line_number, hash);
previous_line_number = *line_number;
}
states.push(
(previous_line_number, previous_line_number, prev_state.clone())
);
states
}
fn get_state(&self, hash: &u64, _line_number: &usize) -> Option<State> {
match self.timelines.get(hash) {
Some(_timeline) => {
Some(State::OutOfScope)
},
_ => None
}
}
fn append_external_event(&mut self, event: ExternalEvent, line_number: &usize) {
self.preprocess_external_events.push((*line_number, event.clone()));
let resourceaccesspoint = ResourceAccessPoint_extract(&event);
match (resourceaccesspoint.0, resourceaccesspoint.1, &event) {
(Some(ResourceAccessPoint::Function(_)), Some(ResourceAccessPoint::Function(_)), _) => {
},
(Some(ResourceAccessPoint::Function(_from_function)), Some(_to_variable), _) => {
},
(Some(_from_variable), Some(ResourceAccessPoint::Function(_function)),
ExternalEvent::PassByStaticReference{..}) => {
},
(Some(_from_variable), Some(ResourceAccessPoint::Function(_function)),
ExternalEvent::PassByMutableReference{..}) => {
},
(Some(_from_variable), Some(ResourceAccessPoint::Function(_to_function)), _) => {
},
(Some(_from_variable), Some(_to_variable), _) => {
if let Some(event_vec) = self.event_line_map.get_mut(&line_number) {
event_vec.push(event);
} else {
let vec = vec![event];
self.event_line_map.insert(line_number.clone(), vec);
}
},
_ => ()
}
}
fn _append_event(&mut self, resource_access_point: &ResourceAccessPoint, event: Event, line_number: &usize) {
let hash = &resource_access_point.hash();
match self.timelines.get(hash) {
None => {
let timeline = Timeline {
resource_access_point: resource_access_point.clone(),
history: Vec::new(),
};
self.timelines.insert(**hash, timeline);
},
_ => {}
}
match self.timelines.get_mut(hash) {
Some(timeline) => {
timeline.history.push(
(*line_number, event)
);
},
_ => {
panic!("Timeline disappeared right after creation or when we could index it. This is impossible.");
}
}
}
fn append_processed_external_event(&mut self, event: ExternalEvent, line_number: usize) {
self.external_events.push((line_number, event.clone()));
fn maybe_append_event(vd: &mut VisualizationData, resource_access_point: &Option<ResourceAccessPoint>, event: Event, line_number : &usize) {
if let Some(ro) = resource_access_point {
vd._append_event(&ro, event, line_number)
};
}
match event {
ExternalEvent::Move{from: from_ro, to: to_ro} => {
maybe_append_event(self, &to_ro, Event::Acquire{from : from_ro.to_owned()}, &line_number);
maybe_append_event(self, &from_ro, Event::Move{to : to_ro.to_owned()}, &line_number);
},
ExternalEvent::Bind{from: from_ro, to: to_ro} => {
maybe_append_event(self, &to_ro, Event::Acquire{from : from_ro.to_owned()}, &line_number);
maybe_append_event(self, &from_ro, Event::Duplicate{to : to_ro.to_owned()}, &line_number);
},
ExternalEvent::Copy{from: from_ro, to: to_ro} => {
maybe_append_event(self, &to_ro, Event::Copy{from : from_ro.to_owned()}, &line_number);
maybe_append_event(self, &from_ro, Event::Duplicate{to : to_ro.to_owned()}, &line_number);
},
ExternalEvent::StaticBorrow{from: from_ro, to: to_ro} => {
maybe_append_event(self, &from_ro, Event::StaticLend{to : to_ro.to_owned()}, &line_number);
if let Some(some_from_ro) = from_ro {
maybe_append_event(self, &to_ro, Event::StaticBorrow{from : some_from_ro.to_owned()}, &line_number);
}
},
ExternalEvent::StaticDie{from: from_ro, to: to_ro} => {
maybe_append_event(self, &to_ro, Event::StaticReacquire{from : from_ro.to_owned()}, &line_number);
maybe_append_event(self, &from_ro, Event::StaticDie{to : to_ro.to_owned()}, &line_number);
},
ExternalEvent::MutableBorrow{from: from_ro, to: to_ro} => {
maybe_append_event(self, &from_ro, Event::MutableLend{to : to_ro.to_owned()}, &line_number);
if let Some(some_from_ro) = from_ro {
maybe_append_event(self, &to_ro, Event::MutableBorrow{from : some_from_ro.to_owned()}, &line_number);
}
},
ExternalEvent::MutableDie{from: from_ro, to: to_ro} => {
maybe_append_event(self, &to_ro, Event::MutableReacquire{from : from_ro.to_owned()}, &line_number);
maybe_append_event(self, &from_ro, Event::MutableDie{to : to_ro.to_owned()}, &line_number);
},
ExternalEvent::PassByStaticReference{from: from_ro, to: to_ro} => {
maybe_append_event(self, &from_ro.to_owned(), Event::StaticLend{to : to_ro.to_owned()}, &line_number);
if let Some(some_from_ro) = from_ro.to_owned() {
maybe_append_event(self, &to_ro.to_owned(), Event::StaticBorrow{from : some_from_ro.to_owned()}, &line_number);
} else {
eprintln!("Must pass a function to PassByStaticReference.to!");
std::process::exit(1);
}
maybe_append_event(self, &from_ro, Event::StaticReacquire{from : to_ro.to_owned()}, &line_number);
maybe_append_event(self, &to_ro, Event::StaticDie{to : from_ro.to_owned()}, &line_number);
},
ExternalEvent::PassByMutableReference{from: from_ro, to: to_ro} => {
maybe_append_event(self, &from_ro, Event::MutableLend{to : to_ro.to_owned()}, &line_number);
if let Some(some_from_ro) = from_ro.to_owned() {
maybe_append_event(self, &to_ro, Event::MutableBorrow{from : some_from_ro.to_owned()}, &line_number);
} else {
eprintln!("Must pass a function to PassByMutableReference.to!");
std::process::exit(1);
}
maybe_append_event(self, &from_ro, Event::MutableReacquire{from : to_ro.to_owned()}, &line_number);
maybe_append_event(self, &to_ro, Event::MutableDie{to : from_ro.to_owned()}, &line_number);
},
ExternalEvent::InitRefParam{param: ro} => {
maybe_append_event(self, &Some(ro.clone()), Event::InitRefParam{param : ro.to_owned()}, &line_number);
},
ExternalEvent::GoOutOfScope{ro} => {
match ro {
ResourceAccessPoint::Owner(..) => {
maybe_append_event(self, &Some(ro), Event::OwnerGoOutOfScope, &line_number);
},
ResourceAccessPoint::Struct(..) => {
maybe_append_event(self, &Some(ro), Event::OwnerGoOutOfScope, &line_number);
},
ResourceAccessPoint::MutRef(..) => {
maybe_append_event(self, &Some(ro), Event::RefGoOutOfScope, &line_number);
},
ResourceAccessPoint::StaticRef(..) => {
maybe_append_event(self, &Some(ro), Event::RefGoOutOfScope, &line_number);
},
ResourceAccessPoint::Function(func) => {
println!(
"Functions do not go out of scope! We do not expect to see \"{}\" here.",
func.name
);
std::process::exit(1);
}
}
},
}
}
}