use super::{
    facts::{atom, pair, particle},
    types::{Metrics, Output},
    *,
};

impl Activation {
    pub fn enter(
        memory: &View<'_>,
        object: u32,
        formula: u32,
        expected: InputKey,
        limits: Limits,
    ) -> Result<Self, Error> {
        let key = InputKey {
            object: particle(memory, object)?,
            formula: particle(memory, formula)?,
        };
        if key != expected {
            return Err(Error::Key);
        }
        let bound = memory.get(formula).map_err(|_| Error::Noun)?.cost();
        let (tag, body) = pair(memory, formula)?;
        let tag = atom(memory, tag)?;
        if tag > 15 {
            return Err(Error::UnsupportedOpcode);
        }
        let cost = [1, 1, 1, 1, 1, 1, 1, 1, 64, 1, 64, 32, 32, 32, 32, 25][tag as usize];
        let metrics = Metrics::leaf(cost, limits)?;
        let stage = match tag {
            0 => Stage::Ready(Output::axis(memory, object, body)?),
            1 => Stage::Ready(Output::Equal(particle(memory, body)?)),
            8 | 13 | 15 => Stage::Unary {
                tag,
                formula: particle(memory, body)?,
            },
            4 => {
                let (test, arms) = pair(memory, body)?;
                let (yes, no) = pair(memory, arms)?;
                Stage::BranchTest {
                    test: particle(memory, test)?,
                    yes: particle(memory, yes)?,
                    no: particle(memory, no)?,
                }
            }
            _ => {
                let (a, b) = pair(memory, body)?;
                Stage::BinaryLeft {
                    tag,
                    a: particle(memory, a)?,
                    b: particle(memory, b)?,
                }
            }
        };
        Ok(Self {
            key,
            bound,
            metrics,
            stage,
        })
    }

    pub fn expected(&self) -> Option<InputKey> {
        let formula = match self.stage {
            Stage::Ready(_) => return None,
            Stage::Unary { formula, .. } | Stage::BranchChosen { formula } => formula,
            Stage::BinaryLeft { a, .. } => a,
            Stage::BinaryRight { b, .. } => b,
            Stage::BranchTest { test, .. } => test,
            Stage::Continuation(key) => return Some(key),
        };
        Some(InputKey {
            object: self.key.object,
            formula,
        })
    }

    pub fn accept(&mut self, summary: VerifiedSummary, limits: Limits) -> Result<(), Error> {
        if self.expected() != Some(summary.key) {
            return Err(Error::Key);
        }
        let metrics = self.metrics.add(summary.metrics, limits)?;
        let result = summary.result;
        let stage = match self.stage {
            Stage::Unary { tag, .. } => Stage::Ready(Output::unary(tag, result)?),
            Stage::BinaryLeft { tag, b, .. } => Stage::BinaryRight {
                tag,
                b,
                left: result,
            },
            Stage::BinaryRight { tag: 2, left, .. } => Stage::Continuation(InputKey {
                object: left.particle(),
                formula: result.particle(),
            }),
            Stage::BinaryRight { tag, left, .. } => {
                Stage::Ready(Output::binary(tag, left, result)?)
            }
            Stage::BranchTest { yes, no, .. } => Stage::BranchChosen {
                formula: if result.atom()? == 0 { yes } else { no },
            },
            Stage::BranchChosen { .. } | Stage::Continuation(_) => {
                Stage::Ready(Output::Equal(result.particle()))
            }
            Stage::Ready(_) => return Err(Error::State),
        };
        self.metrics = metrics;
        self.stage = stage;
        Ok(())
    }
}

Homonyms

soft3/crate/src/chain/tests/rules.rs
soft3/cybernode/rs/src/chain/tests/rules.rs
soft3/zheng/rs/src/execution/disclosed/evaluation/rules.rs

Graph