1use super::MAX_LINE_LEN;
2use crate::error;
3use crate::lang::{Column, Error, Line, LineNumber, MaxValue};
4use std::collections::{btree_map::Values, BTreeMap, HashMap};
5use std::ops::{Range, RangeInclusive};
6use std::sync::Arc;
7
8#[derive(Debug, Clone, Default)]
9pub struct Listing {
10 source: Arc<BTreeMap<LineNumber, Line>>,
11 pub indirect_errors: Arc<Vec<Error>>,
12 pub direct_errors: Arc<Vec<Error>>,
13}
14
15impl Listing {
16 pub fn clear(&mut self) {
17 self.source = Arc::default();
18 self.indirect_errors = Arc::default();
19 self.direct_errors = Arc::default();
20 }
21
22 pub fn is_empty(&self) -> bool {
23 self.source.is_empty()
24 }
25
26 pub fn insert(&mut self, line: Line) -> Option<Line> {
27 Arc::get_mut(&mut self.source)
28 .unwrap()
29 .insert(line.number(), line)
30 }
31
32 pub fn remove(&mut self, ln: LineNumber) -> Option<Line> {
33 Arc::get_mut(&mut self.source).unwrap().remove(&ln)
34 }
35
36 pub fn remove_range(&mut self, range: RangeInclusive<LineNumber>) -> bool {
37 let to_remove = self
38 .source
39 .range(range)
40 .map(|(k, _)| *k)
41 .collect::<Vec<LineNumber>>();
42 if to_remove.is_empty() {
43 return false;
44 }
45 let source = Arc::get_mut(&mut self.source).unwrap();
46 for line_number in to_remove {
47 source.remove(&line_number);
48 }
49 true
50 }
51
52 pub fn line(&self, num: usize) -> Option<(String, Vec<Range<usize>>)> {
53 if num > LineNumber::max_value() as usize {
54 return None;
55 }
56 let mut range = Some(num as u16)..=Some(num as u16);
57 self.list_line(&mut range)
58 }
59
60 pub fn lines(&self) -> Values<'_, LineNumber, Line> {
61 self.source.values()
62 }
63
64 pub fn load_str(&mut self, line: &str) -> Result<(), Error> {
66 if line.len() > MAX_LINE_LEN {
67 return Err(error!(LineBufferOverflow));
68 }
69 let line = Line::new(line);
70 if line.is_empty() {
71 if !line.is_direct() {
72 Arc::get_mut(&mut self.source)
73 .unwrap()
74 .remove(&line.number());
75 }
76 Ok(())
77 } else if line.is_direct() {
78 Err(error!(DirectStatementInFile))
79 } else {
80 self.insert(line);
81 Ok(())
82 }
83 }
84
85 pub fn list_line(
86 &self,
87 range: &mut RangeInclusive<LineNumber>,
88 ) -> Option<(String, Vec<Range<usize>>)> {
89 let mut source_range = self.source.range(range.clone());
90 if let Some((line_number, line)) = source_range.next() {
91 if line_number < range.end() {
92 if let Some(num) = line_number {
93 *range = Some(num + 1)..=*range.end();
94 }
95 } else {
96 *range = Some(LineNumber::max_value() + 1)..=Some(LineNumber::max_value() + 1);
97 }
98 let columns: Vec<Column> = self
99 .indirect_errors
100 .iter()
101 .filter_map(|e| {
102 if e.line_number() == *line_number {
103 Some(e.column())
104 } else {
105 None
106 }
107 })
108 .collect();
109 return Some((line.to_string(), columns));
110 }
111 None
112 }
113
114 pub fn renum(&mut self, new_start: u16, old_start: u16, step: u16) -> Result<(), Error> {
115 let mut changes: HashMap<u16, u16> = HashMap::default();
116 let mut old_end: u16 = LineNumber::max_value() + 1;
117 let mut new_num = new_start;
118 for (&ln, _) in self.source.iter() {
119 let ln = match ln {
120 Some(ln) => ln,
121 None => return Err(error!(InternalError)),
122 };
123 if ln >= old_start {
124 if old_end <= LineNumber::max_value() && old_end >= new_start {
125 return Err(error!(IllegalFunctionCall));
126 }
127 if new_num > LineNumber::max_value() {
128 return Err(error!(Overflow));
129 }
130 changes.insert(ln, new_num);
131 new_num = match new_num.checked_add(step) {
132 Some(num) => num,
133 None => return Err(error!(Overflow)),
134 };
135 } else {
136 old_end = ln;
137 }
138 }
139 let mut new_source: BTreeMap<LineNumber, Line> = BTreeMap::default();
140 for line in self.lines() {
141 let line = line.renum(&changes);
142 new_source.insert(line.number(), line);
143 }
144 self.source = Arc::from(new_source);
145 Ok(())
146 }
147}