use crate::{
control::cap::mint::ControlOp,
control::lease::planner::LeaseGraphBudget,
eff::{
EffAtom, EffKind, EffStruct,
meta::{MAX_SEGMENT_EFFS, MAX_SEGMENTS},
},
global::{
ControlDesc,
const_dsl::{
ControlMarker, EffList, PolicyMode, ScopeEvent, ScopeId, ScopeMarker, SegmentSummary,
},
},
};
use super::super::images::program::{
CompiledProgramCounts, MAX_COMPILED_PROGRAM_CONTROLS, MAX_COMPILED_PROGRAM_RESOURCES,
MAX_COMPILED_PROGRAM_SCOPES, MAX_COMPILED_PROGRAM_TAP_EVENTS,
};
use super::program_lowering::control_scope_mask_bit;
const MAX_COMPILED_IMAGE_NODES: usize = crate::eff::meta::MAX_EFF_NODES;
const ROUTE_SCOPE_ORDINAL_WORDS: usize = (MAX_COMPILED_IMAGE_NODES + 63) / 64;
const MAX_TRACKED_ROLE_FACTS: usize = u16::BITS as usize;
const MAX_COMPILED_SCOPE_MARKERS: usize = MAX_COMPILED_PROGRAM_SCOPES;
const MAX_COMPILED_ATOM_ROWS: usize = crate::eff::meta::MAX_EFF_NODES;
const MAX_COMPILED_POLICY_ROWS: usize = MAX_SEGMENTS * 2;
const MAX_COMPILED_CONTROL_DESC_ROWS: usize = MAX_SEGMENTS * 2;
const MAX_COMPILED_CONTROL_MARKERS: usize = MAX_SEGMENTS * 2;
#[inline(always)]
const fn reject_dynamic_policy_unsupported() -> ! {
panic!("dynamic policy attached to unsupported control op");
}
#[inline(always)]
const fn checked_role_index(role: u8) -> usize {
let role = role as usize;
if role >= MAX_TRACKED_ROLE_FACTS {
panic!("role index exceeds tracked lowering facts");
}
role
}
#[derive(Clone, Copy)]
pub(crate) struct ProgramSourceLookup {
policy_at: Option<fn(usize) -> Option<PolicyMode>>,
control_desc_at: Option<fn(usize) -> Option<ControlDesc>>,
}
impl ProgramSourceLookup {
#[inline(always)]
pub(crate) const fn empty() -> Self {
Self {
policy_at: None,
control_desc_at: None,
}
}
#[inline(always)]
pub(crate) const fn new(
policy_at: fn(usize) -> Option<PolicyMode>,
control_desc_at: fn(usize) -> Option<ControlDesc>,
) -> Self {
Self {
policy_at: Some(policy_at),
control_desc_at: Some(control_desc_at),
}
}
#[inline(always)]
fn policy_at(self, offset: usize) -> Option<PolicyMode> {
self.policy_at.and_then(|lookup| lookup(offset))
}
#[inline(always)]
fn control_desc_at(self, offset: usize) -> Option<ControlDesc> {
self.control_desc_at.and_then(|lookup| lookup(offset))
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) struct ProgramStamp {
lane0: u64,
lane1: u64,
}
impl ProgramStamp {
const SEED0: u64 = 0xcbf2_9ce4_8422_2325;
const SEED1: u64 = 0x8422_2325_cbf2_9ce4;
const PRIME0: u64 = 0x0000_0100_0000_01b3;
const PRIME1: u64 = 0x9e37_79b1_85eb_ca87;
#[inline(always)]
const fn mix_u64(state: u64, value: u64) -> u64 {
state.wrapping_mul(Self::PRIME0) ^ value.wrapping_mul(Self::PRIME1)
}
#[inline(always)]
const fn mix_eff_struct(mut state: u64, node: EffStruct) -> u64 {
state = Self::mix_u64(state, node.kind as u64);
match node.kind {
EffKind::Pure => state,
EffKind::Atom => {
let atom = node.atom_data();
state = Self::mix_u64(state, atom.from as u64);
state = Self::mix_u64(state, atom.to as u64);
state = Self::mix_u64(state, atom.label as u64);
state = Self::mix_u64(state, atom.is_control as u64);
state = Self::mix_u64(
state,
match atom.resource {
Some(resource) => resource as u64,
None => u8::MAX as u64,
},
);
Self::mix_u64(state, atom.lane as u64)
}
}
}
#[inline(always)]
const fn mix_policy(mut state: u64, policy: PolicyMode) -> u64 {
match policy.dynamic_policy_id() {
None => Self::mix_u64(state, 0),
Some(policy_id) => {
state = Self::mix_u64(state, 1);
state = Self::mix_u64(state, policy_id as u64);
Self::mix_u64(state, policy.scope().raw())
}
}
}
#[inline(always)]
const fn mix_control_desc(mut state: u64, desc: ControlDesc) -> u64 {
state = Self::mix_u64(state, desc.resource_tag() as u64);
state = Self::mix_u64(state, desc.scope_kind() as u64);
state = Self::mix_u64(state, desc.tap_id() as u64);
state = Self::mix_u64(state, desc.shot() as u64);
state = Self::mix_u64(state, desc.path() as u64);
Self::mix_u64(state, desc.op() as u64)
}
#[inline(always)]
pub(crate) const fn words(self) -> [u64; 2] {
[self.lane0, self.lane1]
}
}
#[derive(Clone, Copy)]
struct ProgramImageSegmentData {
atom_mask: u128,
summary: SegmentSummary,
node_len: u16,
atom_row_start: u16,
atom_row_len: u16,
scope_marker_start: u16,
scope_marker_len: u16,
policy_row_start: u16,
policy_row_len: u16,
control_desc_row_start: u16,
control_desc_row_len: u16,
control_marker_start: u16,
control_marker_len: u16,
}
impl ProgramImageSegmentData {
const EMPTY: Self = Self {
atom_mask: 0,
summary: SegmentSummary::EMPTY,
node_len: 0,
atom_row_start: 0,
atom_row_len: 0,
scope_marker_start: 0,
scope_marker_len: 0,
policy_row_start: 0,
policy_row_len: 0,
control_desc_row_start: 0,
control_desc_row_len: 0,
control_marker_start: 0,
control_marker_len: 0,
};
#[inline(always)]
const fn compact_count(value: usize) -> u16 {
if value > u16::MAX as usize {
panic!("lowering segment row count overflow");
}
value as u16
}
}
#[derive(Clone, Copy)]
struct ProgramAtomRow {
offset: u16,
atom: EffAtom,
}
impl ProgramAtomRow {
const EMPTY: Self = Self {
offset: u16::MAX,
atom: EffAtom {
from: 0,
to: 0,
label: 0,
is_control: false,
resource: None,
lane: 0,
},
};
#[inline(always)]
const fn new(offset: usize, atom: EffAtom) -> Self {
Self {
offset: ProgramImageSegmentData::compact_count(offset),
atom,
}
}
}
#[derive(Clone, Copy)]
struct ProgramPolicyRow {
offset: u16,
policy: PolicyMode,
}
impl ProgramPolicyRow {
const EMPTY: Self = Self {
offset: u16::MAX,
policy: PolicyMode::Static,
};
#[inline(always)]
const fn new(offset: usize, policy: PolicyMode) -> Self {
Self {
offset: ProgramImageSegmentData::compact_count(offset),
policy,
}
}
}
#[derive(Clone, Copy)]
struct ProgramControlDescRow {
offset: u16,
desc: Option<ControlDesc>,
}
impl ProgramControlDescRow {
const EMPTY: Self = Self {
offset: u16::MAX,
desc: None,
};
#[inline(always)]
const fn new(offset: usize, desc: ControlDesc) -> Self {
Self {
offset: ProgramImageSegmentData::compact_count(offset),
desc: Some(desc),
}
}
}
#[derive(Clone)]
struct ProgramImageValidationData {
segments: [ProgramImageSegmentData; MAX_SEGMENTS],
len: usize,
atom_rows: [ProgramAtomRow; MAX_COMPILED_ATOM_ROWS],
atom_row_len: usize,
scope_markers: [ScopeMarker; MAX_COMPILED_SCOPE_MARKERS],
scope_marker_len: usize,
policy_rows: [ProgramPolicyRow; MAX_COMPILED_POLICY_ROWS],
policy_row_len: usize,
policy_rows_complete: bool,
control_desc_rows: [ProgramControlDescRow; MAX_COMPILED_CONTROL_DESC_ROWS],
control_desc_row_len: usize,
control_desc_rows_complete: bool,
}
#[derive(Clone)]
struct ProgramImageData {
control_markers: [ControlMarker; MAX_COMPILED_CONTROL_MARKERS],
control_marker_len: usize,
control_markers_complete: bool,
lease_budget: LeaseGraphBudget,
compiled_program_counts: CompiledProgramCounts,
lowering_facts: ProgramLoweringFacts,
control_scope_mask: u8,
stamp: ProgramStamp,
}
#[derive(Clone)]
struct ProgramRoleImageData {
facts: [RoleCompiledFacts; MAX_TRACKED_ROLE_FACTS],
count: u8,
}
#[derive(Clone)]
pub(crate) struct CompiledProgramImage {
validation: ProgramImageValidationData,
program: ProgramImageData,
roles: ProgramRoleImageData,
source_lookup: ProgramSourceLookup,
}
#[derive(Clone, Copy, Default)]
struct ProgramLoweringFacts {
scope_count: u16,
max_active_scope_depth: u16,
max_route_stack_depth: u16,
eff_count: u16,
parallel_enter_count: u16,
route_scope_count: u16,
}
impl ProgramLoweringFacts {
const EMPTY: Self = Self {
scope_count: 0,
max_active_scope_depth: 0,
max_route_stack_depth: 0,
eff_count: 0,
parallel_enter_count: 0,
route_scope_count: 0,
};
}
#[derive(Clone, Copy, Default)]
struct RoleCompiledFacts {
local_step_count: u16,
phase_count: u16,
phase_lane_entry_count: u16,
phase_lane_word_count: u16,
passive_linger_route_scope_count: u16,
active_lane_count: u16,
endpoint_lane_slot_count: u16,
logical_lane_count: u16,
}
impl RoleCompiledFacts {
const EMPTY: Self = Self {
local_step_count: 0,
phase_count: 0,
phase_lane_entry_count: 0,
phase_lane_word_count: 0,
passive_linger_route_scope_count: 0,
active_lane_count: 0,
endpoint_lane_slot_count: 0,
logical_lane_count: 0,
};
}
#[derive(Clone, Copy)]
pub(crate) struct RoleCompiledCounts {
pub(crate) scope_count: usize,
pub(crate) max_active_scope_depth: usize,
pub(crate) max_route_stack_depth: usize,
pub(crate) eff_count: usize,
pub(crate) local_step_count: usize,
pub(crate) phase_count: usize,
pub(crate) phase_lane_entry_count: usize,
pub(crate) phase_lane_word_count: usize,
pub(crate) parallel_enter_count: usize,
pub(crate) route_scope_count: usize,
pub(crate) passive_linger_route_scope_count: usize,
pub(crate) active_lane_count: usize,
pub(crate) endpoint_lane_slot_count: usize,
pub(crate) logical_lane_count: usize,
}
#[derive(Clone, Copy)]
pub(crate) struct CompiledProgramView<'a> {
segments: &'a [ProgramImageSegmentData; MAX_SEGMENTS],
len: usize,
atom_rows: &'a [ProgramAtomRow],
scope_markers: &'a [ScopeMarker],
policy_rows: &'a [ProgramPolicyRow],
policy_rows_complete: bool,
control_desc_rows: &'a [ProgramControlDescRow],
control_desc_rows_complete: bool,
source_lookup: ProgramSourceLookup,
}
impl<'a> CompiledProgramView<'a> {
#[inline(always)]
pub(crate) const fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub(crate) const fn scope_markers(&self) -> &'a [ScopeMarker] {
self.scope_markers
}
#[inline(always)]
const fn segment_slot(offset: usize) -> (usize, usize) {
if offset >= MAX_COMPILED_IMAGE_NODES {
panic!("lowering offset out of bounds");
}
(offset / MAX_SEGMENT_EFFS, offset % MAX_SEGMENT_EFFS)
}
#[inline(always)]
const fn offset_is_atom(&self, offset: usize) -> bool {
if offset >= self.len {
return false;
}
let (segment, local) = Self::segment_slot(offset);
let segment = self.segments[segment];
(segment.atom_mask & (1u128 << local)) != 0
}
#[inline(always)]
pub(crate) const fn node_at(&self, offset: usize) -> EffStruct {
if offset >= self.len {
panic!("lowering node out of bounds");
}
let Some(atom) = self.atom_at(offset) else {
return EffStruct::pure();
};
EffStruct::atom(atom)
}
#[inline(always)]
pub(crate) const fn atom_at(&self, offset: usize) -> Option<EffAtom> {
if !self.offset_is_atom(offset) {
return None;
}
let (segment, _) = Self::segment_slot(offset);
let segment = self.segments[segment];
let mut row_idx = segment.atom_row_start as usize;
let end = row_idx + segment.atom_row_len as usize;
while row_idx < end {
let row = self.atom_rows[row_idx];
if row.offset as usize == offset {
return Some(row.atom);
}
row_idx += 1;
}
panic!("compiled atom mask has no resident atom row");
}
#[inline(always)]
pub(crate) fn policy_at(&self, offset: usize) -> Option<PolicyMode> {
if offset < self.len {
let (segment, _) = Self::segment_slot(offset);
let segment = self.segments[segment];
let mut row_idx = segment.policy_row_start as usize;
let end = row_idx + segment.policy_row_len as usize;
while row_idx < end {
let row = self.policy_rows[row_idx];
if row.offset as usize == offset {
return Some(row.policy);
}
row_idx += 1;
}
if !self.policy_rows_complete {
return self.source_lookup.policy_at(offset);
}
}
None
}
#[inline(always)]
pub(crate) fn control_desc_at(&self, offset: usize) -> Option<ControlDesc> {
if offset < self.len {
let (segment, _) = Self::segment_slot(offset);
let segment = self.segments[segment];
let mut row_idx = segment.control_desc_row_start as usize;
let end = row_idx + segment.control_desc_row_len as usize;
while row_idx < end {
let row = self.control_desc_rows[row_idx];
if row.offset as usize == offset {
return row.desc;
}
row_idx += 1;
}
if !self.control_desc_rows_complete {
return self.source_lookup.control_desc_at(offset);
}
}
None
}
pub(crate) fn first_route_head_dynamic_policy_in_range(
&self,
route_scope: ScopeId,
route_enter_marker_idx: usize,
scope_end: usize,
) -> Option<(PolicyMode, usize, u8, ControlOp)> {
if route_enter_marker_idx >= self.scope_markers.len() {
return None;
}
let route_marker = self.scope_markers[route_enter_marker_idx];
if !matches!(route_marker.event, ScopeEvent::Enter)
|| !matches!(
route_marker.scope_kind,
crate::global::const_dsl::ScopeKind::Route
)
|| route_marker.scope_id.canonical().raw() != route_scope.canonical().raw()
{
return None;
}
let scope_start = route_marker.offset;
if scope_start >= MAX_COMPILED_IMAGE_NODES || scope_start >= scope_end {
return None;
}
let mut marker_idx = route_enter_marker_idx + 1;
let mut active_scope_depth = 1usize;
let mut idx = scope_start;
while idx < scope_end && idx < self.len {
let mut scan_marker_idx = marker_idx;
let mut depth_after_exits = active_scope_depth;
while scan_marker_idx < self.scope_markers.len() {
let marker = self.scope_markers[scan_marker_idx];
if marker.offset != idx {
break;
}
if matches!(marker.event, ScopeEvent::Exit) {
depth_after_exits = depth_after_exits.saturating_sub(1);
}
scan_marker_idx += 1;
}
let mut enter_count = 0usize;
let mut nested_non_policy_enter = false;
let mut next_marker_idx = marker_idx;
while next_marker_idx < self.scope_markers.len() {
let marker = self.scope_markers[next_marker_idx];
if marker.offset != idx {
break;
}
if matches!(marker.event, ScopeEvent::Enter) {
if depth_after_exits == 1
&& !matches!(
marker.scope_kind,
crate::global::const_dsl::ScopeKind::Generic
)
{
nested_non_policy_enter = true;
}
enter_count += 1;
}
next_marker_idx += 1;
}
if depth_after_exits == 1 && !nested_non_policy_enter {
if let Some(policy) = self.policy_at(idx) {
if policy.dynamic_policy_id().is_some() {
let control = match self.control_desc_at(idx) {
Some(control) => control,
None => panic!("dynamic route policy requires controller control op"),
};
if !control.supports_dynamic_policy() {
reject_dynamic_policy_unsupported();
}
return Some((policy, idx, control.resource_tag(), control.op()));
}
}
}
active_scope_depth = depth_after_exits.saturating_add(enter_count);
marker_idx = next_marker_idx;
idx += 1;
}
None
}
}
impl ProgramImageValidationData {
#[inline(always)]
const fn view<'a>(&'a self, source_lookup: ProgramSourceLookup) -> CompiledProgramView<'a> {
CompiledProgramView {
segments: &self.segments,
len: self.len,
atom_rows: unsafe {
core::slice::from_raw_parts(self.atom_rows.as_ptr(), self.atom_row_len)
},
scope_markers: unsafe {
core::slice::from_raw_parts(self.scope_markers.as_ptr(), self.scope_marker_len)
},
policy_rows: unsafe {
core::slice::from_raw_parts(self.policy_rows.as_ptr(), self.policy_row_len)
},
policy_rows_complete: self.policy_rows_complete,
control_desc_rows: unsafe {
core::slice::from_raw_parts(
self.control_desc_rows.as_ptr(),
self.control_desc_row_len,
)
},
control_desc_rows_complete: self.control_desc_rows_complete,
source_lookup,
}
}
}
impl ProgramImageData {
#[cfg(test)]
#[inline(always)]
const fn control_markers(&self) -> &[ControlMarker] {
unsafe {
core::slice::from_raw_parts(self.control_markers.as_ptr(), self.control_marker_len)
}
}
#[inline(always)]
const fn validate_projection_program(&self, scope_marker_len: usize) {
if self.compiled_program_counts.resources > MAX_COMPILED_PROGRAM_RESOURCES {
panic!("CompiledProgram: MAX_RESOURCES exceeded");
}
if self.compiled_program_counts.tap_events > MAX_COMPILED_PROGRAM_TAP_EVENTS {
panic!("CompiledProgram: MAX_TAP_EVENTS exceeded");
}
if self.compiled_program_counts.dynamic_policy_sites > MAX_COMPILED_IMAGE_NODES {
panic!("CompiledProgram: MAX_DYNAMIC_POLICY_SITES exceeded");
}
if self.compiled_program_counts.route_controls > MAX_COMPILED_IMAGE_NODES {
panic!("CompiledProgram: MAX_ROUTE_CONTROLS exceeded");
}
if self.compiled_program_counts.controls > MAX_COMPILED_PROGRAM_CONTROLS {
panic!("CompiledProgram: MAX_CONTROLS exceeded");
}
if scope_marker_len > MAX_COMPILED_PROGRAM_SCOPES {
panic!("CompiledProgram: MAX_SCOPES exceeded");
}
self.lease_budget.validate();
}
}
impl ProgramRoleImageData {
#[inline(always)]
const fn lowering_counts<const ROLE: u8>(
&self,
program: ProgramLoweringFacts,
) -> RoleCompiledCounts {
let role = self.facts[ROLE as usize];
RoleCompiledCounts {
scope_count: program.scope_count as usize,
max_active_scope_depth: program.max_active_scope_depth as usize,
max_route_stack_depth: program.max_route_stack_depth as usize,
eff_count: program.eff_count as usize,
local_step_count: role.local_step_count as usize,
phase_count: role.phase_count as usize,
phase_lane_entry_count: role.phase_lane_entry_count as usize,
phase_lane_word_count: role.phase_lane_word_count as usize,
parallel_enter_count: program.parallel_enter_count as usize,
route_scope_count: program.route_scope_count as usize,
passive_linger_route_scope_count: role.passive_linger_route_scope_count as usize,
active_lane_count: role.active_lane_count as usize,
endpoint_lane_slot_count: role.endpoint_lane_slot_count as usize,
logical_lane_count: role.logical_lane_count as usize,
}
}
}
impl CompiledProgramImage {
#[cfg(test)]
#[inline(always)]
fn scope_marker_eq(
lhs: crate::global::const_dsl::ScopeMarker,
rhs: crate::global::const_dsl::ScopeMarker,
) -> bool {
lhs.offset == rhs.offset
&& lhs.scope_id.raw() == rhs.scope_id.raw()
&& lhs.scope_kind as u8 == rhs.scope_kind as u8
&& lhs.event as u8 == rhs.event as u8
&& lhs.linger == rhs.linger
&& lhs.controller_role == rhs.controller_role
}
#[cfg(test)]
#[inline(always)]
fn control_marker_eq(
lhs: crate::global::const_dsl::ControlMarker,
rhs: crate::global::const_dsl::ControlMarker,
) -> bool {
lhs.offset == rhs.offset
&& lhs.scope_kind as u8 == rhs.scope_kind as u8
&& lhs.tap_id == rhs.tap_id
}
#[cfg(test)]
#[inline(always)]
fn eff_struct_eq(lhs: EffStruct, rhs: EffStruct) -> bool {
if lhs.kind != rhs.kind {
return false;
}
match lhs.kind {
EffKind::Pure => true,
EffKind::Atom => lhs.atom_data() == rhs.atom_data(),
}
}
#[inline(always)]
const fn segment_for_scope_marker_offset(
offset: usize,
current_len: usize,
event: ScopeEvent,
) -> usize {
if offset > current_len || current_len > MAX_COMPILED_IMAGE_NODES {
panic!("lowering marker offset out of bounds");
}
if matches!(event, ScopeEvent::Enter) {
if offset >= MAX_COMPILED_IMAGE_NODES {
panic!("lowering marker offset out of bounds");
}
return offset / MAX_SEGMENT_EFFS;
}
if current_len == 0 {
0
} else if offset == current_len && offset % MAX_SEGMENT_EFFS == 0 {
(offset / MAX_SEGMENT_EFFS) - 1
} else {
offset / MAX_SEGMENT_EFFS
}
}
const fn segment_for_effect_indexed_marker_offset(offset: usize) -> usize {
if offset >= MAX_COMPILED_IMAGE_NODES {
panic!("lowering effect marker offset out of bounds");
}
offset / MAX_SEGMENT_EFFS
}
const fn scan_into(summary: &mut Self, eff_list: &EffList) {
let mut lane0 = ProgramStamp::mix_u64(ProgramStamp::SEED0, eff_list.len() as u64);
let mut lane1 = ProgramStamp::mix_u64(ProgramStamp::SEED1, eff_list.scope_budget() as u64);
let mut scope_count = 0u16;
let mut policy_markers_len = 0u16;
let mut role_count = 0usize;
let mut route_scope_ordinals = [0u64; ROUTE_SCOPE_ORDINAL_WORDS];
let mut lease_budget = LeaseGraphBudget::new();
summary.program.lowering_facts.eff_count = eff_list.len() as u16;
let mut segment = 0usize;
while segment < eff_list.segment_count() {
let segment_start = EffList::segment_start(segment);
let segment_len = eff_list.segment_len(segment);
summary.validation.segments[segment].summary = eff_list.segment_summary(segment);
summary.validation.segments[segment].node_len =
ProgramImageSegmentData::compact_count(segment_len);
let mut local = 0usize;
while local < segment_len {
let idx = segment_start + local;
let node = eff_list.node_at(idx);
lane0 = ProgramStamp::mix_u64(lane0, idx as u64);
lane1 = ProgramStamp::mix_eff_struct(lane1, node);
let policy = if let Some((policy, _scope)) = eff_list.policy_with_scope(idx) {
let row_idx = summary.validation.policy_row_len;
if row_idx < MAX_COMPILED_POLICY_ROWS {
summary.validation.policy_rows[row_idx] =
ProgramPolicyRow::new(idx, policy);
summary.validation.policy_row_len += 1;
if summary.validation.segments[segment].policy_row_len == 0 {
summary.validation.segments[segment].policy_row_start =
ProgramImageSegmentData::compact_count(row_idx);
}
summary.validation.segments[segment].policy_row_len =
ProgramImageSegmentData::compact_count(
summary.validation.segments[segment]
.policy_row_len
.saturating_add(1) as usize,
);
} else {
summary.validation.policy_rows_complete = false;
}
policy_markers_len = policy_markers_len.saturating_add(1);
lane0 = ProgramStamp::mix_u64(lane0, idx as u64);
lane1 = ProgramStamp::mix_policy(lane1, policy);
policy
} else {
PolicyMode::Static
};
let mut current_control_desc = None;
if let Some(spec) = eff_list.control_spec_at(idx) {
let desc = ControlDesc::from_static(spec).with_sites(
crate::eff::EffIndex::from_dense_ordinal(idx),
ControlDesc::STATIC_POLICY_SITE,
);
current_control_desc = Some(desc);
let row_idx = summary.validation.control_desc_row_len;
if row_idx < MAX_COMPILED_CONTROL_DESC_ROWS {
summary.validation.control_desc_rows[row_idx] =
ProgramControlDescRow::new(idx, desc);
summary.validation.control_desc_row_len += 1;
if summary.validation.segments[segment].control_desc_row_len == 0 {
summary.validation.segments[segment].control_desc_row_start =
ProgramImageSegmentData::compact_count(row_idx);
}
summary.validation.segments[segment].control_desc_row_len =
ProgramImageSegmentData::compact_count(
summary.validation.segments[segment]
.control_desc_row_len
.saturating_add(1) as usize,
);
} else {
summary.validation.control_desc_rows_complete = false;
}
lane0 = ProgramStamp::mix_u64(lane0, idx as u64);
lane1 = ProgramStamp::mix_control_desc(lane1, desc);
}
if matches!(node.kind, EffKind::Atom) {
let atom = node.atom_data();
summary.validation.segments[segment].atom_mask |= 1u128 << local;
let row_idx = summary.validation.atom_row_len;
if row_idx >= MAX_COMPILED_ATOM_ROWS {
panic!("CompiledProgram: atom side table exceeded");
}
summary.validation.atom_rows[row_idx] = ProgramAtomRow::new(idx, atom);
summary.validation.atom_row_len += 1;
if summary.validation.segments[segment].atom_row_len == 0 {
summary.validation.segments[segment].atom_row_start =
ProgramImageSegmentData::compact_count(row_idx);
}
summary.validation.segments[segment].atom_row_len =
ProgramImageSegmentData::compact_count(
summary.validation.segments[segment]
.atom_row_len
.saturating_add(1) as usize,
);
let from = checked_role_index(atom.from);
let to = checked_role_index(atom.to);
summary.roles.facts[from].local_step_count =
summary.roles.facts[from].local_step_count.saturating_add(1);
if to != from {
summary.roles.facts[to].local_step_count =
summary.roles.facts[to].local_step_count.saturating_add(1);
}
if from + 1 > role_count {
role_count = from + 1;
}
if to + 1 > role_count {
role_count = to + 1;
}
lease_budget = lease_budget.include_atom(current_control_desc, policy);
if atom.is_control {
if policy.is_dynamic()
&& let Some(control_spec) = current_control_desc
&& !control_spec.supports_dynamic_policy()
{
reject_dynamic_policy_unsupported();
}
if atom.resource.is_some() {
summary.program.compiled_program_counts.resources += 1;
}
} else if !policy.is_static() && !matches!(policy, PolicyMode::Dynamic { .. }) {
panic!("static policy attached to non-control atom");
}
if policy.is_dynamic() {
summary.program.compiled_program_counts.dynamic_policy_sites += 1;
}
}
local += 1;
}
segment += 1;
}
let src_scope_markers = eff_list.scope_markers();
let mut scope_idx = 0usize;
let mut active_scope_depth = 0u16;
let mut max_active_scope_depth = 0u16;
let mut active_route_depth = 0u16;
let mut max_route_depth = 0u16;
while scope_idx < src_scope_markers.len() {
let marker = src_scope_markers[scope_idx];
if scope_idx >= MAX_COMPILED_SCOPE_MARKERS {
panic!("CompiledProgram: scope marker table exceeded");
}
summary.validation.scope_markers[scope_idx] = marker;
let marker_segment =
Self::segment_for_scope_marker_offset(marker.offset, eff_list.len(), marker.event);
if summary.validation.segments[marker_segment].scope_marker_len == 0 {
summary.validation.segments[marker_segment].scope_marker_start =
ProgramImageSegmentData::compact_count(scope_idx);
}
summary.validation.segments[marker_segment].scope_marker_len =
ProgramImageSegmentData::compact_count(
summary.validation.segments[marker_segment]
.scope_marker_len
.saturating_add(1) as usize,
);
if matches!(marker.event, ScopeEvent::Enter) {
scope_count = scope_count.saturating_add(1);
active_scope_depth = active_scope_depth.saturating_add(1);
if active_scope_depth > max_active_scope_depth {
max_active_scope_depth = active_scope_depth;
}
if matches!(
marker.scope_kind,
crate::global::const_dsl::ScopeKind::Parallel
) {
summary.program.lowering_facts.parallel_enter_count = summary
.program
.lowering_facts
.parallel_enter_count
.saturating_add(1);
} else if matches!(
marker.scope_kind,
crate::global::const_dsl::ScopeKind::Route
) {
active_route_depth = active_route_depth.saturating_add(1);
if active_route_depth > max_route_depth {
max_route_depth = active_route_depth;
}
let ordinal = marker.scope_id.local_ordinal() as usize;
let word = ordinal / 64;
let bit = ordinal % 64;
if word >= route_scope_ordinals.len() {
panic!("route scope ordinal overflow");
}
let mask = 1u64 << bit;
if (route_scope_ordinals[word] & mask) == 0 {
route_scope_ordinals[word] |= mask;
summary.program.lowering_facts.route_scope_count = summary
.program
.lowering_facts
.route_scope_count
.saturating_add(1);
summary.program.compiled_program_counts.route_controls =
summary.program.lowering_facts.route_scope_count as usize;
if marker.linger
&& let Some(controller_role) = marker.controller_role
{
let mut role_idx = 0usize;
while role_idx < summary.roles.facts.len() {
if role_idx != controller_role as usize {
summary.roles.facts[role_idx]
.passive_linger_route_scope_count = summary.roles.facts
[role_idx]
.passive_linger_route_scope_count
.saturating_add(1);
}
role_idx += 1;
}
}
}
}
} else {
if matches!(
marker.scope_kind,
crate::global::const_dsl::ScopeKind::Route
) {
active_route_depth = active_route_depth.saturating_sub(1);
}
active_scope_depth = active_scope_depth.saturating_sub(1);
}
lane0 = ProgramStamp::mix_u64(lane0, scope_idx as u64);
lane0 = ProgramStamp::mix_u64(lane0, marker.offset as u64);
lane0 = ProgramStamp::mix_u64(lane0, marker.scope_id.raw());
lane0 = ProgramStamp::mix_u64(lane0, marker.scope_kind as u64);
lane1 = ProgramStamp::mix_u64(lane1, marker.event as u64);
lane1 = ProgramStamp::mix_u64(lane1, marker.linger as u64);
lane1 = ProgramStamp::mix_u64(
lane1,
match marker.controller_role {
Some(role) => role as u64,
None => u8::MAX as u64,
},
);
if let Some(controller_role) = marker.controller_role {
let controller_role = checked_role_index(controller_role);
if controller_role + 1 > role_count {
role_count = controller_role + 1;
}
}
scope_idx += 1;
}
let mut role_idx = 0usize;
while role_idx < role_count {
let exact_facts = {
let view = summary.validation.view(ProgramSourceLookup::empty());
super::seal::exact_role_phase_facts(eff_list, view.scope_markers(), role_idx as u8)
};
summary.roles.facts[role_idx].phase_count = exact_facts.phase_count;
summary.roles.facts[role_idx].phase_lane_entry_count =
exact_facts.phase_lane_entry_count;
summary.roles.facts[role_idx].phase_lane_word_count = exact_facts.phase_lane_word_count;
summary.roles.facts[role_idx].active_lane_count = exact_facts.active_lane_count;
summary.roles.facts[role_idx].endpoint_lane_slot_count =
exact_facts.endpoint_lane_slot_count;
summary.roles.facts[role_idx].logical_lane_count = exact_facts.logical_lane_count;
role_idx += 1;
}
let src_control_markers = eff_list.control_markers();
summary.program.compiled_program_counts.controls = src_control_markers.len();
let mut control_idx = 0usize;
while control_idx < src_control_markers.len() {
let marker = src_control_markers[control_idx];
if control_idx < MAX_COMPILED_CONTROL_MARKERS {
summary.program.control_markers[control_idx] = marker;
summary.program.control_marker_len += 1;
let marker_segment =
Self::segment_for_effect_indexed_marker_offset(marker.offset as usize);
if summary.validation.segments[marker_segment].control_marker_len == 0 {
summary.validation.segments[marker_segment].control_marker_start =
ProgramImageSegmentData::compact_count(control_idx);
}
summary.validation.segments[marker_segment].control_marker_len =
ProgramImageSegmentData::compact_count(
summary.validation.segments[marker_segment]
.control_marker_len
.saturating_add(1) as usize,
);
} else {
summary.program.control_markers_complete = false;
}
summary.program.control_scope_mask |= control_scope_mask_bit(marker.scope_kind);
lane0 = ProgramStamp::mix_u64(lane0, control_idx as u64);
lane0 = ProgramStamp::mix_u64(lane0, marker.offset as u64);
lane1 = ProgramStamp::mix_u64(lane1, marker.scope_kind as u64);
lane1 = ProgramStamp::mix_u64(lane1, marker.tap_id as u64);
if marker.tap_id != 0 {
summary.program.compiled_program_counts.tap_events += 1;
}
control_idx += 1;
}
lease_budget.validate();
summary.program.lowering_facts.scope_count = scope_count;
summary.program.lowering_facts.max_active_scope_depth = max_active_scope_depth;
summary.program.lowering_facts.max_route_stack_depth = if max_route_depth == 0 {
0
} else {
max_route_depth.saturating_add(1)
};
summary.program.lease_budget = lease_budget;
summary.roles.count = if role_count > u8::MAX as usize {
u8::MAX
} else {
role_count as u8
};
summary.program.stamp = ProgramStamp { lane0, lane1 };
}
const fn scan_impl(eff_list: &EffList, source_lookup: ProgramSourceLookup) -> Self {
let src_scope_markers = eff_list.scope_markers();
let mut summary = Self {
validation: ProgramImageValidationData {
segments: [ProgramImageSegmentData::EMPTY; MAX_SEGMENTS],
len: eff_list.len(),
atom_rows: [ProgramAtomRow::EMPTY; MAX_COMPILED_ATOM_ROWS],
atom_row_len: 0,
scope_markers: [ScopeMarker::empty(); MAX_COMPILED_SCOPE_MARKERS],
scope_marker_len: src_scope_markers.len(),
policy_rows: [ProgramPolicyRow::EMPTY; MAX_COMPILED_POLICY_ROWS],
policy_row_len: 0,
policy_rows_complete: true,
control_desc_rows: [ProgramControlDescRow::EMPTY; MAX_COMPILED_CONTROL_DESC_ROWS],
control_desc_row_len: 0,
control_desc_rows_complete: true,
},
program: ProgramImageData {
control_markers: [ControlMarker::empty(); MAX_COMPILED_CONTROL_MARKERS],
control_marker_len: 0,
control_markers_complete: true,
lease_budget: LeaseGraphBudget::new(),
compiled_program_counts: CompiledProgramCounts {
tap_events: 0,
resources: 0,
controls: 0,
dynamic_policy_sites: 0,
route_controls: 0,
},
lowering_facts: ProgramLoweringFacts::EMPTY,
control_scope_mask: 0,
stamp: ProgramStamp {
lane0: ProgramStamp::SEED0,
lane1: ProgramStamp::SEED1,
},
},
roles: ProgramRoleImageData {
facts: [RoleCompiledFacts::EMPTY; MAX_TRACKED_ROLE_FACTS],
count: 0,
},
source_lookup,
};
Self::scan_into(&mut summary, eff_list);
if summary.validation.policy_rows_complete && summary.validation.control_desc_rows_complete
{
summary.source_lookup = ProgramSourceLookup::empty();
}
summary
}
#[cfg(test)]
#[inline(always)]
pub(crate) const fn scan_const(eff_list: &EffList) -> Self {
Self::scan_const_with_lookup(eff_list, ProgramSourceLookup::empty())
}
#[inline(always)]
pub(crate) const fn scan_const_with_lookup(
eff_list: &EffList,
source_lookup: ProgramSourceLookup,
) -> Self {
Self::scan_impl(eff_list, source_lookup)
}
#[inline(always)]
pub(crate) const fn view(&self) -> CompiledProgramView<'_> {
self.validation.view(self.source_lookup)
}
#[inline(always)]
pub(crate) const fn projection_program_facts(
&self,
) -> crate::global::program::ProjectionProgramFacts {
crate::global::program::ProjectionProgramFacts {
role_count: self.roles.count,
eff_count: self.program.lowering_facts.eff_count,
scope_count: self.program.lowering_facts.scope_count,
route_scope_count: self.program.lowering_facts.route_scope_count,
parallel_enter_count: self.program.lowering_facts.parallel_enter_count,
control_scope_mask: self.program.control_scope_mask,
fingerprint: self.program.stamp.words(),
}
}
pub(crate) fn visit_projection_metadata<V>(&self, visitor: &mut V)
where
V: crate::global::program::ProjectionMetadataVisitor,
{
visitor.visit_program(self.projection_program_facts());
let view = self.view();
let mut idx = 0usize;
while idx < view.len() {
if let Some(atom) = view.atom_at(idx) {
let control = view.control_desc_at(idx);
visitor.visit_atom(crate::global::program::ProjectionAtomSpec {
eff_index: idx as u16,
from: atom.from,
to: atom.to,
label: atom.label,
lane: atom.lane,
is_control: atom.is_control,
resource: atom.resource,
control_scope: control.map(|desc| desc.scope_kind() as u8),
control_path: control.map(|desc| desc.path().as_u8()),
control_shot: control.map(|desc| desc.shot() as u8),
control_op: control.map(|desc| desc.op().as_u8()),
control_tap_id: control.map(|desc| desc.tap_id()),
control_auto_mint_wire: match control {
Some(desc) => desc.auto_mint_wire(),
None => false,
},
});
}
if let Some(policy) = view.policy_at(idx)
&& let Some(policy_id) = policy.dynamic_policy_id()
{
visitor.visit_policy(crate::global::program::ProjectionPolicySpec {
eff_index: idx as u16,
policy_id,
scope_raw: policy.scope().raw(),
});
}
idx += 1;
}
for marker in view.scope_markers() {
visitor.visit_scope(crate::global::program::ProjectionScopeSpec {
offset: marker.offset as u16,
scope_raw: marker.scope_id.raw(),
scope_kind: marker.scope_kind as u8,
event: marker.event as u8,
linger: marker.linger,
controller_role: marker.controller_role,
});
}
}
#[cfg(test)]
#[inline(always)]
pub(crate) const fn segment_summary(&self, segment: usize) -> SegmentSummary {
if segment >= crate::eff::meta::MAX_SEGMENTS {
panic!("lowering segment summary out of bounds");
}
self.validation.segments[segment].summary
}
#[inline(always)]
pub(crate) const fn stamp(&self) -> ProgramStamp {
self.program.stamp
}
#[inline(always)]
pub(crate) const fn compiled_program_role_count(&self) -> usize {
self.roles.count as usize
}
#[inline(always)]
pub(crate) const fn role_lowering_counts<const ROLE: u8>(&self) -> RoleCompiledCounts {
self.roles
.lowering_counts::<ROLE>(self.program.lowering_facts)
}
#[inline(always)]
pub(crate) const fn compiled_program_control_scope_mask(&self) -> u8 {
self.program.control_scope_mask
}
#[inline(always)]
pub(crate) const fn validate_projection_program(&self) {
self.program
.validate_projection_program(self.validation.scope_marker_len);
}
#[cfg(test)]
pub(crate) fn equivalent_summary(&self, other: &Self) -> bool {
if self.validation.len != other.validation.len
|| self.validation.scope_marker_len != other.validation.scope_marker_len
|| self.program.control_marker_len != other.program.control_marker_len
|| self.program.compiled_program_counts.controls
!= other.program.compiled_program_counts.controls
|| self.validation.policy_rows_complete != other.validation.policy_rows_complete
|| self.validation.control_desc_rows_complete
!= other.validation.control_desc_rows_complete
|| self.program.control_markers_complete != other.program.control_markers_complete
{
return false;
}
let mut segment = 0usize;
while segment < MAX_SEGMENTS {
let lhs = self.validation.segments[segment].clone();
let rhs = other.validation.segments[segment].clone();
if lhs.summary != rhs.summary
|| lhs.node_len != rhs.node_len
|| lhs.atom_row_start != rhs.atom_row_start
|| lhs.atom_row_len != rhs.atom_row_len
|| lhs.scope_marker_start != rhs.scope_marker_start
|| lhs.scope_marker_len != rhs.scope_marker_len
|| lhs.policy_row_start != rhs.policy_row_start
|| lhs.policy_row_len != rhs.policy_row_len
|| lhs.control_desc_row_start != rhs.control_desc_row_start
|| lhs.control_desc_row_len != rhs.control_desc_row_len
|| lhs.control_marker_start != rhs.control_marker_start
|| lhs.control_marker_len != rhs.control_marker_len
{
return false;
}
segment += 1;
}
let mut idx = 0usize;
while idx < self.validation.len {
let self_view = self.view();
let other_view = other.view();
if !Self::eff_struct_eq(self_view.node_at(idx), other_view.node_at(idx)) {
return false;
}
if self_view.policy_at(idx) != other_view.policy_at(idx) {
return false;
}
if self_view.control_desc_at(idx) != other_view.control_desc_at(idx) {
return false;
}
idx += 1;
}
let mut scope_idx = 0usize;
while scope_idx < self.validation.scope_marker_len {
if !Self::scope_marker_eq(
self.validation.scope_markers[scope_idx],
other.validation.scope_markers[scope_idx],
) {
return false;
}
scope_idx += 1;
}
let mut control_idx = 0usize;
while control_idx < self.program.control_marker_len {
if !Self::control_marker_eq(
self.program.control_markers[control_idx],
other.program.control_markers[control_idx],
) {
return false;
}
control_idx += 1;
}
true
}
}
#[cfg(test)]
mod tests {
use crate::eff::{EffAtom, EffIndex, EffStruct};
use crate::global::StaticControlDesc;
use crate::global::const_dsl::{ControlScopeKind, EffList, PolicyMode, ScopeId, ScopeKind};
use crate::global::program::boundary_source_program_image;
use crate::integration::cap::ResourceKind;
use crate::integration::cap::advanced::LoopContinueKind;
const fn atom(label: u8) -> EffStruct {
EffStruct::atom(EffAtom {
from: 0,
to: 1,
label,
is_control: false,
resource: None,
lane: 0,
})
}
const fn prefix_at_segment_boundary() -> EffList {
let mut list = EffList::new();
let mut idx = 0usize;
while idx < crate::eff::meta::MAX_SEGMENT_EFFS {
list = list.push(atom(idx as u8));
idx += 1;
}
list
}
const fn scoped_suffix() -> EffList {
EffList::new()
.push(atom(0xaa))
.with_scope(ScopeId::new(ScopeKind::Route, 9))
}
const fn scope_enter_at_boundary_program() -> EffList {
prefix_at_segment_boundary().extend_list(scoped_suffix())
}
const fn scope_exit_at_boundary_program() -> EffList {
prefix_at_segment_boundary().with_scope(ScopeId::new(ScopeKind::Route, 10))
}
const fn control_spec_at_boundary_program() -> EffList {
prefix_at_segment_boundary()
.push(atom(0xbb))
.push_control_spec(
crate::eff::meta::MAX_SEGMENT_EFFS,
StaticControlDesc::of::<LoopContinueKind>(),
)
.push_control_marker(
crate::eff::meta::MAX_SEGMENT_EFFS,
ControlScopeKind::Route,
77,
)
.push_policy(crate::eff::meta::MAX_SEGMENT_EFFS, PolicyMode::dynamic(77))
}
const fn atom_heavy_program() -> EffList {
let mut list = EffList::new();
let mut idx = 0usize;
while idx <= super::MAX_COMPILED_PROGRAM_TAP_EVENTS {
list = list.push(atom(idx as u8));
idx += 1;
}
list
}
const SIDE_TABLE_CAPACITY_REGRESSION_ROWS: usize = (crate::eff::meta::MAX_SEGMENTS * 2) + 1;
const fn control_atom(label: u8) -> EffStruct {
EffStruct::atom(EffAtom {
from: 0,
to: 0,
label,
is_control: true,
resource: Some(<LoopContinueKind as ResourceKind>::TAG),
lane: 0,
})
}
const fn policy_side_table_regression_program() -> EffList {
let mut list = EffList::new();
let mut idx = 0usize;
while idx < SIDE_TABLE_CAPACITY_REGRESSION_ROWS {
list = list.push(atom(idx as u8));
list = list.push_policy(idx, PolicyMode::dynamic(7));
idx += 1;
}
list
}
const fn control_side_table_regression_program() -> EffList {
let mut list = EffList::new();
let mut idx = 0usize;
while idx < SIDE_TABLE_CAPACITY_REGRESSION_ROWS {
list = list.push(control_atom(idx as u8));
list = list.push_control_spec(idx, StaticControlDesc::of::<LoopContinueKind>());
list = list.push_control_marker(idx, ControlScopeKind::Loop, idx as u16);
idx += 1;
}
list
}
static SCOPE_ENTER_AT_BOUNDARY: EffList = scope_enter_at_boundary_program();
static SCOPE_EXIT_AT_BOUNDARY: EffList = scope_exit_at_boundary_program();
static CONTROL_SPEC_AT_BOUNDARY: EffList = control_spec_at_boundary_program();
static ATOM_HEAVY_PROGRAM: EffList = atom_heavy_program();
static POLICY_SIDE_TABLE_REGRESSION_PROGRAM: EffList = policy_side_table_regression_program();
static CONTROL_SIDE_TABLE_REGRESSION_PROGRAM: EffList = control_side_table_regression_program();
fn regression_policy_lookup(offset: usize) -> Option<PolicyMode> {
POLICY_SIDE_TABLE_REGRESSION_PROGRAM
.policy_with_scope(offset)
.map(|(policy, _scope)| policy)
}
fn regression_control_lookup(offset: usize) -> Option<crate::global::ControlDesc> {
let spec = CONTROL_SIDE_TABLE_REGRESSION_PROGRAM.control_spec_at(offset)?;
Some(crate::global::ControlDesc::from_static(spec).with_sites(
EffIndex::from_dense_ordinal(offset),
crate::global::ControlDesc::STATIC_POLICY_SITE,
))
}
fn no_regression_policy_lookup(_: usize) -> Option<PolicyMode> {
None
}
fn no_regression_control_lookup(_: usize) -> Option<crate::global::ControlDesc> {
None
}
static SCOPE_ENTER_AT_BOUNDARY_SUMMARY: super::CompiledProgramImage =
boundary_source_program_image(&SCOPE_ENTER_AT_BOUNDARY);
static SCOPE_EXIT_AT_BOUNDARY_SUMMARY: super::CompiledProgramImage =
boundary_source_program_image(&SCOPE_EXIT_AT_BOUNDARY);
static CONTROL_SPEC_AT_BOUNDARY_SUMMARY: super::CompiledProgramImage =
boundary_source_program_image(&CONTROL_SPEC_AT_BOUNDARY);
static ATOM_HEAVY_SUMMARY: super::CompiledProgramImage =
boundary_source_program_image(&ATOM_HEAVY_PROGRAM);
static POLICY_SIDE_TABLE_REGRESSION_SUMMARY: super::CompiledProgramImage =
super::CompiledProgramImage::scan_const_with_lookup(
&POLICY_SIDE_TABLE_REGRESSION_PROGRAM,
super::ProgramSourceLookup::new(regression_policy_lookup, no_regression_control_lookup),
);
static CONTROL_SIDE_TABLE_REGRESSION_SUMMARY: super::CompiledProgramImage =
super::CompiledProgramImage::scan_const_with_lookup(
&CONTROL_SIDE_TABLE_REGRESSION_PROGRAM,
super::ProgramSourceLookup::new(no_regression_policy_lookup, regression_control_lookup),
);
#[test]
fn ordinary_atom_capacity_is_not_tied_to_tap_event_budget() {
assert!(ATOM_HEAVY_PROGRAM.len() > super::MAX_COMPILED_PROGRAM_TAP_EVENTS);
ATOM_HEAVY_SUMMARY.validate_projection_program();
crate::global::compiled::lowering::seal::validate_all_roles(
&ATOM_HEAVY_SUMMARY,
&ATOM_HEAVY_PROGRAM,
);
let view = ATOM_HEAVY_SUMMARY.view();
let offset = super::MAX_COMPILED_PROGRAM_TAP_EVENTS;
assert_eq!(
view.atom_at(offset).map(|atom| atom.label),
Some(offset as u8)
);
}
#[test]
fn policy_side_table_capacity_matches_0_6_0_program_capacity() {
assert!(SIDE_TABLE_CAPACITY_REGRESSION_ROWS > crate::eff::meta::MAX_SEGMENTS * 2);
POLICY_SIDE_TABLE_REGRESSION_SUMMARY.validate_projection_program();
crate::global::compiled::lowering::seal::validate_all_roles(
&POLICY_SIDE_TABLE_REGRESSION_SUMMARY,
&POLICY_SIDE_TABLE_REGRESSION_PROGRAM,
);
let last = SIDE_TABLE_CAPACITY_REGRESSION_ROWS - 1;
let view = POLICY_SIDE_TABLE_REGRESSION_SUMMARY.view();
assert_eq!(
view.policy_at(last)
.and_then(|policy| policy.dynamic_policy_id()),
Some(7)
);
}
#[test]
fn control_side_tables_keep_0_6_0_program_capacity() {
assert!(SIDE_TABLE_CAPACITY_REGRESSION_ROWS > crate::eff::meta::MAX_SEGMENTS * 2);
CONTROL_SIDE_TABLE_REGRESSION_SUMMARY.validate_projection_program();
crate::global::compiled::lowering::seal::validate_all_roles(
&CONTROL_SIDE_TABLE_REGRESSION_SUMMARY,
&CONTROL_SIDE_TABLE_REGRESSION_PROGRAM,
);
let last = SIDE_TABLE_CAPACITY_REGRESSION_ROWS - 1;
let view = CONTROL_SIDE_TABLE_REGRESSION_SUMMARY.view();
assert!(view.control_desc_at(last).is_some());
assert_eq!(
CONTROL_SIDE_TABLE_REGRESSION_SUMMARY
.program
.compiled_program_counts
.controls,
SIDE_TABLE_CAPACITY_REGRESSION_ROWS
);
assert_eq!(
CONTROL_SIDE_TABLE_REGRESSION_SUMMARY
.program
.control_markers()
.len(),
crate::eff::meta::MAX_SEGMENTS * 2
);
}
#[test]
fn lowering_scope_enter_at_exact_segment_boundary_belongs_to_next_segment() {
let summary = &SCOPE_ENTER_AT_BOUNDARY_SUMMARY;
assert_eq!(summary.segment_summary(0).scope_marker_len(), 0);
assert_eq!(summary.segment_summary(1).scope_marker_len(), 2);
assert_eq!(summary.segment_summary(1).route_scope_enter_len(), 1);
assert_eq!(summary.validation.segments[1].scope_marker_start, 0);
assert_eq!(summary.validation.segments[1].scope_marker_len, 2);
}
#[test]
fn lowering_scope_exit_at_exact_segment_boundary_belongs_to_previous_segment() {
let summary = &SCOPE_EXIT_AT_BOUNDARY_SUMMARY;
assert_eq!(summary.segment_summary(0).scope_marker_len(), 2);
assert_eq!(summary.segment_summary(0).route_scope_enter_len(), 1);
assert_eq!(summary.segment_summary(1).scope_marker_len(), 0);
assert_eq!(summary.validation.segments[0].scope_marker_start, 0);
assert_eq!(summary.validation.segments[0].scope_marker_len, 2);
}
#[test]
fn lowering_control_spec_at_segment_boundary_belongs_to_effect_segment() {
let summary = &CONTROL_SPEC_AT_BOUNDARY_SUMMARY;
assert_eq!(summary.segment_summary(0).control_marker_len(), 0);
assert_eq!(summary.segment_summary(0).policy_marker_len(), 0);
assert_eq!(summary.segment_summary(0).control_spec_len(), 0);
assert_eq!(summary.segment_summary(1).control_marker_len(), 1);
assert_eq!(summary.segment_summary(1).policy_marker_len(), 1);
assert_eq!(summary.segment_summary(1).control_spec_len(), 1);
assert_eq!(summary.validation.segments[1].control_marker_start, 0);
assert_eq!(summary.validation.segments[1].control_marker_len, 1);
}
}