cpclib_asm/assembler/
stable_ticker.rs

1use crate::error::AssemblerError;
2
3/// Manage the stack of stable counters.
4/// They are updated each time an opcode is visited as well
5#[derive(Default, Clone)]
6pub struct StableTickerCounters {
7    counters: Vec<(String, usize)>
8}
9
10#[allow(missing_docs)]
11impl StableTickerCounters {
12    pub fn new_pass(&mut self) {
13        self.counters.clear();
14    }
15
16    /// Check if a counter with the same name already exists
17    pub fn has_counter<S: AsRef<str>>(&self, name: &S) -> bool {
18        let name = name.as_ref();
19        self.counters.iter().any(|(s, _)| s == name)
20    }
21
22    /// Add a new counter if no counter has the same name
23    pub fn add_counter<S: AsRef<str>>(&mut self, name: &S) -> Result<(), AssemblerError> {
24        let name: String = name.as_ref().to_owned();
25        if self.has_counter(&name) {
26            return Err(AssemblerError::CounterAlreadyExists { symbol: name });
27        }
28        self.counters.push((name, 0));
29        Ok(())
30    }
31
32    /// Release the latest counter (if exists)
33    pub fn release_last_counter(&mut self) -> Option<(String, usize)> {
34        self.counters.pop()
35    }
36
37    pub fn release_counter(&mut self, name: &str) -> Option<(String, usize)> {
38        if let Some(idx) = self.counters.iter().position(|c| c.0 == name) {
39            Some(self.counters.remove(idx))
40        }
41        else {
42            None
43        }
44    }
45
46    /// Update each opened counters by count
47    pub fn update_counters(&mut self, count: usize) {
48        self.counters.iter_mut().for_each(|(_, local_count)| {
49            *local_count += count;
50        });
51    }
52
53    pub fn len(&self) -> usize {
54        self.counters.len()
55    }
56
57    pub fn is_empty(&self) -> bool {
58        self.len() == 0
59    }
60}