| 237 |
237 |
|
arms: u16,
|
| 238 |
238 |
|
/// The fill program under construction, innermost body last.
|
| 239 |
239 |
|
stack: Vec<Vec<Fill>>,
|
|
240 |
+ |
/// The arm site of the member currently being built both ways, if any.
|
|
241 |
+ |
///
|
|
242 |
+ |
/// Set while a member carrying a guarded settling setting is staged, and
|
|
243 |
+ |
/// read by that setting: its guard becomes a read of this site's arm rather
|
|
244 |
+ |
/// than a refusal, and it writes no fill of its own because the wrapper
|
|
245 |
+ |
/// already wrote one.
|
|
246 |
+ |
swapping: Option<u16>,
|
| 240 |
247 |
|
}
|
| 241 |
248 |
|
|
| 242 |
249 |
|
impl Counters {
|
| 407 |
414 |
|
body,
|
| 408 |
415 |
|
} => {
|
| 409 |
416 |
|
if let Some(guard) = guard {
|
|
417 |
+ |
// The member around this one is being built both ways, and this
|
|
418 |
+ |
// setting is what differs between them. Its guard becomes the
|
|
419 |
+ |
// arm the plan asks for; the wrapper wrote the fill.
|
|
420 |
+ |
if !placing(name)
|
|
421 |
+ |
&& let Some(site) = counters.swapping
|
|
422 |
+ |
{
|
|
423 |
+ |
return Ok(Item::Attribute {
|
|
424 |
+ |
name: name.clone(),
|
|
425 |
+ |
args: staged_args(name, args, counters)?,
|
|
426 |
+ |
guard: Some(Guard {
|
|
427 |
+ |
negated: false,
|
|
428 |
+ |
predicate: Predicate::Truth(plan_read("swap", site)),
|
|
429 |
+ |
span: guard.span,
|
|
430 |
+ |
}),
|
|
431 |
+ |
body: items(body, counters)?,
|
|
432 |
+ |
});
|
|
433 |
+ |
}
|
| 410 |
434 |
|
if !placing(name) {
|
| 411 |
435 |
|
return Err(syn::Error::new(
|
| 412 |
436 |
|
guard.span,
|
| 617 |
641 |
|
})],
|
| 618 |
642 |
|
}
|
| 619 |
643 |
|
}
|
|
644 |
+ |
// A member whose own body settles it under a guard: `latched when x`
|
|
645 |
+ |
// inside a chip, which is `chosen`'s case one production over. Built
|
|
646 |
+ |
// both ways and marked as two arms of itself, exactly as a settling
|
|
647 |
+ |
// setting on an argument is.
|
|
648 |
+ |
Item::Emit(emission) if settling_guard(emission).is_some() => {
|
|
649 |
+ |
let guard = settling_guard(emission).expect("just asked");
|
|
650 |
+ |
let site = counters.arms;
|
|
651 |
+ |
counters.arms += 1;
|
|
652 |
+ |
|
|
653 |
+ |
// No scope of its own, for `Fill::Arms`'s reason: both arms' holes
|
|
654 |
+ |
// are numbered at the level around them.
|
|
655 |
+ |
let held = counters.swapping.replace(site);
|
|
656 |
+ |
let staged = self::emission(emission, counters)?;
|
|
657 |
+ |
counters.swapping = held;
|
|
658 |
+ |
counters.wrote(Fill::Swap {
|
|
659 |
+ |
guard: guard.clone(),
|
|
660 |
+ |
});
|
|
661 |
+ |
|
|
662 |
+ |
Item::Marked {
|
|
663 |
+ |
site,
|
|
664 |
+ |
varies: crate::ast::Varies::Arm {
|
|
665 |
+ |
of: 2,
|
|
666 |
+ |
taken: plan_arm(site, 2),
|
|
667 |
+ |
},
|
|
668 |
+ |
body: vec![Item::Emit(staged)],
|
|
669 |
+ |
}
|
|
670 |
+ |
}
|
| 620 |
671 |
|
Item::Emit(emission) => Item::Emit(self::emission(emission, counters)?),
|
| 621 |
672 |
|
})
|
| 622 |
673 |
|
}
|
| 623 |
674 |
|
|
|
675 |
+ |
/// The one guarded settling setting in a member's own body, if it has one.
|
|
676 |
+ |
///
|
|
677 |
+ |
/// A member may settle itself under a guard, which is what `latched when x`
|
|
678 |
+ |
/// inside a chip is: what varies is the markup this statement produces rather
|
|
679 |
+ |
/// than a run of members beside it, so the member becomes two arms of itself.
|
|
680 |
+ |
///
|
|
681 |
+ |
/// Shallow on purpose. It reads the body this emission owns and no deeper: a
|
|
682 |
+ |
/// guard further in belongs to whatever member IS further in, and that member
|
|
683 |
+ |
/// is staged in its own right when the walk reaches it.
|
|
684 |
+ |
fn settling_guard(emission: &Emission) -> Option<&Guard> {
|
|
685 |
+ |
body_of(emission)?.iter().find_map(|item| match item {
|
|
686 |
+ |
Item::Attribute {
|
|
687 |
+ |
guard: Some(guard),
|
|
688 |
+ |
name,
|
|
689 |
+ |
..
|
|
690 |
+ |
} if !placing(name) => Some(guard),
|
|
691 |
+ |
_ => None,
|
|
692 |
+ |
})
|
|
693 |
+ |
}
|
|
694 |
+ |
|
|
695 |
+ |
/// The items a member's own body holds, for the emissions that have one.
|
|
696 |
+ |
///
|
|
697 |
+ |
/// The three placement wrappers carry no body of their own and pass the
|
|
698 |
+ |
/// question to what they place, which is the same reading every other pass over
|
|
699 |
+ |
/// this grammar takes of them.
|
|
700 |
+ |
fn body_of(emission: &Emission) -> Option<&[Item]> {
|
|
701 |
+ |
Some(match emission {
|
|
702 |
+ |
Emission::Simple { body, .. }
|
|
703 |
+ |
| Emission::Chip { body, .. }
|
|
704 |
+ |
| Emission::Screen { body, .. }
|
|
705 |
+ |
| Emission::Row { body, .. }
|
|
706 |
+ |
| Emission::Form { body, .. }
|
|
707 |
+ |
| Emission::Field { body, .. }
|
|
708 |
+ |
| Emission::Act { body, .. }
|
|
709 |
+ |
| Emission::Offers { body, .. }
|
|
710 |
+ |
| Emission::Column { body, .. }
|
|
711 |
+ |
| Emission::Cell { body, .. }
|
|
712 |
+ |
| Emission::Offering { body, .. }
|
|
713 |
+ |
| Emission::Removes { body, .. }
|
|
714 |
+ |
| Emission::Repeats { body, .. }
|
|
715 |
+ |
| Emission::Region { body, .. }
|
|
716 |
+ |
| Emission::Across { body, .. } => body,
|
|
717 |
+ |
Emission::List(body) | Emission::Table(body) | Emission::Cells(body) => body,
|
|
718 |
+ |
Emission::Framed { inner, .. }
|
|
719 |
+ |
| Emission::Beside { inner, .. }
|
|
720 |
+ |
| Emission::At { inner, .. } => {
|
|
721 |
+ |
return body_of(inner);
|
|
722 |
+ |
}
|
|
723 |
+ |
Emission::Guarded { .. }
|
|
724 |
+ |
| Emission::Given { .. }
|
|
725 |
+ |
| Emission::Activate(_)
|
|
726 |
+ |
| Emission::Include(_)
|
|
727 |
+ |
| Emission::IncludeEach(_)
|
|
728 |
+ |
| Emission::Link { .. } => return None,
|
|
729 |
+ |
})
|
|
730 |
+ |
}
|
|
731 |
+ |
|
| 624 |
732 |
|
/// One member's body, with its settling guard reading the plan's arm.
|
| 625 |
733 |
|
///
|
| 626 |
734 |
|
/// Arm 0 is the setting made, which is [`Plan::swap`][swap]'s own reading and
|