logicaffeine_language/
session.rs1use crate::analysis;
17use logicaffeine_base::Arena;
18use crate::arena_ctx::AstContext;
19use crate::drs::WorldState;
20use crate::error::ParseError;
21use logicaffeine_base::Interner;
22use crate::lexer::Lexer;
23use crate::mwe;
24use crate::parser::Parser;
25use crate::registry::SymbolRegistry;
26use crate::semantics;
27use crate::OutputFormat;
28
29pub struct Session {
34 world_state: WorldState,
36
37 interner: Interner,
39
40 registry: SymbolRegistry,
42
43 mwe_trie: mwe::MweTrie,
45
46 history: Vec<String>,
48
49 format: OutputFormat,
51}
52
53impl Default for Session {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl Session {
60 pub fn new() -> Self {
62 Session {
63 world_state: WorldState::new(),
64 interner: Interner::new(),
65 registry: SymbolRegistry::new(),
66 mwe_trie: mwe::build_mwe_trie(),
67 history: Vec::new(),
68 format: OutputFormat::Unicode,
69 }
70 }
71
72 pub fn set_format(&mut self, format: OutputFormat) {
78 self.format = format;
79 }
80
81 pub fn with_format(format: OutputFormat) -> Self {
83 Session {
84 world_state: WorldState::new(),
85 interner: Interner::new(),
86 registry: SymbolRegistry::new(),
87 mwe_trie: mwe::build_mwe_trie(),
88 history: Vec::new(),
89 format,
90 }
91 }
92
93 pub fn eval(&mut self, input: &str) -> Result<String, ParseError> {
98 let event_var_name = self.world_state.next_event_var();
100 let event_var_symbol = self.interner.intern(&event_var_name);
101
102 let mut lexer = Lexer::new(input, &mut self.interner);
104 let tokens = lexer.tokenize();
105
106 let tokens = mwe::apply_mwe_pipeline(tokens, &self.mwe_trie, &mut self.interner);
108
109 let type_registry = {
111 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut self.interner);
112 discovery.run()
113 };
114
115 let expr_arena = Arena::new();
117 let term_arena = Arena::new();
118 let np_arena = Arena::new();
119 let sym_arena = Arena::new();
120 let role_arena = Arena::new();
121 let pp_arena = Arena::new();
122
123 let ast_ctx = AstContext::new(
124 &expr_arena,
125 &term_arena,
126 &np_arena,
127 &sym_arena,
128 &role_arena,
129 &pp_arena,
130 );
131
132 let mut parser = Parser::new(
134 tokens,
135 &mut self.world_state,
136 &mut self.interner,
137 ast_ctx,
138 type_registry,
139 );
140 parser.set_discourse_event_var(event_var_symbol);
141
142 parser.swap_drs_with_world_state();
144 let ast = parser.parse()?;
145 parser.swap_drs_with_world_state();
147
148 self.world_state.end_sentence();
150
151 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut self.interner);
153
154 let output = ast.transpile(&mut self.registry, &self.interner, self.format);
156
157 self.history.push(output.clone());
159
160 Ok(output)
161 }
162
163 pub fn history(&self) -> String {
167 if self.history.is_empty() {
168 return String::new();
169 }
170
171 let event_history = self.world_state.event_history();
172 let mut precedes = Vec::new();
173 for i in 0..event_history.len().saturating_sub(1) {
174 precedes.push(format!("Precedes({}, {})", event_history[i], event_history[i + 1]));
175 }
176
177 if precedes.is_empty() {
178 self.history.join(" ∧ ")
179 } else {
180 format!("{} ∧ {}", self.history.join(" ∧ "), precedes.join(" ∧ "))
181 }
182 }
183
184 pub fn turn_count(&self) -> usize {
186 self.history.len()
187 }
188
189 pub fn world_state(&self) -> &WorldState {
191 &self.world_state
192 }
193
194 pub fn world_state_mut(&mut self) -> &mut WorldState {
196 &mut self.world_state
197 }
198
199 pub fn reset(&mut self) {
201 self.world_state = WorldState::new();
202 self.history.clear();
203 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 #[test]
212 fn test_session_basic() {
213 let mut session = Session::new();
214 let out = session.eval("John walked.").unwrap();
215 assert!(out.contains("Walk"), "Should have Walk predicate");
216 }
217
218 #[test]
219 fn test_session_multiple_sentences() {
220 let mut session = Session::new();
221 session.eval("John walked.").unwrap();
222 session.eval("Mary ran.").unwrap();
223
224 assert_eq!(session.turn_count(), 2);
225
226 let history = session.history();
227 assert!(history.contains("Walk"));
228 assert!(history.contains("Run"));
229 assert!(history.contains("Precedes"));
230 }
231}