1use crate::{
6 errors::{error::Error, error_kind::ErrorKind},
7 tokens::{token::Token, token_kind::TokenKind},
8 values::value::Value,
9};
10use std::{
11 collections::{HashMap, VecDeque},
12 rc::Rc,
13};
14
15#[derive(Debug)]
16pub struct Code {
17 value_pointer: usize,
18 values: VecDeque<Rc<Value>>,
19 labels: HashMap<String, (usize, usize)>,
20}
21
22impl Code {
23 pub fn new(tokens: VecDeque<Token>) -> Result<Code, Error> {
29 let mut labels = HashMap::new();
30 let mut values = VecDeque::new();
31 let iter = tokens.into_iter().enumerate();
32 let mut label_stack = vec![];
33 for (pos, token) in iter {
34 match &token.kind {
35 TokenKind::Label(name) => {
36 label_stack.push((pos, token.pos, name.to_owned()));
37 values.push_back(Rc::new(token.into()));
38 },
39 TokenKind::End => {
40 match label_stack.pop() {
41 Some((last_start, last_pos, last_name)) => {
42 if labels.insert(last_name, (last_start, pos)).is_some() {
43 return Err(Error::new(ErrorKind::DuplicateLabel, last_pos));
44 } else {
45 values.push_back(Rc::new(token.into()));
46 }
47 },
48 None => return Err(Error::new(ErrorKind::EndWithoutLabel, token.pos)),
49 }
50 },
51 _ => values.push_back(Rc::new(token.into())),
52 };
53 }
54
55 if let Some((_, last_pos, _)) = label_stack.pop() {
56 Err(Error::new(ErrorKind::NoEndOfLabel, last_pos))
57 } else if let Some(&(value_pointer, _)) = labels.get(&"main".to_owned()) {
58 Ok(Code {
59 value_pointer: value_pointer + 1,
60 values,
61 labels,
62 })
63 } else {
64 Err(Error::message_only(ErrorKind::NoMainLabel))
65 }
66 }
67
68 pub fn repl(tokens: VecDeque<Token>) -> Result<Code, Error> {
75 let mut labels = HashMap::new();
76 let mut values = VecDeque::new();
77 let iter = tokens.into_iter().enumerate();
78 let mut label_stack = vec![];
79 for (pos, token) in iter {
80 match &token.kind {
81 TokenKind::Label(name) => {
82 label_stack.push((pos, token.pos, name.to_owned()));
83 values.push_back(Rc::new(token.into()));
84 },
85 TokenKind::End => {
86 match label_stack.pop() {
87 Some((last_start, last_pos, last_name)) => {
88 if labels.insert(last_name, (last_start, pos)).is_some() {
89 return Err(Error::new(ErrorKind::DuplicateLabel, last_pos));
90 } else {
91 values.push_back(Rc::new(token.into()));
92 }
93 },
94 None => return Err(Error::new(ErrorKind::EndWithoutLabel, token.pos)),
95 }
96 },
97 _ => values.push_back(Rc::new(token.into())),
98 };
99 }
100
101 Ok(
102 Code {
103 value_pointer: 0,
104 values,
105 labels,
106 }
107 )
108 }
109
110 pub fn jump(&mut self, jump_location: i64, pos: usize) -> Option<Error> {
117 let upper_bound = self.values.len() as i64;
118 if jump_location >= 0 && jump_location <= upper_bound {
119 self.value_pointer = jump_location as usize;
120 None
121 } else {
122 Some(Error::new(
123 ErrorKind::OutOfBounds(0, self.values.len() + 1),
124 pos,
125 ))
126 }
127 }
128
129 pub fn relative_jump(&mut self, jump_location: i64, pos: usize) -> Option<Error> {
136 let lower_bound = -(self.value_pointer as i64);
137 let upper_bound = self.values.len() as i64;
138 if jump_location >= lower_bound && jump_location <= upper_bound {
139 self.value_pointer += jump_location as usize;
140 None
141 } else {
142 Some(Error::new(
143 ErrorKind::OutOfBounds(lower_bound as usize, self.values.len()),
144 pos,
145 ))
146 }
147 }
148
149 pub fn set_label_location(&mut self, label_name: &String, pos: usize) -> Result<(usize, usize), Error> {
156 if let Some(&(label_pos_start, label_pos_end)) = self.labels.get(label_name) {
157 self.value_pointer = label_pos_start + 1;
158 Ok((label_pos_start, label_pos_end))
159 } else {
160 Err(Error::new(ErrorKind::UndefinedLabel, pos))
161 }
162 }
163
164 pub fn get_label_start_end(&self, label_name: &String) -> Option<(usize, usize)> {
167 self.labels.get(label_name).copied()
168 }
169
170 pub fn get_current_pos(&self) -> usize {
172 self.value_pointer
173 }
174
175 pub fn is_finished(&self) -> bool {
177 self.value_pointer >= self.values.len()
178 }
179}
180
181impl Iterator for Code {
182 type Item = Rc<Value>;
183
184 fn next(&mut self) -> Option<Self::Item> {
185 self.value_pointer += 1;
186
187 self.values.get(self.value_pointer - 1).cloned()
189 }
190}