summaryrefslogtreecommitdiff
path: root/chain/src/item/mod.rs
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2023-02-27 12:36:41 +0800
committerJSDurand <mmemmew@gmail.com>2023-02-27 12:36:41 +0800
commitfbaa420ed550e9c3e7cdc09d4a8ec22bfbd782a6 (patch)
treefad9722825bb3fa796dd52c3fd4a8bf46b958cf9 /chain/src/item/mod.rs
parentafad02bdff111ecccb0077b9c989e869723c231c (diff)
before a major refactor
I decide to adopt a new approach of recording and updating item derivation forests. Since this affects a lot of things, I decide to commit before the refactor, so that I can create a branch for that refactor.
Diffstat (limited to 'chain/src/item/mod.rs')
-rw-r--r--chain/src/item/mod.rs85
1 files changed, 61 insertions, 24 deletions
diff --git a/chain/src/item/mod.rs b/chain/src/item/mod.rs
index 284d640..39d04c7 100644
--- a/chain/src/item/mod.rs
+++ b/chain/src/item/mod.rs
@@ -9,43 +9,64 @@ use graph::{error::Error as GError, GraphLabel, LabelGraph, Parent, ParentsGraph
use core::borrow::Borrow;
-/// A parent or a segment.
+/// A parent or a virtual segment.
+///
+/// # Parent
///
/// A parent is a node with an edge index, which represents a certain
/// edge.
///
-/// A segment represents every edge from the root node to the single
-/// terminating node.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-pub enum PaSe {
+/// # Virtual Segment
+///
+/// A virtual segment represents an expansion from a non-terminal by a
+/// terminal. We do not directly add this segment when we encounter
+/// this expansion at the start because this expansion might contain
+/// multiple derivations some of which will not be used.
+///
+/// If we add the expansion immediately when we encounter it, we have
+/// to later discern and delete those unwanted derivations. This is
+/// asking for trouble, in my experiences.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
+pub enum PaVi {
/// An edge from a node, as the n-th child.
Parent(usize, usize),
- /// A segment from a root to the single terminating node.
- Segment(usize, usize),
+ /// A virtual segment from a non-terminal by a terminal, rooted at
+ /// a node.
+ ///
+ /// # Tuple elements
+ ///
+ /// The contained tuple is of the form (nt, t, node), which means
+ /// a virtually added node at the `node` representing the
+ /// expansion from the non-terminal `nt` by the terminal `t`.
+ Virtual(usize, usize, usize),
+ /// This is an empty segment that represents the root node. This
+ /// is a special case for the unit state of the chain-rule
+ /// machine.
+ #[default]
+ Empty,
}
-impl From<Parent> for PaSe {
+impl From<Parent> for PaVi {
fn from(value: Parent) -> Self {
Self::Parent(value.node(), value.edge())
}
}
-impl Default for PaSe {
- fn default() -> Self {
- Self::Segment(0, 0)
- }
-}
-
-impl core::fmt::Display for PaSe {
+impl core::fmt::Display for PaVi {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Parent(node, edge) => write!(f, "the {edge}-th edge from {node}"),
- Self::Segment(root, leaf) => write!(f, "a segment from {root} to {leaf}"),
+ Self::Virtual(nt, t, node) => write!(
+ f,
+ "a virtual node for non-terminal {nt} and terminal {t} at node {node}"
+ ),
+ Self::Empty => write!(f, "empty segment at root"),
}
}
}
-impl PaSe {
+impl PaVi {
+ /// Get the Parent variant.
fn parent(self) -> Option<Parent> {
if let Self::Parent(node, edge) = self {
Some(Parent::new(node, edge))
@@ -54,12 +75,29 @@ impl PaSe {
}
}
- fn segment(self) -> Option<(usize, usize)> {
- if let Self::Segment(root, leaf) = self {
- Some((root, leaf))
- } else {
- None
- }
+ // /// Get the "Virtual" variant.
+ // ///
+ // /// # Name
+ // ///
+ // /// We cannot use the name "virtual" since it is a reserved
+ // /// keyword in Rust, so we use its French name.
+ // ///
+ // /// # Tuple elements
+ // ///
+ // /// The returned tuple is of the form (nt, t, node), which means a
+ // /// virtually added node at the `node` representing the expansion
+ // /// from the non-terminal `nt` by the terminal `t`.
+ // fn virtuel(self) -> Option<(usize, usize, usize)> {
+ // if let Self::Virtual(nt, t, node) = self {
+ // Some((nt, t, node))
+ // } else {
+ // None
+ // }
+ // }
+
+ /// Is this an empty segment?
+ fn is_empty(self) -> bool {
+ self == Self::Empty
}
}
@@ -101,7 +139,6 @@ impl<T: GraphLabel> core::fmt::Display for ForestLabel<T> {
}
/// The type of erros for converting forest labels.
-#[non_exhaustive]
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum ForestLabelError {
/// Try to pack a cloned node.