1use crate::address::AddressValue;
2use crate::disassembly::context::ContextDatabase;
3use crate::disassembly::pattern::PatternExpression;
4use crate::disassembly::symbol::{Constructor, FixedHandle, Operands, Symbol, SymbolTable, Tokens};
5use crate::disassembly::{Error, IRBuilderArena};
6use crate::space_manager::SpaceManager;
7
8use std::cell::RefCell;
9use std::fmt;
10use std::mem::size_of;
11use std::ops::Range;
12
13pub use bumpalo::collections::String as BString;
14pub use bumpalo::collections::Vec as BVec;
15
16use bumpalo::vec as bvec;
17
18use unsafe_unwrap::UnsafeUnwrap;
19
20const MAX_PARSE_DEPTH: usize = 64 + 1;
21
22pub struct InstructionFormatter<'b, 'c, 'z> {
23 walker: RefCell<ParserWalker<'b, 'c, 'z>>,
24 symbols: &'b SymbolTable,
25 ctor: &'b Constructor,
26}
27
28pub struct MnemonicFormatter<'a, 'b, 'c, 'z> {
29 inner: &'a InstructionFormatter<'b, 'c, 'z>,
30}
31
32pub struct OperandFormatter<'a, 'b, 'c, 'z> {
33 inner: &'a InstructionFormatter<'b, 'c, 'z>,
34}
35
36impl<'b, 'c, 'z> InstructionFormatter<'b, 'c, 'z> {
37 pub fn new(
38 walker: ParserWalker<'b, 'c, 'z>,
39 symbols: &'b SymbolTable,
40 ctor: &'b Constructor,
41 ) -> Self {
42 Self {
43 walker: RefCell::new(walker),
44 symbols,
45 ctor,
46 }
47 }
48
49 pub fn mnemonic<'a>(&'a self) -> MnemonicFormatter<'a, 'b, 'c, 'z> {
50 MnemonicFormatter { inner: self }
51 }
52
53 pub fn mnemonic_str<'az>(&self, irb: &'az IRBuilderArena) -> BString<'az> {
54 bumpalo::format!(in irb.inner(), "{}", self.mnemonic())
55 }
56
57 pub fn operands<'a>(&'a self) -> OperandFormatter<'a, 'b, 'c, 'z> {
58 OperandFormatter { inner: self }
59 }
60
61 pub fn operands_str<'az>(&self, irb: &'az IRBuilderArena) -> BString<'az> {
62 bumpalo::format!(in irb.inner(), "{}", self.operands())
63 }
64
65 pub fn operand_data<'az>(&self, irb: &'az IRBuilderArena) -> Operands<'b, 'az> {
66 self.ctor
67 .operands(irb, &mut self.walker.borrow_mut(), self.symbols)
68 }
69
70 pub fn tokens<'az>(&self, irb: &'az IRBuilderArena) -> (Tokens<'b, 'az>, Tokens<'b, 'az>) {
71 let mut mnemonic_tokens = Tokens::new(irb);
72 self.ctor.mnemonic_tokens(
73 &mut mnemonic_tokens,
74 &mut self.walker.borrow_mut(),
75 self.symbols,
76 );
77
78 let mut body_tokens = Tokens::new(irb);
79 self.ctor.body_tokens(
80 &mut body_tokens,
81 &mut self.walker.borrow_mut(),
82 self.symbols,
83 );
84
85 (mnemonic_tokens, body_tokens)
86 }
87}
88
89impl<'b, 'c, 'z> fmt::Display for InstructionFormatter<'b, 'c, 'z> {
90 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
91 self.ctor
92 .format_mnemonic(f, &mut self.walker.borrow_mut(), self.symbols)?;
93 write!(f, " ")?;
94 self.ctor
95 .format_body(f, &mut self.walker.borrow_mut(), self.symbols)?;
96 Ok(())
97 }
98}
99
100impl<'a, 'b, 'c, 'z> fmt::Display for MnemonicFormatter<'a, 'b, 'c, 'z> {
101 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
102 self.inner.ctor.format_mnemonic(
103 f,
104 &mut self.inner.walker.borrow_mut(),
105 self.inner.symbols,
106 )?;
107 Ok(())
108 }
109}
110
111impl<'a, 'b, 'c, 'z> fmt::Display for OperandFormatter<'a, 'b, 'c, 'z> {
112 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
113 self.inner
114 .ctor
115 .format_body(f, &mut self.inner.walker.borrow_mut(), self.inner.symbols)?;
116 Ok(())
117 }
118}
119
120#[derive(Clone)]
121pub struct ConstructState<'b> {
122 parent: Option<usize>,
123 constructor: Option<&'b Constructor>,
124 handle: Option<FixedHandle<'b>>,
125 resolve: [Option<usize>; 64],
126 length: usize,
127 offset: usize,
128}
129
130impl<'b> ConstructState<'b> {
131 pub fn set_parent(&mut self, parent: usize) {
132 self.parent = Some(parent);
133 }
134}
135
136impl<'b> Default for ConstructState<'b> {
137 fn default() -> Self {
138 Self {
139 parent: None,
140 constructor: None,
141 handle: None,
142 resolve: [None; 64],
143 length: 0,
144 offset: 0,
145 }
146 }
147}
148
149#[derive(Clone)]
150pub struct ContextSet<'b> {
151 triple: &'b Symbol,
152 number: usize,
153 mask: u32,
154 value: u32,
155 point: usize,
156 flow: bool,
157}
158
159#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
160pub enum ParserState {
161 Uninitialised,
162 Disassembly,
163 PCode,
164}
165
166#[derive(Clone)]
167pub struct ParserContext<'b, 'z> {
168 parse_state: ParserState,
169 context: BVec<'z, u32>,
170 context_commit: BVec<'z, ContextSet<'b>>,
171
172 backing: [u8; 16],
173
174 address: AddressValue,
175 next_address: Option<AddressValue>,
176 delay_slot: usize,
178
179 alloc: usize,
180 state: BVec<'z, ConstructState<'b>>,
181}
182
183impl<'b, 'z> ParserContext<'b, 'z> {
184 pub fn empty(arena: &'z IRBuilderArena, space_manager: &'b SpaceManager) -> Self {
185 Self {
186 parse_state: ParserState::Uninitialised,
187 context: BVec::with_capacity_in(2, arena.inner()),
188 context_commit: BVec::with_capacity_in(2, arena.inner()),
189 backing: [0; 16],
190 address: AddressValue::new(space_manager.default_space(), 0),
191 next_address: None,
192 delay_slot: 0,
194 alloc: 1,
195 state: bvec![in arena.inner(); ConstructState::default(); 75],
196 }
197 }
198
199 pub fn new(
200 arena: &'z IRBuilderArena,
201 context_db: &ContextDatabase,
202 address: AddressValue,
203 buffer: &[u8],
204 ) -> Self {
205 let mut backing = [0u8; 16];
206 let length = buffer.len().min(backing.len());
207
208 backing[..length].copy_from_slice(&buffer[..length]);
209
210 let context = context_db.get_context(&address);
211
212 Self {
213 parse_state: ParserState::Uninitialised,
214 context: BVec::from_iter_in(context.iter().map(|v| *v), arena.inner()),
215 backing,
216 context_commit: BVec::with_capacity_in(2, arena.inner()),
217 address,
218 next_address: None,
219 delay_slot: 0,
221 alloc: 1,
222 state: bvec![in arena.inner(); ConstructState::default(); 75], }
224 }
225
226 pub fn reinitialise(
227 &mut self,
228 _arena: &'z IRBuilderArena,
229 context_db: &ContextDatabase,
230 address: AddressValue,
231 buffer: &[u8],
232 ) {
233 let mut backing = [0u8; 16];
234 let length = buffer.len().min(backing.len());
235
236 backing[..length].copy_from_slice(&buffer[..length]);
237
238 self.parse_state = ParserState::Uninitialised;
239 self.backing = backing;
240 self.context.clear();
241 self.context
242 .extend_from_slice(&context_db.get_context(&address));
243 self.context_commit.clear();
244 self.address = address;
245 self.next_address = None;
246 self.delay_slot = 0;
247 self.alloc = 1;
248
249 self.state[0] = Default::default();
251 }
252
253 pub fn allocate_operand(&mut self, parent: Option<usize>) -> usize {
254 let id = self.alloc;
255
256 if self.state.len() <= id {
257 self.state
258 .resize((1 + self.state.len()) * 2, Default::default());
259 }
260
261 let op = unsafe { self.state.get_unchecked_mut(id) };
262
263 op.parent = parent;
264 op.constructor = None;
265 op.handle = None;
266 *unsafe { op.resolve.get_unchecked_mut(0) } = None;
267 op.offset = 0;
268 op.length = 0;
269
270 self.alloc += 1;
271
272 id
273 }
274
275 pub(crate) fn set_constructor(&mut self, point: usize, constructor: &'b Constructor) {
276 unsafe { self.state.get_unchecked_mut(point) }.constructor = Some(constructor);
277 }
278
279 pub(crate) fn set_offset(&mut self, point: usize, offset: usize) {
280 unsafe { self.state.get_unchecked_mut(point) }.offset = offset;
281 }
282
283 pub(crate) fn point(&self, point: usize) -> &ConstructState<'b> {
284 unsafe { self.state.get_unchecked(point) }
285 }
286
287 pub(crate) fn point_mut(&mut self, point: usize) -> &mut ConstructState<'b> {
288 unsafe { self.state.get_unchecked_mut(point) }
289 }
290
291 pub(crate) fn set_handle(&mut self, point: usize, handle: FixedHandle<'b>) {
292 unsafe { self.state.get_unchecked_mut(point) }.handle = Some(handle);
293 }
294
295 pub fn handle(&self, point: usize) -> Option<&FixedHandle<'b>> {
296 self.state[point].handle.as_ref()
297 }
298
299 pub unsafe fn unchecked_handle(&self, point: usize) -> &FixedHandle<'b> {
300 if let Some(ref handle) = self.state.get_unchecked(point).handle {
301 handle
302 } else {
303 unreachable!()
304 }
305 }
306
307 pub fn handle_mut(&mut self, point: usize) -> Option<&mut FixedHandle<'b>> {
308 self.state[point].handle.as_mut()
309 }
310
311 pub fn base_state(&self) -> &ConstructState {
312 &self.state[0]
313 }
314
315 pub fn base_state_mut(&mut self) -> &mut ConstructState<'b> {
316 &mut self.state[0]
317 }
318
319 pub fn instruction_bytes(
320 &self,
321 start: usize,
322 size: usize,
323 offset: usize,
324 ) -> Result<u32, Error> {
325 let offset = offset + start;
326
327 if offset >= self.backing.len() {
328 return Err(Error::InstructionResolution);
329 }
330
331 let size = (self.backing.len() - offset).min(size);
335 let buf = &self.backing[offset..];
336
337 let mut result = 0u32;
338
339 for b in buf.iter().take(size) {
340 result = result << 8;
341 result |= *b as u32;
342 }
343
344 Ok(result)
345 }
346
347 pub fn instruction_bits(&self, start: usize, size: usize, offset: usize) -> Result<u32, Error> {
348 let offset = offset + (start / 8);
349 let start = start % 8;
350 let bytes_size = (start + size - 1) / 8 + 1;
351
352 if offset >= self.backing.len() {
356 return Err(Error::InstructionResolution);
357 }
358
359 let bytes_size = (self.backing.len() - offset).min(bytes_size);
360
361 let buf = &self.backing[offset..];
362 let mut result = 0u32;
363
364 for b in buf.iter().take(bytes_size) {
365 result = result << 8;
366 result |= *b as u32;
367 }
368
369 result = result
370 .checked_shl(8 * (size_of::<u32>() - bytes_size) as u32 + start as u32)
371 .unwrap_or(0);
372 result = result
373 .checked_shr(8 * size_of::<u32>() as u32 - size as u32)
374 .unwrap_or(0);
375
376 Ok(result)
377 }
378
379 pub fn context_bytes(&self, start: usize, size: usize) -> u32 {
380 let start_off = start / size_of::<u32>();
381 let bytes_off = start % size_of::<u32>();
382
383 let unused = size_of::<u32>() - size;
384 let mut result = self.context[start_off];
385
386 result = result << (bytes_off as u32 * 8); result = result >> (unused as u32 * 8); let remaining = (bytes_off + size).checked_sub(size_of::<u32>());
390
391 if remaining.is_some() && remaining.unwrap() > 0 && start_off + 1 < self.context.len() {
392 let mut nresult = self.context[start_off + 1];
393 let unused = size_of::<u32>() - remaining.unwrap();
394 nresult = nresult >> (unused as u32 * 8); result |= nresult;
396 }
397
398 result
399 }
400
401 pub fn context_bits(&self, start: usize, size: usize) -> u32 {
402 let start_off = start / (8 * size_of::<u32>());
403 let bits_off = start % (8 * size_of::<u32>());
404
405 let unused = 8 * size_of::<u32>() - size;
406 let mut result = self.context[start_off];
407
408 result = result.checked_shl(bits_off as u32).unwrap_or(0);
409 result = result.checked_shr(unused as u32).unwrap_or(0);
410
411 let remaining = (bits_off + size).checked_sub(8 * size_of::<u32>());
412
413 if remaining.is_some() && remaining.unwrap() > 0 && start_off + 1 < self.context.len() {
414 let mut nresult = self.context[start_off + 1];
415 let unused = 8 * size_of::<u32>() - remaining.unwrap();
416 nresult = nresult.checked_shr(unused as u32).unwrap_or(0);
417 result |= nresult;
418 }
419
420 result
421 }
422
423 pub fn set_context_word(&mut self, num: usize, value: u32, mask: u32) {
424 self.context[num] = (self.context[num] & !mask) | (mask & value);
425 }
426
427 pub fn add_commit(
428 &mut self,
429 symbol: &'b Symbol,
430 num: usize,
431 mask: u32,
432 point: usize,
433 flow: bool,
434 ) {
435 let set = ContextSet {
436 triple: symbol,
437 number: num,
438 mask,
439 value: self.context[num] & mask,
440 point,
441 flow,
442 };
443 self.context_commit.push(set);
444 }
445
446 pub fn apply_commits<'a, 'c>(
447 &'c mut self,
448 db: &mut ContextDatabase,
449 manager: &'b SpaceManager,
450 symbols: &'b SymbolTable,
451 ) -> Result<(), Error> {
452 if self.context_commit.is_empty() {
453 return Ok(());
454 }
455
456 let curr_address = self.address.clone();
457 let commits = self.context_commit.clone();
458 let mut nwalker = ParserWalker::<'b, 'c, 'z>::new(self);
459
460 for commit in commits {
461 let symbol = commit.triple;
462 let mut address = if let Symbol::Operand { handle_index, .. } = symbol {
463 let handle =
464 unsafe { nwalker.unchecked_handle_ref_via(commit.point, *handle_index) };
465 AddressValue::new(handle.space, handle.offset_offset)
466 } else {
467 let handle = symbol.fixed_handle(&mut nwalker, manager, symbols)?;
468 AddressValue::new(handle.space, handle.offset_offset)
469 };
470
471 if address.is_constant() {
472 let space = unsafe { manager.unchecked_space_by_id(curr_address.space()) };
473 let noffset = address.offset() * space.word_size() as u64;
474 address = AddressValue::new(space, noffset);
475 }
476
477 if commit.flow {
478 db.set_context_change_point(
479 address,
480 commit.number,
481 commit.mask,
482 commit.value,
483 );
484 } else {
485 let naddress = address.clone() + 1usize;
486 if naddress.offset() < address.offset() {
487 db.set_context_change_point(
488 address,
489 commit.number,
490 commit.mask,
491 commit.value,
492 );
493 } else {
494 db.set_context_region(
495 address,
496 Some(naddress),
497 commit.number,
498 commit.mask,
499 commit.value,
500 );
501 }
502 }
503 }
504
505 Ok(())
506 }
507
508 pub fn constructor(&self, point: usize) -> Option<&'b Constructor> {
509 self.state[point].constructor
510 }
511
512 pub unsafe fn unchecked_constructor(&self, point: usize) -> &'b Constructor {
513 self.state.get_unchecked(point).constructor.unsafe_unwrap()
514 }
515
516 pub fn set_next_address(&mut self, address: AddressValue) {
517 self.next_address = Some(address);
518 }
519
520 pub fn set_state(&mut self, state: ParserState) {
521 self.parse_state = state;
522 }
523}
524
525pub struct ParserWalker<'b, 'c, 'z> {
526 ctx: &'c mut ParserContext<'b, 'z>,
527
528 point: Option<usize>,
529 depth: isize,
530 breadcrumb: [usize; MAX_PARSE_DEPTH],
531}
532
533impl<'b, 'c, 'z> ParserWalker<'b, 'c, 'z> {
534 pub fn new(ctx: &'c mut ParserContext<'b, 'z>) -> Self {
535 Self {
536 ctx,
537 point: Some(0),
538 depth: 0,
539 breadcrumb: [0; MAX_PARSE_DEPTH],
540 }
541 }
542
543 pub fn context_mut(&mut self) -> &mut ParserContext<'b, 'z> {
544 self.ctx
545 }
546
547 pub fn base_state(&mut self) {
548 self.point = Some(0);
549 self.depth = 0;
550 self.breadcrumb[0] = 0;
551 }
552
553 pub fn is_state(&self) -> bool {
554 self.point.is_some()
555 }
556
557 pub fn address(&self) -> AddressValue {
558 self.ctx.address.clone()
559 }
560
561 pub unsafe fn unchecked_next_address(&self) -> &AddressValue {
562 if let Some(ref address) = self.ctx.next_address {
563 address
564 } else {
565 unreachable!()
566 }
567 }
568
569 pub fn next_address(&self) -> Option<AddressValue> {
570 self.ctx.next_address.clone()
571 }
572
573 pub unsafe fn unchecked_next2_address(&self) -> &AddressValue {
574 unimplemented!("inst_next2")
575 }
576
577 pub fn next2_address(&self) -> Option<AddressValue> {
578 None
579 }
580
581 pub fn length(&self) -> usize {
582 self.ctx.point(0).length
583 }
584
585 pub fn set_parent_handle(&mut self, handle: FixedHandle<'b>) {
586 self.ctx
587 .set_handle(unsafe { self.point.unsafe_unwrap() }, handle);
588 }
589
590 pub fn parent_handle_mut(&mut self) -> Option<&mut FixedHandle<'b>> {
591 self.ctx.handle_mut(unsafe { self.point.unsafe_unwrap() })
592 }
593
594 pub fn handle(&self, index: usize) -> Result<Option<FixedHandle<'b>>, Error> {
595 let ph = self
596 .point()
597 .ok_or_else(|| Error::InconsistentState)?
598 .resolve[index]
599 .ok_or_else(|| Error::InconsistentState)?;
600 Ok(self.ctx.handle(ph).map(|v| v.clone()))
601 }
602
603 pub fn handle_ref(&self, index: usize) -> Option<&FixedHandle<'b>> {
604 self.point()
605 .and_then(|ctor| ctor.resolve.get(index))
606 .and_then(|v| *v)
607 .and_then(|hidx| self.ctx.handle(hidx))
608 }
609
610 pub fn handle_ref_via(&self, point: usize, index: usize) -> Option<&FixedHandle<'b>> {
611 self.ctx
612 .point(point)
613 .resolve
614 .get(index)
615 .and_then(|v| *v)
616 .and_then(|hidx| self.ctx.handle(hidx))
617 }
618
619 pub unsafe fn unchecked_handle(&self, index: usize) -> FixedHandle<'b> {
620 self.unchecked_handle_ref(index).clone()
621 }
622
623 pub unsafe fn unchecked_handle_ref(&self, index: usize) -> &FixedHandle<'b> {
624 let ph = self
625 .unchecked_point()
626 .resolve
627 .get_unchecked(index)
628 .unsafe_unwrap();
629 self.ctx.unchecked_handle(ph)
630 }
631
632 pub unsafe fn unchecked_handle_ref_via(&self, point: usize, index: usize) -> &FixedHandle<'b> {
633 let ph = self
634 .ctx
635 .point(point)
636 .resolve
637 .get_unchecked(index)
638 .unsafe_unwrap();
639 self.ctx.unchecked_handle(ph)
640 }
641
642 pub fn set_next_address(&mut self, address: AddressValue) {
643 self.ctx.set_next_address(address);
644 }
645
646 pub fn set_state(&mut self, state: ParserState) {
647 self.ctx.set_state(state);
648 }
649
650 pub fn set_current_length(&mut self, length: usize) {
651 self.ctx
652 .point_mut(unsafe { self.point.unsafe_unwrap() })
653 .length = length;
654 }
655
656 pub fn set_delay_slot(&mut self, delay: usize) {
657 self.ctx.delay_slot = delay;
658 }
659
660 pub fn delay_slot(&self) -> usize {
661 self.ctx.delay_slot
662 }
663
664 pub fn calculate_length(&mut self, length: usize, nops: usize) {
684 let index = unsafe { self.point.unsafe_unwrap() };
685 let poff = self.ctx.point(index).offset;
686
687 let length = length + poff;
688 let length = (0..nops).fold(length, |length, id| {
689 let subpt = self.ctx.point(unsafe {
690 self.ctx
691 .state
692 .get_unchecked(index)
693 .resolve
694 .get_unchecked(id)
695 .unsafe_unwrap()
696 });
697 let sub_length = subpt.length + subpt.offset;
698 length.max(sub_length)
699 });
700
701 self.ctx.point_mut(index).length = length - poff;
702 }
703
704 pub fn operand(&self) -> usize {
705 *unsafe { self.breadcrumb.get_unchecked(self.depth as usize) }
706 }
707
708 pub fn allocate_operand(&mut self, id: usize) -> Result<(), Error> {
709 let op = self.ctx.allocate_operand(self.point);
710
711 self.ctx
712 .point_mut(self.point.ok_or_else(|| Error::InconsistentState)?)
713 .resolve[id] = Some(op);
714
715 self.breadcrumb[self.depth as usize] += 1;
716 self.depth += 1;
717
718 self.point = Some(op);
719 self.breadcrumb[self.depth as usize] = 0;
720
721 Ok(())
722 }
723
724 pub(crate) fn unchecked_allocate_operand(&mut self, id: usize) {
725 let op = self.ctx.allocate_operand(self.point);
726
727 *unsafe {
728 self.ctx
729 .point_mut(self.point.unsafe_unwrap())
730 .resolve
731 .get_unchecked_mut(id)
732 } = Some(op);
733
734 *unsafe { self.breadcrumb.get_unchecked_mut(self.depth as usize) } += 1;
735 self.depth += 1;
736
737 self.point = Some(op);
738 *unsafe { self.breadcrumb.get_unchecked_mut(self.depth as usize) } = 0;
739 }
740
741 pub fn push_operand(&mut self, id: usize) -> Result<(), Error> {
742 self.breadcrumb[self.depth as usize] = id + 1;
743 self.depth += 1;
744 self.point = self
745 .ctx
746 .point(self.point.ok_or_else(|| Error::InconsistentState)?)
747 .resolve[id];
748 self.breadcrumb[self.depth as usize] = 0;
749 Ok(())
750 }
751
752 pub(crate) fn unchecked_push_operand(&mut self, id: usize) {
753 *unsafe { self.breadcrumb.get_unchecked_mut(self.depth as usize) } = id + 1;
754 self.depth += 1;
755 self.point = unsafe {
756 *self
757 .ctx
758 .point(self.point.unsafe_unwrap())
759 .resolve
760 .get_unchecked(id)
761 };
762 *unsafe { self.breadcrumb.get_unchecked_mut(self.depth as usize) } = 0;
763 }
764
765 pub fn pop_operand(&mut self) -> Result<(), Error> {
766 self.point = self
767 .ctx
768 .point(self.point.ok_or_else(|| Error::InconsistentState)?)
769 .parent;
770 self.depth -= 1;
771 Ok(())
772 }
773
774 pub(crate) fn unchecked_pop_operand(&mut self) {
775 self.point = unsafe { self.ctx.point(self.point.unsafe_unwrap()) }.parent;
776 self.depth -= 1;
777 }
778
779 pub unsafe fn offset(&self, offset: Option<usize>) -> usize {
780 match offset {
781 None => self.unchecked_point().offset,
782 Some(index) => {
783 let op_index = unsafe {
784 self.unchecked_point()
785 .resolve
786 .get_unchecked(index)
787 .unsafe_unwrap()
788 };
789 let op = self.ctx.point(op_index);
790 op.offset + op.length
791 }
792 }
793 }
794
795 #[inline]
796 pub unsafe fn resolve_with_aux<'d, T, F>(
797 &'d mut self,
798 pat: &'b PatternExpression,
799 ctor: &'b Constructor,
800 index: usize,
801 symbols: &'b SymbolTable,
802 mut f: F,
803 ) -> Result<T, Error>
804 where
805 F: FnMut(
806 &'b PatternExpression,
807 &mut ParserWalker<'b, 'd, 'z>,
808 &'b SymbolTable,
809 ) -> Result<T, Error>,
810 {
811 let mut cur_depth = self.depth;
812 let mut point = self.unchecked_point();
813
814 while point.constructor.map(|ct| ct != ctor).unwrap_or(false) {
815 if cur_depth == 0 {
816 let mut nwalker = ParserWalker::<'b, 'd, 'z>::new(self.context_mut());
817 let mut state = ConstructState::default();
818
819 state.constructor = Some(ctor);
820 nwalker.point = Some(nwalker.ctx.state.len());
821 nwalker.ctx.state.push(state);
822
823 let value = f(pat, &mut nwalker, symbols)?;
824
825 nwalker.ctx.state.pop(); return Ok(value);
828 }
829 cur_depth -= 1;
830 point = self.ctx.point(unsafe { point.parent.unsafe_unwrap() });
831 }
832
833 let sym = unsafe { symbols.unchecked_symbol(ctor.operand(index)) };
834 let offset = if sym.offset_base().is_none() {
835 point.offset + sym.relative_offset()
837 } else {
838 self.ctx
839 .point(unsafe { point.resolve.get_unchecked(index).unsafe_unwrap() })
840 .offset };
842
843 let mut state = ConstructState::default();
844 state.offset = offset;
845 state.constructor = Some(ctor);
846 state.length = point.length;
847
848 let mut nwalker = ParserWalker::<'b, 'd, 'z>::new(self.context_mut());
849
850 nwalker.point = Some(nwalker.ctx.state.len());
851 nwalker.ctx.state.push(state);
852
853 let value = f(pat, &mut nwalker, symbols)?;
854
855 nwalker.ctx.state.pop(); Ok(value)
858 }
859
860 pub unsafe fn resolve_with<'d>(
861 &'d mut self,
862 pat: &'b PatternExpression,
863 ctor: &'b Constructor,
864 index: usize,
865 symbols: &'b SymbolTable,
866 ) -> Result<i64, Error> {
867 self.resolve_with_aux(pat, ctor, index, symbols, |p, w, s| p.value(w, s))
868 }
869
870 pub unsafe fn resolve_with_bits<'d>(
871 &'d mut self,
872 pat: &'b PatternExpression,
873 ctor: &'b Constructor,
874 index: usize,
875 symbols: &'b SymbolTable,
876 ) -> Result<(i64, Option<Range<u32>>), Error> {
877 self.resolve_with_aux(pat, ctor, index, symbols, |p, w, s| p.value_with(w, s))
878 }
879
880 pub fn add_commit(&mut self, symbol: &'b Symbol, num: usize, mask: u32, flow: bool) {
881 let point = unsafe { self.point.unsafe_unwrap() };
882 self.ctx.add_commit(symbol, num, mask, point, flow)
883 }
884
885 pub fn apply_commits(
886 &mut self,
887 db: &mut ContextDatabase,
888 manager: &'b SpaceManager,
889 symbols: &'b SymbolTable,
890 ) -> Result<(), Error> {
891 self.ctx.apply_commits(db, manager, symbols)
892 }
893
894 pub fn set_context_word(&mut self, num: usize, value: u32, mask: u32) {
895 self.ctx.set_context_word(num, value, mask)
896 }
897
898 pub fn set_constructor(&mut self, constructor: &'b Constructor) {
899 self.ctx
900 .set_constructor(unsafe { self.point.unsafe_unwrap() }, constructor)
901 }
902
903 pub fn constructor(&self) -> Result<Option<&'b Constructor>, Error> {
904 if self.point.is_none() {
905 Ok(None)
906 } else {
907 Ok(self
908 .ctx
909 .constructor(self.point.ok_or_else(|| Error::InconsistentState)?))
910 }
911 }
912
913 pub unsafe fn unchecked_constructor(&self) -> &'b Constructor {
914 self.ctx.unchecked_constructor(self.point.unsafe_unwrap())
915 }
916
917 pub fn point(&self) -> Option<&ConstructState<'b>> {
918 self.point.map(|index| self.ctx.point(index))
919 }
920
921 pub unsafe fn unchecked_point(&self) -> &ConstructState<'b> {
922 self.ctx.point(self.point.unsafe_unwrap())
923 }
924
925 pub fn set_offset(&mut self, offset: usize) -> Result<(), Error> {
926 self.ctx
927 .set_offset(self.point.ok_or_else(|| Error::InconsistentState)?, offset);
928 Ok(())
929 }
930
931 pub fn context_bytes(&self, offset: usize, size: usize) -> u32 {
932 self.ctx.context_bytes(offset, size)
933 }
934
935 pub fn context_bits(&self, offset: usize, size: usize) -> u32 {
936 self.ctx.context_bits(offset, size)
937 }
938
939 pub fn instruction_bytes(&self, offset: usize, size: usize) -> Result<u32, Error> {
940 let point = self
941 .ctx
942 .point(self.point.ok_or_else(|| Error::InconsistentState)?);
943 Ok(self.ctx.instruction_bytes(offset, size, point.offset)?)
944 }
945
946 pub unsafe fn unchecked_instruction_bytes(&self, offset: usize, size: usize) -> u32 {
947 let point = self.ctx.point(self.point.unsafe_unwrap());
948 self.ctx
949 .instruction_bytes(offset, size, point.offset)
950 .unwrap()
951 }
952
953 pub fn instruction_bits(&self, offset: usize, size: usize) -> Result<u32, Error> {
954 let point = self
955 .ctx
956 .point(self.point.ok_or_else(|| Error::InconsistentState)?);
957 Ok(self.ctx.instruction_bits(offset, size, point.offset)?)
958 }
959
960 pub unsafe fn unchecked_instruction_bits(&self, offset: usize, size: usize) -> u32 {
961 let point = self.ctx.point(self.point.unsafe_unwrap());
962 self.ctx
963 .instruction_bits(offset, size, point.offset)
964 .unwrap()
965 }
966}