1use std::{
2 cmp::Ordering,
3 iter,
4 marker::Copy,
5 mem,
6 ops::{Add, AddAssign, Index, IndexMut, Sub},
7};
8
9use smallvec::SmallVec;
10
11use crate::token::TokenDescription;
12
13const PARSING_FUEL: usize = 256;
14
15#[derive(Clone, Debug, PartialEq)]
16pub(crate) struct Program {
17 pub(crate) functions: &'static [Function],
18}
19
20#[derive(Clone, Debug, PartialEq)]
21pub(crate) struct Function {
22 pub(crate) name: &'static str,
23 pub(crate) code: &'static [Instruction],
24 pub(crate) reg_num: usize,
28}
29
30impl Index<Address> for Function {
31 type Output = Instruction;
32
33 fn index(&self, index: Address) -> &Instruction {
34 &self.code[index.0 as usize]
35 }
36}
37
38#[derive(Clone, Copy, Debug, PartialEq)]
39pub(crate) enum Instruction {
40 LoadConst(Register, Value),
41 #[expect(dead_code)]
42 Copy {
43 src: Register,
44 dst: Register,
45 },
46 Sub {
47 lhs: Register,
48 rhs: Register,
49 out: Register,
50 },
51 #[expect(dead_code)]
52 Add {
53 lhs: Register,
54 rhs: Register,
55 out: Register,
56 },
57 Jump {
58 address: Address,
59 },
60 JumpIfZero {
61 cond: Register,
62 address: Address,
63 },
64 JumpIfNonZero {
65 cond: Register,
66 address: Address,
67 },
68 Invert {
69 src: Register,
70 dst: Register,
71 },
72 #[expect(dead_code)]
73 PushArg(Register),
74 Call {
75 function: FunctionId,
76 result: Register,
77 },
78 Return(Register),
79 Peek {
80 tok: TokenDescription,
81 reg: Register,
82 },
83 PeekAny {
84 reg: Register,
85 },
86 Peek2 {
87 tok: TokenDescription,
88 reg: Register,
89 },
90 #[expect(dead_code)]
91 Peek3 {
92 tok: TokenDescription,
93 reg: Register,
94 },
95 BumpToken {
96 tok: TokenDescription,
97 },
98 Bump,
99 Error,
100}
101
102#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
103pub(crate) struct Register(pub u8);
104
105#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
106pub(crate) struct Address(pub u32);
107
108impl Address {
109 #[expect(dead_code)]
110 fn next(self) -> Address {
111 Address(self.0 + 1)
112 }
113
114 fn prev(self) -> Address {
115 Address(self.0 - 1)
116 }
117}
118
119impl AddAssign<u32> for Address {
120 fn add_assign(&mut self, rhs: u32) {
121 self.0 += rhs;
122 }
123}
124
125#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
126pub(crate) struct FunctionId(pub(crate) u32);
127
128#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
129pub(crate) struct Value(pub(crate) i8);
130
131impl Value {
132 const ONE: Value = Value(1);
133 const ZERO: Value = Value(0);
134
135 fn is_zero(self) -> bool {
136 self.0 == 0
137 }
138}
139
140impl Add for Value {
141 type Output = Value;
142
143 fn add(self, rhs: Value) -> Value {
144 Value(self.0 + rhs.0)
145 }
146}
147
148impl Sub for Value {
149 type Output = Value;
150
151 fn sub(self, rhs: Value) -> Value {
152 Value(self.0 - rhs.0)
153 }
154}
155
156#[derive(Clone, Debug)]
157pub struct Interpreter<'code, Span> {
158 program: &'code Program,
159 frame_counter: usize,
161 descr_counter: usize,
163 stack: Vec<StackFrame<'code>>,
164 token_buffer: TokenBuffer<Span>,
165 next_call_args: Vec<Value>,
166}
167
168impl<'code, Span> Interpreter<'code, Span>
169where
170 Span: Copy,
171{
172 pub(crate) fn new(program: &'code Program, main_fn: FunctionId) -> Interpreter<'code, Span> {
173 let mut this = Self {
174 program,
175 frame_counter: 0,
176 descr_counter: 0,
177 stack: Vec::new(),
178 token_buffer: TokenBuffer::EMPTY,
179 next_call_args: Vec::new(),
180 };
181
182 let main_frame = this.create_stack_frame(main_fn);
183 this.stack.push(main_frame);
184
185 this
186 }
187
188 pub fn step(
189 &mut self,
190 token_description: TokenDescription,
191 span: Span,
192 ) -> Result<Transition, (Vec<TokenDescription>, Span)> {
193 let trans = if self.token_buffer.status() == TokenBufferStatus::Full {
194 self.perform_progress()?
195 } else {
196 Transition::empty(self.token_buffer, self.stack.last().unwrap())
197 };
198
199 let reserved_id = self.descr_id();
200 self.token_buffer.push(token_description, span, reserved_id);
201
202 Ok(trans)
203 }
204
205 pub fn finish(&mut self, end_span: Span) -> Result<Transition, (Vec<TokenDescription>, Span)> {
206 self.fill_buffer(end_span);
211
212 let mut trans = Transition::empty(self.token_buffer, self.stack.last().unwrap());
213
214 let mut finish_fuel = PARSING_FUEL;
215 let mut tried = Vec::new();
216 while self.token_buffer.first().unwrap().0 != TokenDescription::Eof {
217 assert!(finish_fuel > 0, "Out of finishing fuel.");
218 finish_fuel -= 1;
219
220 trans += self.perform_progress()?;
221
222 self.fill_buffer(end_span);
224 }
225
226 let mut finish_fuel = PARSING_FUEL;
229 tried.clear();
230 while !self.stack.is_empty() {
231 if finish_fuel == 0 {
232 return Err((Vec::new(), end_span));
233 }
234 finish_fuel -= 1;
235
236 match self.run_instruction(&mut trans, &mut tried) {
237 Ok(()) => {}
238 Err(span) => return Err((tried, span)),
239 };
240
241 self.fill_buffer(end_span);
243 }
244
245 Ok(trans)
246 }
247
248 fn fill_buffer(&mut self, end_span: Span) {
249 while self.token_buffer.status() != TokenBufferStatus::Full {
250 let reserved_id = self.descr_id();
251 self.token_buffer
252 .push(TokenDescription::Eof, end_span, reserved_id);
253 }
254 }
255
256 fn perform_progress(&mut self) -> Result<Transition, (Vec<TokenDescription>, Span)> {
257 let mut fuel = PARSING_FUEL;
258 let mut trans = Transition::empty(self.token_buffer, self.stack.last().unwrap());
259 let mut tried = Vec::<TokenDescription>::new();
260
261 while self.token_buffer.status() == TokenBufferStatus::Full {
262 assert!(fuel > 0, "Out of parsing fuel.");
263 fuel -= 1;
264
265 match self.run_instruction(&mut trans, &mut tried) {
266 Ok(()) => {}
267 Err(span) => return Err((tried, span)),
268 }
269 }
270
271 Ok(trans)
272 }
273
274 fn run_instruction(
275 &mut self,
276 transition: &mut Transition,
277 tried: &mut Vec<TokenDescription>,
278 ) -> Result<(), Span> {
279 let current_frame = match self.stack.last_mut() {
280 Some(frame) => frame,
281 None => {
282 return Err(self.token_buffer.first().unwrap().1);
283 }
284 };
285
286 transition.log_frame_usage(current_frame);
287
288 let current_instr = current_frame[current_frame.ip];
289
290 current_frame.ip += 1;
291
292 match current_instr {
293 Instruction::LoadConst(reg, val) => {
295 current_frame[reg] = val;
296 }
297
298 Instruction::Copy { src, dst } => {
299 current_frame[dst] = current_frame[src];
300 }
301
302 Instruction::Sub { lhs, rhs, out } => {
303 current_frame[out] = current_frame[lhs] - current_frame[rhs];
304 }
305
306 Instruction::Add { lhs, rhs, out } => {
307 current_frame[out] = current_frame[lhs] + current_frame[rhs];
308 }
309
310 Instruction::Jump { address } => {
311 current_frame.ip = address;
312 }
313
314 Instruction::JumpIfZero { cond, address } => {
315 if current_frame[cond].is_zero() {
316 current_frame.ip = address;
317 }
318 }
319
320 Instruction::JumpIfNonZero { cond, address } => {
321 if !current_frame[cond].is_zero() {
322 current_frame.ip = address;
323 }
324 }
325
326 Instruction::Invert { src, dst } => {
327 let out_val = if current_frame[src].is_zero() {
328 Value::ONE
329 } else {
330 Value::ZERO
331 };
332
333 current_frame[dst] = out_val;
334 }
335
336 Instruction::PushArg(reg) => {
337 self.next_call_args.push(current_frame[reg]);
338 }
339
340 Instruction::Call { function, .. } => {
341 let new_frame = self.create_stack_frame(function);
342
343 transition.log_frame_usage(&new_frame);
344 self.stack.push(new_frame);
345
346 return Ok(());
347 }
348
349 Instruction::Return(reg) => {
350 let return_value = current_frame[reg];
351
352 self.stack.pop();
353
354 if let Some(frame) = self.stack.last_mut() {
355 transition.log_frame_usage(frame);
356
357 let call_instr = frame[frame.ip.prev()];
359 let return_reg = match call_instr {
360 Instruction::Call { result, .. } => result,
361 _ => unreachable!(),
362 };
363
364 frame[return_reg] = return_value;
365
366 self.next_call_args.clear();
368 }
369
370 return Ok(());
371 }
372
373 Instruction::Peek { tok, reg } => {
375 tried.push(tok);
376
377 let tok_ = self.token_buffer.first().unwrap().0;
378
379 if tok_ == tok || tok_.try_split_with(tok).is_some() {
380 current_frame[reg] = Value::ONE;
381 } else {
382 current_frame[reg] = Value::ZERO;
383 }
384 }
385
386 Instruction::PeekAny { reg } => {
387 let any = matches!(self.token_buffer.first(), Some((tok, _)) if tok != TokenDescription::Eof);
388
389 if any {
390 current_frame[reg] = Value::ONE;
391 } else {
392 current_frame[reg] = Value::ZERO;
393 }
394 }
395
396 Instruction::Peek2 { tok, reg } => {
397 let tok_ = self.token_buffer.second().unwrap().0;
398 if tok_ == tok {
399 current_frame[reg] = Value::ONE;
400 } else {
401 current_frame[reg] = Value::ZERO;
402 }
403 }
404
405 Instruction::Peek3 { tok, reg } => {
406 let tok_ = self.token_buffer.third().unwrap().0;
407 if tok_ == tok {
408 current_frame[reg] = Value::ONE;
409 } else {
410 current_frame[reg] = Value::ZERO;
411 }
412 }
413
414 Instruction::BumpToken { tok } => {
415 tried.push(tok);
416 let (tok_, span) = self.token_buffer.first().unwrap();
417
418 if tok_ == tok {
419 self.token_buffer.pop_front();
420 } else if let Some(head) = tok_.try_split_with(tok) {
421 let reserved_id = self.descr_id();
422 self.token_buffer.set_head(head, reserved_id);
423 } else {
424 return Err(span);
425 }
426 }
427
428 Instruction::Bump => {
429 self.token_buffer.pop_front();
430 }
431
432 Instruction::Error => {
433 return Err(self.token_buffer.first().unwrap().1);
434 }
435 }
436
437 Ok(())
438 }
439
440 fn create_stack_frame(&mut self, function: FunctionId) -> StackFrame<'code> {
441 let id = self.frame_id();
442
443 let function = &self.program.functions[function.0 as usize];
444 let fn_locals_num = function.reg_num - self.next_call_args.len();
445
446 let registers = iter::once(Value::ZERO) .chain(mem::take(&mut self.next_call_args)) .chain(iter::repeat(Value::ZERO).take(fn_locals_num)) .collect::<Vec<_>>();
450
451 StackFrame {
452 id,
453 function,
454 ip: Address(0),
455 registers,
456 }
457 }
458
459 fn frame_id(&mut self) -> StackFrameId {
460 let id = self.frame_counter;
461 self.frame_counter += 1;
462 StackFrameId(id)
463 }
464
465 fn descr_id(&mut self) -> DescrId {
466 let id_ = DescrId(self.descr_counter);
467 self.descr_counter += 1;
468
469 id_
470 }
471
472 pub fn initial_transition(&self) -> Transition {
473 Transition::empty(self.token_buffer, self.stack.last().unwrap())
474 }
475}
476
477impl<Span> PartialEq for Interpreter<'_, Span>
478where
479 Span: Copy,
480{
481 fn eq(&self, other: &Interpreter<'_, Span>) -> bool {
482 self.frame_counter.eq(&other.frame_counter)
485 && self.descr_counter.eq(&other.descr_counter)
486 && self.stack.eq(&other.stack)
487 && self.token_buffer.eq(&other.token_buffer)
488 && self.next_call_args.eq(&other.next_call_args)
489 }
490}
491impl<Span> Eq for Interpreter<'_, Span> where Span: Copy {}
492
493impl<Span> PartialOrd for Interpreter<'_, Span>
494where
495 Span: Copy,
496{
497 fn partial_cmp(&self, other: &Interpreter<'_, Span>) -> Option<Ordering> {
498 Some(self.cmp(other))
499 }
500}
501
502impl<Span> Ord for Interpreter<'_, Span>
503where
504 Span: Copy,
505{
506 fn cmp(&self, other: &Interpreter<'_, Span>) -> Ordering {
507 self.stack
512 .cmp(&other.stack)
513 .then_with(|| self.token_buffer.cmp(&other.token_buffer))
514 .then_with(|| self.next_call_args.cmp(&other.next_call_args))
515 }
516}
517
518#[derive(Clone, Debug)]
519struct StackFrame<'code> {
520 id: StackFrameId,
523 function: &'code Function,
524 ip: Address,
525 registers: Vec<Value>,
526}
527
528impl PartialOrd for StackFrame<'_> {
529 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
530 Some(self.cmp(other))
531 }
532}
533
534impl Ord for StackFrame<'_> {
535 fn cmp(&self, other: &Self) -> Ordering {
536 self.ip
540 .cmp(&other.ip)
541 .then_with(|| self.registers.cmp(&other.registers))
542 }
543}
544
545impl PartialEq for StackFrame<'_> {
546 fn eq(&self, other: &Self) -> bool {
547 self.cmp(other) == Ordering::Equal
548 }
549}
550
551impl Eq for StackFrame<'_> {}
552
553impl Index<Register> for StackFrame<'_> {
554 type Output = Value;
555
556 fn index(&self, index: Register) -> &Value {
557 &self.registers[index.0 as usize]
558 }
559}
560
561impl IndexMut<Register> for StackFrame<'_> {
562 fn index_mut(&mut self, index: Register) -> &mut Value {
563 &mut self.registers[index.0 as usize]
564 }
565}
566
567impl Index<Address> for StackFrame<'_> {
568 type Output = Instruction;
569
570 fn index(&self, index: Address) -> &Instruction {
571 &self.function[index]
572 }
573}
574
575#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
576pub(crate) struct StackFrameId(pub(crate) usize);
577
578#[derive(Clone, Copy, Debug)]
579enum TokenBuffer<Span> {
580 Zero([TokenBufferSlot<Span>; 0]),
581 One([TokenBufferSlot<Span>; 1]),
582 Two([TokenBufferSlot<Span>; 2]),
583 Three([TokenBufferSlot<Span>; 3]),
584}
585
586impl<Span> Eq for TokenBuffer<Span> where Span: Copy {}
587
588impl<Span> PartialEq for TokenBuffer<Span>
589where
590 Span: Copy,
591{
592 fn eq(&self, other: &Self) -> bool {
593 self.as_slice().eq(other.as_slice())
594 }
595}
596
597impl<Span> PartialOrd for TokenBuffer<Span>
598where
599 Span: Copy,
600{
601 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
602 Some(self.cmp(other))
603 }
604}
605
606impl<Span> Ord for TokenBuffer<Span>
607where
608 Span: Copy,
609{
610 fn cmp(&self, other: &Self) -> Ordering {
611 self.as_slice().cmp(other.as_slice())
612 }
613}
614
615#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
616struct DescrId(usize);
617
618impl<Span> TokenBuffer<Span>
619where
620 Span: Copy,
621{
622 const EMPTY: TokenBuffer<Span> = TokenBuffer::Zero([]);
623
624 fn as_slice(&self) -> &[TokenBufferSlot<Span>] {
625 match self {
626 TokenBuffer::Zero(inner) => inner,
627 TokenBuffer::One(inner) => inner,
628 TokenBuffer::Two(inner) => inner,
629 TokenBuffer::Three(inner) => inner,
630 }
631 }
632
633 fn status(&self) -> TokenBufferStatus {
634 match self {
635 TokenBuffer::Zero(_) => TokenBufferStatus::Empty,
636 TokenBuffer::One(_) => TokenBufferStatus::One,
637 TokenBuffer::Two(_) => TokenBufferStatus::Two,
638 TokenBuffer::Three(_) => TokenBufferStatus::Full,
639 }
640 }
641
642 fn push(&mut self, descr: TokenDescription, span: Span, id: DescrId) {
643 let slot = TokenBufferSlot { descr, span, id };
644
645 match self {
646 TokenBuffer::Zero([]) => {
647 *self = TokenBuffer::One([slot]);
648 }
649 TokenBuffer::One([a]) => {
650 *self = TokenBuffer::Two([*a, slot]);
651 }
652 TokenBuffer::Two([a, b]) => {
653 *self = TokenBuffer::Three([*a, *b, slot]);
654 }
655 TokenBuffer::Three(_) => {
656 panic!("Token buffer is full");
657 }
658 }
659 }
660
661 fn first(&self) -> Option<(TokenDescription, Span)> {
662 match self.as_slice() {
663 [] => None,
664 [TokenBufferSlot { descr, span, .. }, ..] => Some((*descr, *span)),
665 }
666 }
667
668 pub(crate) fn second(&self) -> Option<(TokenDescription, Span)> {
669 match self.as_slice() {
670 [] | [_] => None,
671 [_, TokenBufferSlot { descr, span, .. }, ..] => Some((*descr, *span)),
672 }
673 }
674
675 pub(crate) fn third(&self) -> Option<(TokenDescription, Span)> {
676 match self.as_slice() {
677 [] | [_] | [_, _] => None,
678 [_, _, TokenBufferSlot { descr, span, .. }, ..] => Some((*descr, *span)),
679 }
680 }
681
682 fn pop_front(&mut self) {
683 match self {
684 TokenBuffer::Zero([]) => unreachable!(),
685
686 TokenBuffer::One([_, remaining @ ..]) => {
687 *self = TokenBuffer::Zero(*remaining);
688 }
689
690 TokenBuffer::Two([_, remaining @ ..]) => {
691 *self = TokenBuffer::One(*remaining);
692 }
693
694 TokenBuffer::Three([_, remaining @ ..]) => {
695 *self = TokenBuffer::Two(*remaining);
696 }
697 }
698 }
699
700 fn set_head(&mut self, descr_: TokenDescription, id_: DescrId) {
701 match self {
702 TokenBuffer::Zero([]) => panic!("`set_head` called en empty buffer"),
703
704 TokenBuffer::One([TokenBufferSlot { descr, id, .. }])
705 | TokenBuffer::Two([TokenBufferSlot { descr, id, .. }, _])
706 | TokenBuffer::Three([TokenBufferSlot { descr, id, .. }, _, _]) => {
707 *descr = descr_;
708 *id = id_;
709 }
710 }
711 }
712
713 fn as_small_vec(&self) -> SmallVec<[(TokenDescription, DescrId); 16]> {
714 self.as_slice()
715 .iter()
716 .copied()
717 .map(TokenBufferSlot::forget_span)
718 .collect()
719 }
720}
721
722#[derive(Clone, Copy, Debug)]
723struct TokenBufferSlot<Span> {
724 descr: TokenDescription,
725 span: Span,
726 id: DescrId,
727}
728
729impl<Span> PartialEq for TokenBufferSlot<Span> {
730 fn eq(&self, other: &TokenBufferSlot<Span>) -> bool {
731 (self.descr, self.id).eq(&(other.descr, other.id))
732 }
733}
734
735impl<Span> Eq for TokenBufferSlot<Span> {}
736
737impl<Span> Ord for TokenBufferSlot<Span> {
738 fn cmp(&self, other: &TokenBufferSlot<Span>) -> Ordering {
739 self.descr.cmp(&other.descr)
744 }
745}
746
747impl<Span> PartialOrd for TokenBufferSlot<Span> {
748 fn partial_cmp(&self, other: &TokenBufferSlot<Span>) -> Option<Ordering> {
749 Some(self.cmp(other))
750 }
751}
752
753impl<Span> TokenBufferSlot<Span> {
754 fn forget_span(self) -> (TokenDescription, DescrId) {
755 (self.descr, self.id)
756 }
757}
758
759#[derive(Debug, PartialEq)]
760enum TokenBufferStatus {
761 Empty,
762 One,
763 Two,
764 Full,
765}
766
767#[derive(Clone, Debug, Eq, PartialEq)]
768pub struct Transition {
769 buffer: SmallVec<[(TokenDescription, DescrId); 16]>,
772 stack_top_rev: Vec<FrameDescr>,
774}
775
776impl Transition {
777 fn empty<Span>(buffer: TokenBuffer<Span>, stack_top: &StackFrame) -> Transition
778 where
779 Span: Copy,
780 {
781 let buffer = buffer.as_small_vec();
782 let top = FrameDescr::for_frame(stack_top);
783
784 Transition {
785 buffer,
786 stack_top_rev: vec![top],
787 }
788 }
789
790 fn log_frame_usage(&mut self, frame: &StackFrame) {
794 if frame.id < self.stack_top_rev.last().unwrap().id {
795 self.stack_top_rev.push(FrameDescr::for_frame(frame));
799 }
800 }
801}
802
803impl AddAssign for Transition {
804 fn add_assign(&mut self, rhs: Transition) {
805 let last_known_descr_id = self.buffer.last().map(|(_, id)| id);
808
809 let to_append = match last_known_descr_id {
810 Some(id) => {
811 let idx_to_start_from = rhs
812 .buffer
813 .iter()
814 .enumerate()
815 .find(|(_, (_, id_))| id_ == id)
816 .map(|(idx, _)| idx);
817
818 match idx_to_start_from {
819 Some(idx) if idx + 1 < rhs.buffer.len() => &rhs.buffer[idx + 1..],
820 Some(_) => &[],
821 None => &rhs.buffer,
822 }
823 }
824 None => rhs.buffer.as_slice(),
825 };
826
827 self.buffer.extend_from_slice(to_append);
828
829 let mut to_append = rhs
830 .stack_top_rev
831 .into_iter()
832 .filter(|frame| self.stack_top_rev.last().unwrap().id > frame.id)
833 .collect();
834
835 self.stack_top_rev.append(&mut to_append);
836 }
837}
838
839impl Add for Transition {
840 type Output = Transition;
841
842 fn add(mut self, rhs: Transition) -> Transition {
843 self += rhs;
844 self
845 }
846}
847
848impl PartialOrd for Transition {
849 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
850 Some(self.cmp(other))
851 }
852}
853
854impl Ord for Transition {
855 fn cmp(&self, rhs: &Self) -> Ordering {
856 self.buffer
857 .iter()
858 .map(|(descr, _)| descr)
859 .cmp(rhs.buffer.iter().map(|(descr, _)| descr))
860 .then_with(|| {
861 self.buffer
862 .iter()
863 .map(|(descr, _)| descr)
864 .cmp(rhs.buffer.iter().map(|(descr, _)| descr))
865 })
866 }
867}
868
869#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
870struct FrameDescr {
871 id: StackFrameId,
872 ip: Address,
874 registers: Vec<Value>,
876}
877
878impl FrameDescr {
879 fn for_frame(frame: &StackFrame) -> FrameDescr {
880 FrameDescr {
881 id: frame.id,
882 ip: frame.ip,
883 registers: frame.registers.clone(),
884 }
885 }
886}