flams_ontology/narration/
mod.rs

1#![allow(clippy::large_enum_variant)]
2
3pub mod checking;
4pub mod documents;
5pub mod notations;
6pub mod paragraphs;
7pub mod problems;
8pub mod sections;
9pub mod variables;
10
11use std::marker::PhantomData;
12
13use documents::Document;
14use flams_utils::prelude::InnerArc;
15use notations::Notation;
16use paragraphs::LogicalParagraph;
17use problems::{CognitiveDimension, Problem};
18use sections::{Section, SectionLevel};
19use variables::Variable;
20
21use crate::{
22    content::{
23        declarations::{
24            morphisms::Morphism,
25            structures::{Extension, MathStructure},
26            symbols::Symbol,
27        },
28        terms::Term,
29    },
30    uris::{DocumentElementURI, DocumentURI, Name, NameStep, SymbolURI},
31    Checked, CheckingState, DocumentRange, Unchecked,
32};
33
34#[derive(Debug, Copy, Clone)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify))]
37#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
38#[cfg_attr(feature = "serde", serde(tag = "type"))]
39pub enum LOKind {
40    Definition,
41    Example,
42    Problem(CognitiveDimension),
43    SubProblem(CognitiveDimension),
44}
45
46#[derive(Debug, Clone)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48pub struct LazyDocRef<T> {
49    pub start: usize,
50    pub end: usize,
51    pub in_doc: DocumentURI,
52    phantom_data: PhantomData<T>,
53}
54impl<T> LazyDocRef<T> {
55    #[inline]
56    #[must_use]
57    pub const fn new(start: usize, end: usize, in_doc: DocumentURI) -> Self {
58        Self {
59            start,
60            end,
61            in_doc,
62            phantom_data: PhantomData,
63        }
64    }
65}
66
67pub trait NarrationTrait {
68    fn from_element(e: &DocumentElement<Checked>) -> Option<&Self>
69    where
70        Self: Sized;
71    fn children(&self) -> &[DocumentElement<Checked>];
72
73    fn find<T: NarrationTrait>(&self, steps: &[NameStep]) -> Option<&T> {
74        enum I<'a> {
75            One(std::slice::Iter<'a, DocumentElement<Checked>>),
76            Mul(
77                std::slice::Iter<'a, DocumentElement<Checked>>,
78                Vec<std::slice::Iter<'a, DocumentElement<Checked>>>,
79            ),
80        }
81        impl<'a> I<'a> {
82            fn push(&mut self, es: &'a [DocumentElement<Checked>]) {
83                match self {
84                    Self::One(_) => {
85                        let new = Self::Mul(es.iter(), Vec::with_capacity(1));
86                        let Self::One(s) = std::mem::replace(self, new) else {
87                            unreachable!()
88                        };
89                        let Self::Mul(_, v) = self else {
90                            unreachable!()
91                        };
92                        v.push(s);
93                    }
94                    Self::Mul(f, r) => {
95                        let of = std::mem::replace(f, es.iter());
96                        r.push(of);
97                    }
98                }
99            }
100        }
101        impl<'a> Iterator for I<'a> {
102            type Item = &'a DocumentElement<Checked>;
103            #[allow(clippy::option_if_let_else)]
104            fn next(&mut self) -> Option<Self::Item> {
105                match self {
106                    Self::One(s) => s.next(),
107                    Self::Mul(f, r) => loop {
108                        if let Some(n) = f.next() {
109                            return Some(n);
110                        }
111                        let Some(mut n) = r.pop() else { unreachable!() };
112                        if r.is_empty() {
113                            let r = n.next();
114                            *self = Self::One(n);
115                            return r;
116                        }
117                        *f = n;
118                    },
119                }
120            }
121        }
122        let mut steps = steps;
123        let mut curr = I::One(self.children().iter());
124        'outer: while !steps.is_empty() {
125            let step = &steps[0];
126            steps = &steps[1..];
127            while let Some(c) = curr.next() {
128                match c {
129                    DocumentElement::Section(Section { uri, children, .. })
130                    | DocumentElement::Paragraph(LogicalParagraph { uri, children, .. })
131                    | DocumentElement::Problem(Problem { uri, children, .. })
132                        if uri.name().last_name() == step =>
133                    {
134                        if steps.is_empty() {
135                            return T::from_element(c);
136                        }
137                        curr = I::One(children.iter());
138                        continue 'outer;
139                    }
140                    DocumentElement::Slide { uri, .. }
141                        if uri.name().last_name() == step && steps.is_empty() =>
142                    {
143                        return T::from_element(c);
144                    }
145                    DocumentElement::Module { children, .. }
146                    | DocumentElement::Morphism { children, .. }
147                    | DocumentElement::MathStructure { children, .. }
148                    | DocumentElement::Slide { children, .. }
149                    | DocumentElement::Extension { children, .. } => curr.push(children),
150                    DocumentElement::Notation { id: uri, .. }
151                    | DocumentElement::VariableNotation { id: uri, .. }
152                    | DocumentElement::Variable(Variable { uri, .. })
153                    | DocumentElement::TopTerm { uri, .. }
154                        if uri.name().last_name() == step =>
155                    {
156                        if steps.is_empty() {
157                            return T::from_element(c);
158                        }
159                        return None;
160                    }
161                    DocumentElement::Section(_)
162                    | DocumentElement::Paragraph(_)
163                    | DocumentElement::Problem(_)
164                    | DocumentElement::SetSectionLevel(_)
165                    | DocumentElement::SymbolDeclaration(_)
166                    | DocumentElement::UseModule(_)
167                    | DocumentElement::ImportModule(_)
168                    | DocumentElement::SkipSection(_)
169                    | DocumentElement::Variable(_)
170                    | DocumentElement::Definiendum { .. }
171                    | DocumentElement::SymbolReference { .. }
172                    | DocumentElement::VariableReference { .. }
173                    | DocumentElement::DocumentReference { .. }
174                    | DocumentElement::Notation { .. }
175                    | DocumentElement::VariableNotation { .. }
176                    | DocumentElement::TopTerm { .. } => (),
177                }
178            }
179        }
180        None
181    }
182}
183
184pub struct NarrativeReference<T: NarrationTrait>(InnerArc<Document, T>);
185
186impl<T: NarrationTrait> NarrativeReference<T> {
187    #[must_use]
188    pub fn new(d: &Document, name: &Name) -> Option<Self> {
189        unsafe {
190            InnerArc::new(d, |d| &d.0, |d| d.find(name.steps()).ok_or(()))
191                .ok()
192                .map(Self)
193        }
194    }
195    #[must_use]
196    #[inline]
197    pub const fn top(&self) -> &Document {
198        self.0.outer()
199    }
200}
201
202impl<T: NarrationTrait> AsRef<T> for NarrativeReference<T> {
203    #[inline]
204    fn as_ref(&self) -> &T {
205        self.0.as_ref()
206    }
207}
208
209impl<T: NarrationTrait + std::fmt::Debug> std::fmt::Debug for NarrativeReference<T> {
210    #[inline]
211    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212        std::fmt::Debug::fmt(self.as_ref(), f)
213    }
214}
215
216//#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
217pub enum DocumentElement<State: CheckingState> {
218    SetSectionLevel(SectionLevel),
219    Section(Section<State>),
220    Slide {
221        range: DocumentRange,
222        uri: DocumentElementURI,
223        children: State::Seq<DocumentElement<State>>,
224    },
225    Module {
226        range: DocumentRange,
227        module: State::ModuleLike,
228        children: State::Seq<DocumentElement<State>>,
229    },
230    Morphism {
231        range: DocumentRange,
232        morphism: State::Decl<Morphism<Checked>>,
233        children: State::Seq<DocumentElement<State>>,
234    },
235    MathStructure {
236        range: DocumentRange,
237        structure: State::Decl<MathStructure<Checked>>,
238        children: State::Seq<DocumentElement<State>>,
239    },
240    Extension {
241        range: DocumentRange,
242        extension: State::Decl<Extension<Checked>>,
243        target: State::Decl<MathStructure<Checked>>,
244        children: State::Seq<DocumentElement<State>>,
245    },
246    DocumentReference {
247        id: DocumentElementURI,
248        range: DocumentRange,
249        target: State::Doc,
250    },
251    SymbolDeclaration(State::Decl<Symbol>),
252    Notation {
253        symbol: SymbolURI,
254        id: DocumentElementURI,
255        notation: LazyDocRef<Notation>,
256    },
257    VariableNotation {
258        variable: DocumentElementURI,
259        id: DocumentElementURI,
260        notation: LazyDocRef<Notation>,
261    },
262    Variable(Variable),
263    Definiendum {
264        range: DocumentRange,
265        uri: SymbolURI,
266    },
267    SymbolReference {
268        range: DocumentRange,
269        uri: SymbolURI,
270        notation: Option<NameStep>,
271    },
272    VariableReference {
273        range: DocumentRange,
274        uri: DocumentElementURI,
275        notation: Option<NameStep>,
276    },
277    TopTerm {
278        uri: DocumentElementURI,
279        term: Term,
280    },
281    UseModule(State::ModuleLike),
282    ImportModule(State::ModuleLike),
283    Paragraph(LogicalParagraph<State>),
284    Problem(Problem<State>),
285    SkipSection(State::Seq<DocumentElement<State>>),
286}
287
288crate::serde_impl! {
289    enum DocumentElement {
290        {0 = SetSectionLevel(l)}
291        {1 = Section(s)}
292        {2 = Module{range,module,children}}
293        {3 = Morphism{range,morphism,children}}
294        {4 = MathStructure{range,structure,children}}
295        {5 = Extension{range,extension,target,children}}
296        {6 = DocumentReference { id, range, target }}
297        {7 = SymbolDeclaration(s)}
298        {8 = Notation{symbol,id,notation}}
299        {9 = VariableNotation { variable, id, notation }}
300        {10 = Variable(v)}
301        {11 = Definiendum { range, uri }}
302        {12 = SymbolReference { range, uri, notation }}
303        {13 = VariableReference { range, uri, notation }}
304        {14 = TopTerm { uri, term }}
305        {15 = UseModule(m)}
306        {16 = ImportModule(m)}
307        {17 = Paragraph(p)}
308        {18 = Problem(e)}
309        {19 = SkipSection(children)}
310        {20 = Slide{ uri, range, children}}
311    }
312}
313
314impl NarrationTrait for DocumentElement<Checked> {
315    #[inline]
316    fn from_element(e: &DocumentElement<Checked>) -> Option<&Self>
317    where
318        Self: Sized,
319    {
320        Some(e)
321    }
322    fn children(&self) -> &[DocumentElement<Checked>] {
323        match self {
324            Self::Section(s) => s.children(),
325            Self::Paragraph(p) => p.children(),
326            Self::Problem(e) => e.children(),
327            Self::Module { children, .. }
328            | Self::Morphism { children, .. }
329            | Self::MathStructure { children, .. }
330            | Self::Extension { children, .. }
331            | Self::SkipSection(children)
332            | Self::Slide { children, .. } => children,
333            _ => &[],
334        }
335    }
336}
337
338impl<State: CheckingState> std::fmt::Debug for DocumentElement<State> {
339    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340        match self {
341            Self::SetSectionLevel(level) => f.debug_tuple("SetSectionLevel").field(level).finish(),
342            Self::Section(section) => f.debug_tuple("Section").field(section).finish(),
343            Self::Module {
344                range,
345                module,
346                children,
347            } => f
348                .debug_struct("Module")
349                .field("range", range)
350                .field("module", module)
351                .field("children", children)
352                .finish(),
353            Self::Morphism {
354                range,
355                morphism,
356                children,
357            } => f
358                .debug_struct("Morphism")
359                .field("range", range)
360                .field("morphism", morphism)
361                .field("children", children)
362                .finish(),
363            Self::MathStructure {
364                range,
365                structure,
366                children,
367            } => f
368                .debug_struct("MathStructure")
369                .field("range", range)
370                .field("structure", structure)
371                .field("children", children)
372                .finish(),
373            Self::Extension {
374                range,
375                extension,
376                target,
377                children,
378            } => f
379                .debug_struct("Extension")
380                .field("range", range)
381                .field("extension", extension)
382                .field("target", target)
383                .field("children", children)
384                .finish(),
385            Self::DocumentReference { id, range, target } => f
386                .debug_struct("DocumentReference")
387                .field("id", id)
388                .field("range", range)
389                .field("target", target)
390                .finish(),
391            Self::SymbolDeclaration(symbol) => {
392                f.debug_tuple("SymbolDeclaration").field(symbol).finish()
393            }
394            Self::Notation {
395                symbol,
396                id,
397                notation,
398            } => f
399                .debug_struct("Notation")
400                .field("symbol", symbol)
401                .field("id", id)
402                .field("notation", notation)
403                .finish(),
404            Self::VariableNotation {
405                variable,
406                id,
407                notation,
408            } => f
409                .debug_struct("VariableNotation")
410                .field("variable", variable)
411                .field("id", id)
412                .field("notation", notation)
413                .finish(),
414            Self::Variable(variable) => f.debug_tuple("Variable").field(variable).finish(),
415            Self::Definiendum { range, uri } => f
416                .debug_struct("Definiendum")
417                .field("range", range)
418                .field("uri", uri)
419                .finish(),
420            Self::SymbolReference {
421                range,
422                uri,
423                notation,
424            } => f
425                .debug_struct("SymbolReference")
426                .field("range", range)
427                .field("uri", uri)
428                .field("notation", notation)
429                .finish(),
430            Self::VariableReference {
431                range,
432                uri,
433                notation,
434            } => f
435                .debug_struct("VariableReference")
436                .field("range", range)
437                .field("uri", uri)
438                .field("notation", notation)
439                .finish(),
440            Self::TopTerm { uri, term } => f
441                .debug_struct("TopTerm")
442                .field("uri", uri)
443                .field("term", term)
444                .finish(),
445            Self::UseModule(module) => f.debug_tuple("UseModule").field(module).finish(),
446            Self::ImportModule(module) => f.debug_tuple("ImportModule").field(module).finish(),
447            Self::Paragraph(paragraph) => f.debug_tuple("Paragraph").field(paragraph).finish(),
448            Self::Problem(problem) => f.debug_tuple("Problem").field(problem).finish(),
449            Self::SkipSection(children) => f.debug_tuple("SkipSection").field(children).finish(),
450            Self::Slide {
451                uri,
452                range,
453                children,
454            } => f
455                .debug_struct("Slide")
456                .field("uri", uri)
457                .field("range", range)
458                .field("children", children)
459                .finish(),
460        }
461    }
462}
463
464impl DocumentElement<Unchecked> {
465    #[allow(clippy::missing_errors_doc)]
466    pub fn set_children(&mut self, new_children: Vec<Self>) -> Result<(), ElementHasNoChildren> {
467        match self {
468            Self::Section(s) => s.children = new_children,
469            Self::Paragraph(p) => p.children = new_children,
470            Self::Problem(e) => e.children = new_children,
471            Self::Module { children, .. }
472            | Self::Morphism { children, .. }
473            | Self::MathStructure { children, .. }
474            | Self::SkipSection(children)
475            | Self::Slide { children, .. } => *children = new_children,
476            _ => return Err(ElementHasNoChildren),
477        }
478        Ok(())
479    }
480}
481
482pub struct ElementHasNoChildren;