asdi/visitor/
mod.rs

1/*!
2This module provides the trait [Typesetter](trait.Typesetter.html), and implementation
3
4![module UML](https://raw.githubusercontent.com/johnstonskj/rust-asdi/main/book/src/model/visitor.svg)
5
6TBD
7
8# Example
9
10TBD
11
12*/
13
14use crate::edb::Fact;
15use crate::error::Result;
16use crate::idb::{query::Query, Rule};
17use crate::{Collection, Program, ProgramCore, QuerySet, Relation, RuleSet};
18
19// ------------------------------------------------------------------------------------------------
20// Public Types & Constants
21// ------------------------------------------------------------------------------------------------
22
23pub trait ProgramVisitor {
24    fn start_program(&self, _program: &Program) -> Result<()> {
25        Ok(())
26    }
27    fn end_program(&self, _program: &Program) -> Result<()> {
28        Ok(())
29    }
30
31    fn relation_visitor(&self) -> Option<&dyn RelationVisitor> {
32        None
33    }
34
35    fn rule_visitor(&self) -> Option<&dyn RuleVisitor> {
36        None
37    }
38
39    fn query_visitor(&self) -> Option<&dyn QueryVisitor> {
40        None
41    }
42}
43
44pub trait ProgramWriter: ProgramVisitor {}
45
46pub trait RelationVisitor {
47    fn start_relation(&self, _relation: &Relation, _extensional: bool) -> Result<()> {
48        Ok(())
49    }
50    fn fact(&self, _fact: &Fact) -> Result<()> {
51        Ok(())
52    }
53    fn end_relation(&self, _relation: &Relation, _extensional: bool) -> Result<()> {
54        Ok(())
55    }
56}
57
58pub trait RuleVisitor {
59    fn start_rules(&self, _rules: &RuleSet) -> Result<()> {
60        Ok(())
61    }
62    fn rule(&self, _rule: &Rule) -> Result<()> {
63        Ok(())
64    }
65    fn end_rules(&self, _rules: &RuleSet) -> Result<()> {
66        Ok(())
67    }
68}
69
70pub trait QueryVisitor {
71    fn start_queries(&self, _queries: &QuerySet) -> Result<()> {
72        Ok(())
73    }
74    fn query(&self, _query: &Query) -> Result<()> {
75        Ok(())
76    }
77    fn end_queries(&self, _queries: &QuerySet) -> Result<()> {
78        Ok(())
79    }
80}
81
82// ------------------------------------------------------------------------------------------------
83// Public Functions
84// ------------------------------------------------------------------------------------------------
85
86pub fn write_program(program: &Program, visitor: &impl ProgramWriter) -> Result<()> {
87    visit_program(program, visitor)
88}
89
90pub fn visit_program(program: &Program, visitor: &impl ProgramVisitor) -> Result<()> {
91    visitor.start_program(program)?;
92
93    if let Some(relation_visitor) = visitor.relation_visitor() {
94        for edb in [true, false] {
95            let relations = if edb {
96                program.extensional()
97            } else {
98                program.intensional()
99            };
100            if !relations.is_empty() {
101                for relation in relations.iter() {
102                    relation_visitor.start_relation(relation, edb)?;
103                    for fact in relation.iter() {
104                        relation_visitor.fact(fact)?;
105                    }
106                    relation_visitor.end_relation(relation, edb)?;
107                }
108            }
109        }
110    }
111
112    let rules = program.rules();
113    if !rules.is_empty() {
114        if let Some(rule_visitor) = visitor.rule_visitor() {
115            rule_visitor.start_rules(&rules)?;
116            for rule in rules.iter() {
117                rule_visitor.rule(rule)?;
118            }
119            rule_visitor.end_rules(&rules)?;
120        }
121    }
122
123    let queries = program.queries();
124    if !queries.is_empty() {
125        if let Some(query_visitor) = visitor.query_visitor() {
126            query_visitor.start_queries(queries)?;
127            for query in queries.iter() {
128                query_visitor.query(query)?;
129            }
130            query_visitor.end_queries(queries)?;
131        }
132    }
133
134    visitor.end_program(program)
135}
136
137// ------------------------------------------------------------------------------------------------
138// Modules
139// ------------------------------------------------------------------------------------------------
140
141mod latex;
142pub use latex::{make_latex_writer, LatexFormatter};
143
144mod native;
145pub use native::{make_native_writer, NativeFormatter};