1use crate::error::{CompileError, PPError};
6use crate::intern::{InternedStr, StringInterner};
7use crate::macro_def::MacroTable;
8use crate::source::SourceLocation;
9use crate::token::{Token, TokenKind};
10
11pub struct PPExprEvaluator<'a> {
13 tokens: &'a [Token],
14 pos: usize,
15 interner: &'a StringInterner,
16 macros: &'a MacroTable,
17 loc: SourceLocation,
18 defined_id: Option<InternedStr>,
20}
21
22impl<'a> PPExprEvaluator<'a> {
23 pub fn new(
25 tokens: &'a [Token],
26 interner: &'a StringInterner,
27 macros: &'a MacroTable,
28 loc: SourceLocation,
29 ) -> Self {
30 let defined_id = interner.lookup("defined");
32
33 Self {
34 tokens,
35 pos: 0,
36 interner,
37 macros,
38 loc,
39 defined_id,
40 }
41 }
42
43 pub fn evaluate(&mut self) -> Result<i64, CompileError> {
45 let result = self.expr()?;
46 Ok(result)
47 }
48
49 fn current(&self) -> Option<&Token> {
51 self.tokens.get(self.pos)
52 }
53
54 fn current_kind(&self) -> Option<&TokenKind> {
56 self.current().map(|t| &t.kind)
57 }
58
59 fn advance(&mut self) {
61 if self.pos < self.tokens.len() {
62 self.pos += 1;
63 }
64 }
65
66 fn error(&self, msg: &str) -> CompileError {
68 CompileError::Preprocess {
69 loc: self.loc.clone(),
70 kind: PPError::InvalidCondition(msg.to_string()),
71 }
72 }
73
74 fn expr(&mut self) -> Result<i64, CompileError> {
76 let cond = self.logical_or()?;
77
78 if matches!(self.current_kind(), Some(TokenKind::Question)) {
79 self.advance();
80 let then_val = self.expr()?;
81 if !matches!(self.current_kind(), Some(TokenKind::Colon)) {
82 return Err(self.error("expected ':' in ternary expression"));
83 }
84 self.advance();
85 let else_val = self.expr()?;
86 Ok(if cond != 0 { then_val } else { else_val })
87 } else {
88 Ok(cond)
89 }
90 }
91
92 fn logical_or(&mut self) -> Result<i64, CompileError> {
94 let mut left = self.logical_and()?;
95
96 while matches!(self.current_kind(), Some(TokenKind::PipePipe)) {
97 self.advance();
98 let right = self.logical_and()?;
99 left = if left != 0 || right != 0 { 1 } else { 0 };
100 }
101
102 Ok(left)
103 }
104
105 fn logical_and(&mut self) -> Result<i64, CompileError> {
107 let mut left = self.bitwise_or()?;
108
109 while matches!(self.current_kind(), Some(TokenKind::AmpAmp)) {
110 self.advance();
111 let right = self.bitwise_or()?;
112 left = if left != 0 && right != 0 { 1 } else { 0 };
113 }
114
115 Ok(left)
116 }
117
118 fn bitwise_or(&mut self) -> Result<i64, CompileError> {
120 let mut left = self.bitwise_xor()?;
121
122 while matches!(self.current_kind(), Some(TokenKind::Pipe)) {
123 self.advance();
124 let right = self.bitwise_xor()?;
125 left |= right;
126 }
127
128 Ok(left)
129 }
130
131 fn bitwise_xor(&mut self) -> Result<i64, CompileError> {
133 let mut left = self.bitwise_and()?;
134
135 while matches!(self.current_kind(), Some(TokenKind::Caret)) {
136 self.advance();
137 let right = self.bitwise_and()?;
138 left ^= right;
139 }
140
141 Ok(left)
142 }
143
144 fn bitwise_and(&mut self) -> Result<i64, CompileError> {
146 let mut left = self.equality()?;
147
148 while matches!(self.current_kind(), Some(TokenKind::Amp)) {
149 self.advance();
150 let right = self.equality()?;
151 left &= right;
152 }
153
154 Ok(left)
155 }
156
157 fn equality(&mut self) -> Result<i64, CompileError> {
159 let mut left = self.relational()?;
160
161 loop {
162 match self.current_kind() {
163 Some(TokenKind::EqEq) => {
164 self.advance();
165 let right = self.relational()?;
166 left = if left == right { 1 } else { 0 };
167 }
168 Some(TokenKind::BangEq) => {
169 self.advance();
170 let right = self.relational()?;
171 left = if left != right { 1 } else { 0 };
172 }
173 _ => break,
174 }
175 }
176
177 Ok(left)
178 }
179
180 fn relational(&mut self) -> Result<i64, CompileError> {
182 let mut left = self.shift()?;
183
184 loop {
185 match self.current_kind() {
186 Some(TokenKind::Lt) => {
187 self.advance();
188 let right = self.shift()?;
189 left = if left < right { 1 } else { 0 };
190 }
191 Some(TokenKind::Gt) => {
192 self.advance();
193 let right = self.shift()?;
194 left = if left > right { 1 } else { 0 };
195 }
196 Some(TokenKind::LtEq) => {
197 self.advance();
198 let right = self.shift()?;
199 left = if left <= right { 1 } else { 0 };
200 }
201 Some(TokenKind::GtEq) => {
202 self.advance();
203 let right = self.shift()?;
204 left = if left >= right { 1 } else { 0 };
205 }
206 _ => break,
207 }
208 }
209
210 Ok(left)
211 }
212
213 fn shift(&mut self) -> Result<i64, CompileError> {
215 let mut left = self.additive()?;
216
217 loop {
218 match self.current_kind() {
219 Some(TokenKind::LtLt) => {
220 self.advance();
221 let right = self.additive()?;
222 left = left.wrapping_shl((right & 63) as u32);
227 }
228 Some(TokenKind::GtGt) => {
229 self.advance();
230 let right = self.additive()?;
231 left >>= (right & 63) as u32;
233 }
234 _ => break,
235 }
236 }
237
238 Ok(left)
239 }
240
241 fn additive(&mut self) -> Result<i64, CompileError> {
243 let mut left = self.multiplicative()?;
244
245 loop {
246 match self.current_kind() {
247 Some(TokenKind::Plus) => {
248 self.advance();
249 let right = self.multiplicative()?;
250 left = left.wrapping_add(right);
251 }
252 Some(TokenKind::Minus) => {
253 self.advance();
254 let right = self.multiplicative()?;
255 left = left.wrapping_sub(right);
256 }
257 _ => break,
258 }
259 }
260
261 Ok(left)
262 }
263
264 fn multiplicative(&mut self) -> Result<i64, CompileError> {
266 let mut left = self.unary()?;
267
268 loop {
269 match self.current_kind() {
270 Some(TokenKind::Star) => {
271 self.advance();
272 let right = self.unary()?;
273 left = left.wrapping_mul(right);
274 }
275 Some(TokenKind::Slash) => {
276 self.advance();
277 let right = self.unary()?;
278 if right == 0 {
279 return Err(self.error("division by zero"));
280 }
281 left /= right;
282 }
283 Some(TokenKind::Percent) => {
284 self.advance();
285 let right = self.unary()?;
286 if right == 0 {
287 return Err(self.error("modulo by zero"));
288 }
289 left %= right;
290 }
291 _ => break,
292 }
293 }
294
295 Ok(left)
296 }
297
298 fn unary(&mut self) -> Result<i64, CompileError> {
300 match self.current_kind() {
301 Some(TokenKind::Plus) => {
302 self.advance();
303 self.unary()
304 }
305 Some(TokenKind::Minus) => {
306 self.advance();
307 Ok(-self.unary()?)
308 }
309 Some(TokenKind::Bang) => {
310 self.advance();
311 let val = self.unary()?;
312 Ok(if val == 0 { 1 } else { 0 })
313 }
314 Some(TokenKind::Tilde) => {
315 self.advance();
316 Ok(!self.unary()?)
317 }
318 _ => self.primary(),
319 }
320 }
321
322 fn primary(&mut self) -> Result<i64, CompileError> {
324 match self.current_kind().cloned() {
325 Some(TokenKind::IntLit(n)) => {
326 self.advance();
327 Ok(n)
328 }
329 Some(TokenKind::UIntLit(n)) => {
330 self.advance();
331 Ok(n as i64)
332 }
333 Some(TokenKind::CharLit(c)) => {
334 self.advance();
335 Ok(c as i64)
336 }
337 Some(TokenKind::WideCharLit(c)) => {
338 self.advance();
339 Ok(c as i64)
340 }
341 Some(TokenKind::LParen) => {
342 self.advance();
343 let val = self.expr()?;
344 if !matches!(self.current_kind(), Some(TokenKind::RParen)) {
345 return Err(self.error("expected ')'"));
346 }
347 self.advance();
348 Ok(val)
349 }
350 Some(TokenKind::Ident(id)) => {
351 if Some(id) == self.defined_id {
353 self.advance();
354 return self.parse_defined();
355 }
356
357 self.advance();
359 Ok(0)
360 }
361 Some(_) => Err(self.error("unexpected token in preprocessor expression")),
362 None => Err(self.error("unexpected end of expression")),
363 }
364 }
365
366 fn parse_defined(&mut self) -> Result<i64, CompileError> {
368 let has_paren = matches!(self.current_kind(), Some(TokenKind::LParen));
369 if has_paren {
370 self.advance();
371 }
372
373 let name = match self.current_kind() {
376 Some(TokenKind::Ident(id)) => Some(*id),
377 Some(kind) if kind.is_keyword() => {
378 let kw_name = kind.format(self.interner);
381 self.interner.lookup(&kw_name)
382 }
383 _ => return Err(self.error("expected identifier after 'defined'")),
384 };
385 self.advance();
386
387 if has_paren {
388 if !matches!(self.current_kind(), Some(TokenKind::RParen)) {
389 return Err(self.error("expected ')' after identifier in 'defined'"));
390 }
391 self.advance();
392 }
393
394 Ok(match name {
396 Some(n) if self.macros.is_defined(n) => 1,
397 _ => 0,
398 })
399 }
400}
401
402#[cfg(test)]
403mod tests {
404 use super::*;
405 use crate::macro_def::MacroDef;
406 use crate::source::FileId;
407
408 fn make_token(kind: TokenKind) -> Token {
409 Token::new(kind, SourceLocation::default())
410 }
411
412 fn eval_tokens(tokens: &[Token], interner: &StringInterner, macros: &MacroTable) -> i64 {
413 let loc = SourceLocation::new(FileId::default(), 1, 1);
414 let mut eval = PPExprEvaluator::new(tokens, interner, macros, loc);
415 eval.evaluate().unwrap()
416 }
417
418 #[test]
419 fn test_shift_amount_is_masked() {
420 let interner = StringInterner::new();
423 let macros = MacroTable::new();
424
425 let tokens = vec![
427 make_token(TokenKind::IntLit(1)),
428 make_token(TokenKind::LtLt),
429 make_token(TokenKind::IntLit(64)),
430 ];
431 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 1);
432
433 let tokens = vec![
435 make_token(TokenKind::IntLit(1)),
436 make_token(TokenKind::LtLt),
437 make_token(TokenKind::IntLit(65)),
438 ];
439 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 2);
440
441 let tokens = vec![
443 make_token(TokenKind::IntLit(256)),
444 make_token(TokenKind::GtGt),
445 make_token(TokenKind::IntLit(68)),
446 ];
447 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 16);
448 }
449
450 #[test]
451 fn test_simple_number() {
452 let interner = StringInterner::new();
453 let macros = MacroTable::new();
454 let tokens = vec![make_token(TokenKind::IntLit(42))];
455
456 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 42);
457 }
458
459 #[test]
460 fn test_arithmetic() {
461 let interner = StringInterner::new();
462 let macros = MacroTable::new();
463
464 let tokens = vec![
466 make_token(TokenKind::IntLit(2)),
467 make_token(TokenKind::Plus),
468 make_token(TokenKind::IntLit(3)),
469 ];
470 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 5);
471
472 let tokens = vec![
474 make_token(TokenKind::IntLit(10)),
475 make_token(TokenKind::Minus),
476 make_token(TokenKind::IntLit(4)),
477 make_token(TokenKind::Star),
478 make_token(TokenKind::IntLit(2)),
479 ];
480 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 2);
481 }
482
483 #[test]
484 fn test_comparison() {
485 let interner = StringInterner::new();
486 let macros = MacroTable::new();
487
488 let tokens = vec![
490 make_token(TokenKind::IntLit(5)),
491 make_token(TokenKind::Gt),
492 make_token(TokenKind::IntLit(3)),
493 ];
494 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 1);
495
496 let tokens = vec![
498 make_token(TokenKind::IntLit(2)),
499 make_token(TokenKind::EqEq),
500 make_token(TokenKind::IntLit(3)),
501 ];
502 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 0);
503 }
504
505 #[test]
506 fn test_logical() {
507 let interner = StringInterner::new();
508 let macros = MacroTable::new();
509
510 let tokens = vec![
512 make_token(TokenKind::IntLit(1)),
513 make_token(TokenKind::AmpAmp),
514 make_token(TokenKind::IntLit(0)),
515 ];
516 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 0);
517
518 let tokens = vec![
520 make_token(TokenKind::IntLit(1)),
521 make_token(TokenKind::PipePipe),
522 make_token(TokenKind::IntLit(0)),
523 ];
524 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 1);
525 }
526
527 #[test]
528 fn test_ternary() {
529 let interner = StringInterner::new();
530 let macros = MacroTable::new();
531
532 let tokens = vec![
534 make_token(TokenKind::IntLit(1)),
535 make_token(TokenKind::Question),
536 make_token(TokenKind::IntLit(10)),
537 make_token(TokenKind::Colon),
538 make_token(TokenKind::IntLit(20)),
539 ];
540 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 10);
541
542 let tokens = vec![
544 make_token(TokenKind::IntLit(0)),
545 make_token(TokenKind::Question),
546 make_token(TokenKind::IntLit(10)),
547 make_token(TokenKind::Colon),
548 make_token(TokenKind::IntLit(20)),
549 ];
550 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 20);
551 }
552
553 #[test]
554 fn test_defined() {
555 let mut interner = StringInterner::new();
556 let mut macros = MacroTable::new();
557
558 let foo = interner.intern("FOO");
559 let defined = interner.intern("defined");
560 let _ = defined; macros.define(MacroDef::object(foo, vec![], SourceLocation::default()), &interner);
564
565 let tokens = vec![
567 make_token(TokenKind::Ident(interner.lookup("defined").unwrap())),
568 make_token(TokenKind::LParen),
569 make_token(TokenKind::Ident(foo)),
570 make_token(TokenKind::RParen),
571 ];
572 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 1);
573
574 let bar = interner.intern("BAR");
576 let tokens = vec![
577 make_token(TokenKind::Ident(interner.lookup("defined").unwrap())),
578 make_token(TokenKind::LParen),
579 make_token(TokenKind::Ident(bar)),
580 make_token(TokenKind::RParen),
581 ];
582 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 0);
583 }
584
585 #[test]
586 fn test_unary() {
587 let interner = StringInterner::new();
588 let macros = MacroTable::new();
589
590 let tokens = vec![
592 make_token(TokenKind::Minus),
593 make_token(TokenKind::IntLit(5)),
594 ];
595 assert_eq!(eval_tokens(&tokens, &interner, ¯os), -5);
596
597 let tokens = vec![
599 make_token(TokenKind::Bang),
600 make_token(TokenKind::IntLit(0)),
601 ];
602 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 1);
603
604 let tokens = vec![
606 make_token(TokenKind::Bang),
607 make_token(TokenKind::IntLit(1)),
608 ];
609 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 0);
610 }
611
612 #[test]
613 fn test_parentheses() {
614 let interner = StringInterner::new();
615 let macros = MacroTable::new();
616
617 let tokens = vec![
619 make_token(TokenKind::LParen),
620 make_token(TokenKind::IntLit(2)),
621 make_token(TokenKind::Plus),
622 make_token(TokenKind::IntLit(3)),
623 make_token(TokenKind::RParen),
624 make_token(TokenKind::Star),
625 make_token(TokenKind::IntLit(4)),
626 ];
627 assert_eq!(eval_tokens(&tokens, &interner, ¯os), 20);
628 }
629}