use std::slice::Iter;
use crate::base::pos::Line;
use crate::base::symbol::Symbol;
use crate::base::types::ArcType;
use crate::types::VmIndex;
#[derive(Debug, Default, Eq, PartialEq, Clone, Hash)]
#[cfg_attr(feature = "serde_derive", derive(Deserialize, Serialize))]
pub struct SourceMap {
map: Vec<(usize, Line)>,
}
impl SourceMap {
pub fn new() -> SourceMap {
SourceMap { map: Vec::new() }
}
pub fn emit(&mut self, instruction_index: usize, current_line: Line) {
let last_emitted_line = self.map.last().map(|&(_, x)| x);
if last_emitted_line != Some(current_line) {
self.map.push((instruction_index, current_line));
}
}
pub fn close(&mut self, instruction_index: usize, current_line: Option<Line>) {
if let Some(current_line) = current_line.or_else(|| self.map.last().map(|t| t.1)) {
self.map.push((instruction_index, current_line));
}
}
pub fn line(&self, instruction_index: usize) -> Option<Line> {
let p = self
.map
.iter()
.position(|&(index, _)| index > instruction_index)
.unwrap_or(self.map.len());
if p == 0
|| (p == self.map.len()
&& instruction_index >= self.map.last().expect("Empty source_map").0)
{
None
} else {
Some(self.map[p - 1].1)
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
#[cfg_attr(feature = "serde_derive", derive(DeserializeState, SerializeState))]
#[cfg_attr(
feature = "serde_derive",
serde(
deserialize_state = "crate::serialization::DeSeed<'gc>",
de_parameters = "'gc"
)
)]
#[cfg_attr(
feature = "serde_derive",
serde(serialize_state = "crate::serialization::SeSeed")
)]
pub struct Local {
start: usize,
end: usize,
pub index: VmIndex,
#[cfg_attr(
feature = "serde_derive",
serde(state_with = "crate::serialization::symbol")
)]
pub name: Symbol,
#[cfg_attr(
feature = "serde_derive",
serde(state_with = "crate::serialization::borrow")
)]
pub typ: ArcType,
}
#[derive(Debug, Default, Eq, PartialEq, Clone, Hash)]
#[cfg_attr(feature = "serde_derive", derive(DeserializeState, SerializeState))]
#[cfg_attr(
feature = "serde_derive",
serde(
deserialize_state = "crate::serialization::DeSeed<'gc>",
de_parameters = "'gc"
)
)]
#[cfg_attr(
feature = "serde_derive",
serde(serialize_state = "crate::serialization::SeSeed")
)]
pub struct LocalMap {
#[cfg_attr(feature = "serde_derive", serde(state))]
map: Vec<Local>,
}
impl LocalMap {
pub fn new() -> LocalMap {
LocalMap { map: Vec::new() }
}
pub fn emit(&mut self, instruction_index: usize, index: VmIndex, name: Symbol, typ: ArcType) {
self.map.push(Local {
start: instruction_index,
end: instruction_index,
index: index,
name: name,
typ: typ,
});
}
pub fn close(&mut self, instruction_index: usize) {
if let Some(local) = self.map.iter_mut().rev().find(|t| t.start == t.end) {
local.end = instruction_index;
}
}
pub fn locals(&self, instruction_index: usize) -> LocalIter {
LocalIter {
locals: self.map.iter(),
instruction_index: instruction_index,
}
}
}
pub struct LocalIter<'a> {
locals: Iter<'a, Local>,
instruction_index: usize,
}
impl<'a> LocalIter<'a> {
pub fn empty() -> LocalIter<'a> {
LocalIter {
locals: [].iter(),
instruction_index: 0,
}
}
}
impl<'a> Iterator for LocalIter<'a> {
type Item = &'a Local;
fn next(&mut self) -> Option<&'a Local> {
while let Some(local) = self.locals.next() {
if local.start <= self.instruction_index && self.instruction_index < local.end {
return Some(local);
}
}
None
}
}