1use std::iter::zip;
11
12use crate::error::CompilationError;
13
14#[derive(Debug)]
17pub enum Token {
18 KeywordExtern,
19 KeywordWithLevel,
20 KeywordPrivilege(Ring),
21 KeywordIsr,
22 KeywordCall,
23
24 Identifier(String),
25
26 LeftParen,
27 RightParen,
28 LeftBracket,
29 RightBracket,
30 Comma,
31 Dollar,
34}
35
36#[derive(Debug)]
40pub struct TokenInfo {
41 token: Token,
42 line: u32,
43 col: u32,
44}
45
46impl TokenInfo {
47 pub fn new(token: Token, line: u32, col: u32) -> TokenInfo {
48 TokenInfo { token, line, col }
49 }
50
51 pub fn borrow_token(&self) -> &Token {
53 &self.token
54 }
55
56 pub fn line(&self) -> u32 {
57 self.line
58 }
59
60 pub fn col(&self) -> u32 {
61 self.col
62 }
63}
64
65impl std::fmt::Display for TokenInfo {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 write!(
68 f,
69 "TokenInfo {{token = {}, line = {}, col = {}}}",
70 self.token, self.line, self.col
71 )
72 }
73}
74
75impl std::fmt::Display for Token {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 match self {
78 Token::KeywordExtern => write!(f, "Token::KeywordExtern"),
79 Token::KeywordWithLevel => write!(f, "Token::KeywordWithLevel"),
80 Token::KeywordPrivilege(p) => write!(f, "Token::KeywordPrivilege({})", p),
81 Token::KeywordIsr => write!(f, "Token::KeywordIsr"),
82 Token::Identifier(id) => write!(f, "Token::Identifier({})", id),
83 Token::LeftParen => write!(f, "Token::LeftParen"),
84 Token::RightParen => write!(f, "Token::RightParen"),
85 Token::LeftBracket => write!(f, "Token::LeftBracket"),
86 Token::RightBracket => write!(f, "Token::RightBracket"),
87 Token::Comma => write!(f, "Token::Comma"),
88 Token::Dollar => write!(f, "Token::Dollar"),
89 Token::KeywordCall => write!(f, "Token::KeywordCall"),
90 }
91 }
92}
93
94#[derive(Debug, Clone, Copy)]
96pub enum Ring {
97 Super,
98 User,
99}
100
101impl PartialEq for Ring {
104 fn eq(&self, other: &Self) -> bool {
105 matches!(
106 (self, other),
107 (Self::Super, Self::Super) | (Self::User, Self::User)
108 )
109 }
110}
111
112impl Eq for Ring {}
113
114impl PartialOrd for Ring {
115 fn lt(&self, other: &Self) -> bool {
116 match (self, other) {
117 (Ring::Super, _) => false,
118 (Ring::User, Ring::Super) => true,
119 (Ring::User, Ring::User) => false,
120 }
121 }
122
123 fn le(&self, other: &Self) -> bool {
124 match (self, other) {
125 (Ring::User, _) => true,
126 (Ring::Super, Ring::Super) => true,
127 (Ring::Super, Ring::User) => false,
128 }
129 }
130
131 fn gt(&self, other: &Self) -> bool {
132 match (self, other) {
133 (Ring::Super, Ring::Super) => false,
134 (Ring::Super, _) => true,
135 (Ring::User, _) => false,
136 }
137 }
138
139 fn ge(&self, other: &Self) -> bool {
140 match (self, other) {
141 (Ring::Super, _) => true,
142 (Ring::User, Ring::User) => true,
143 (Ring::User, _) => false,
144 }
145 }
146
147 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
148 Some(self.cmp(other))
149 }
150}
151
152impl Ord for Ring {
153 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
154 if self.gt(other) {
155 std::cmp::Ordering::Greater
156 } else if self.lt(other) {
157 std::cmp::Ordering::Less
158 } else {
159 std::cmp::Ordering::Equal
160 }
161 }
162
163 fn max(self, other: Self) -> Self
164 where
165 Self: Sized,
166 {
167 if self.gt(&other) { self } else { other }
168 }
169
170 fn min(self, other: Self) -> Self
171 where
172 Self: Sized,
173 {
174 if self.lt(&other) { self } else { other }
175 }
176
177 fn clamp(self, _min: Self, _max: Self) -> Self
178 where
179 Self: Sized,
180 {
181 todo!()
182 }
183}
184
185impl std::fmt::Display for Ring {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 write!(
188 f,
189 "Ring::({})",
190 match self {
191 Ring::User => "User",
192 Ring::Super => "Super",
193 }
194 )
195 }
196}
197
198#[derive(Debug, Clone, Copy)]
200pub enum FuncArgType {
201 U8,
202 I8,
203 U16,
204 I16,
205 U32,
206 I32,
207 U64,
208 I64,
209}
210
211#[derive(Debug)]
212pub struct FuncArg {
213 _name: String,
215
216 type_t: FuncArgType,
218}
219
220impl FuncArg {
221 pub fn new(name: String, type_t: FuncArgType) -> FuncArg {
222 FuncArg {
223 _name: name,
224 type_t,
225 }
226 }
227}
228
229#[derive(Debug)]
230pub struct ExternalFunctionNode {
231 name: String,
232 args: Vec<FuncArg>,
233 privilege: Option<Ring>,
234}
235
236impl ExternalFunctionNode {
237 pub fn new(name: String, args: Vec<FuncArg>, privilege: Option<Ring>) -> ExternalFunctionNode {
238 ExternalFunctionNode {
239 name,
240 args,
241 privilege,
242 }
243 }
244}
245
246#[derive(Debug)]
247pub enum CallArg {
248 Var(String),
249 Dollar,
250}
251
252#[derive(Debug)]
253pub struct ExternalFunctionCall {
254 name: String,
255 args: Vec<CallArg>,
256}
257
258impl ExternalFunctionCall {
259 pub fn new(name: String, args: Vec<CallArg>) -> ExternalFunctionCall {
260 ExternalFunctionCall { name, args }
261 }
262}
263
264#[derive(Debug)]
265pub struct IsrNode {
266 name: String,
267 id: u8,
268 privilege: Option<Ring>,
269 calling_func: Option<ExternalFunctionCall>,
270}
271
272impl IsrNode {
273 pub fn new(
274 name: String,
275 id: u8,
276 privilege: Option<Ring>,
277 calling_func: Option<ExternalFunctionCall>,
278 ) -> IsrNode {
279 IsrNode {
280 name,
281 id,
282 privilege,
283 calling_func,
284 }
285 }
286}
287
288#[derive(Debug)]
289pub enum Ingot {
290 ExternalFunction(ExternalFunctionNode),
291 Isr(IsrNode),
292}
293
294#[derive(Debug)]
295pub struct Ast(Vec<Ingot>);
296
297impl Ast {
298 pub fn new(vec: Vec<Ingot>) -> Ast {
299 Ast(vec)
300 }
301
302 pub fn verify(&self) -> Result<(), CompilationError> {
303 for node in &self.0 {
304 match node {
305 Ingot::ExternalFunction(extern_func) => {
306 if extern_func.args.len() > 1 {
307 eprintln!(
308 "Warning(Definition): Multiple args in external functions not yet supported"
309 );
310 eprintln!("Function: {}", extern_func.name);
311 }
312 }
313 Ingot::Isr(isr) => match &isr.calling_func {
314 None => {
315 eprintln!("Warning: Found ISR with no external function call.",);
316 eprintln!(
317 "This will generate code that effectively ignores this interrupt."
318 );
319 }
320 Some(callsite) => {
321 let calling_func = self
322 .0
323 .iter()
324 .filter_map(|ingot| match ingot {
325 Ingot::Isr(_) => None,
326 Ingot::ExternalFunction(candidate) => {
327 if candidate.name.eq(&callsite.name) {
328 Some(candidate)
329 } else {
330 None
331 }
332 }
333 })
334 .collect::<Vec<&ExternalFunctionNode>>();
335
336 match calling_func[..] {
337 [] => {
338 return Err(CompilationError::new_without_src_info(format!(
339 "Attempt to call an undefined function: {} from isr {}",
340 callsite.name, isr.name
341 )));
342 }
343 [callee] => {
344 if callee.args.len() != callsite.args.len() {
345 return Err(CompilationError::new_without_src_info(format!(
346 "Mismatched arg count between definition and usage of {} within isr {}({})",
347 callee.name, isr.name, isr.id
348 )));
349 }
350
351 if callee.args.len() > 1 {
352 eprintln!(
353 "Warning(Callsite): Multiple args in external functions not yet supported"
354 );
355 eprintln!("Function: {}", callee.name);
356 }
357
358 for (def_arg, call_arg) in zip(&callee.args, &callsite.args) {
359 match (def_arg.type_t, call_arg) {
360 (FuncArgType::I8, CallArg::Dollar) => {
363 return Err(CompilationError::new_without_src_info(
364 format!(
365 "At callsite of {} in isr {}({}): '$' (AKA U8) not safely convertable to I8",
366 callee.name, isr.name, isr.name
367 ),
368 ));
369 }
370 (_, CallArg::Dollar) => {}
371 (_, CallArg::Var(var)) => {
372 return Err(CompilationError::new_without_src_info(
373 format!(
374 "At callsite of {} in isr {}{}: arbitrary variable expressions ({}) not yet supported",
375 callee.name, isr.name, isr.id, var
376 ),
377 ));
378 }
379 }
380 }
381
382 let isr_privilege: Ring = match isr.privilege {
388 None => Ring::Super, Some(p) => p,
390 };
391 let callee_privilege: Ring = match callee.privilege {
392 None => Ring::Super,
393 Some(p) => p,
394 };
395
396 if isr_privilege < callee_privilege {
397 return Err(CompilationError::new_without_src_info(format!(
398 "Attempt to call higher privilege function ({}) from lower privilege ISR ({})",
399 callee.name, isr.name
400 )));
401 }
402 }
403 _ => {
404 return Err(CompilationError::new_without_src_info(format!(
405 "Attempt to call ambiguous function: {} from isr {} (Did you accidentally define {} twice?)",
406 callsite.name, isr.name, callsite.name
407 )));
408 }
409 }
410 }
411 },
412 }
413 }
414
415 Ok(())
416 }
417}