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 with_format(format: OutputFormat) -> Self {
74 Session {
75 world_state: WorldState::new(),
76 interner: Interner::new(),
77 registry: SymbolRegistry::new(),
78 mwe_trie: mwe::build_mwe_trie(),
79 history: Vec::new(),
80 format,
81 }
82 }
83
84 pub fn eval(&mut self, input: &str) -> Result<String, ParseError> {
89 let event_var_name = self.world_state.next_event_var();
91 let event_var_symbol = self.interner.intern(&event_var_name);
92
93 let mut lexer = Lexer::new(input, &mut self.interner);
95 let tokens = lexer.tokenize();
96
97 let tokens = mwe::apply_mwe_pipeline(tokens, &self.mwe_trie, &mut self.interner);
99
100 let type_registry = {
102 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut self.interner);
103 discovery.run()
104 };
105
106 let expr_arena = Arena::new();
108 let term_arena = Arena::new();
109 let np_arena = Arena::new();
110 let sym_arena = Arena::new();
111 let role_arena = Arena::new();
112 let pp_arena = Arena::new();
113
114 let ast_ctx = AstContext::new(
115 &expr_arena,
116 &term_arena,
117 &np_arena,
118 &sym_arena,
119 &role_arena,
120 &pp_arena,
121 );
122
123 let mut parser = Parser::new(
125 tokens,
126 &mut self.world_state,
127 &mut self.interner,
128 ast_ctx,
129 type_registry,
130 );
131 parser.set_discourse_event_var(event_var_symbol);
132
133 parser.swap_drs_with_world_state();
135 let ast = parser.parse()?;
136 parser.swap_drs_with_world_state();
138
139 self.world_state.end_sentence();
141
142 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut self.interner);
144
145 let output = ast.transpile(&mut self.registry, &self.interner, self.format);
147
148 self.history.push(output.clone());
150
151 Ok(output)
152 }
153
154 pub fn history(&self) -> String {
158 if self.history.is_empty() {
159 return String::new();
160 }
161
162 let event_history = self.world_state.event_history();
163 let mut precedes = Vec::new();
164 for i in 0..event_history.len().saturating_sub(1) {
165 precedes.push(format!("Precedes({}, {})", event_history[i], event_history[i + 1]));
166 }
167
168 if precedes.is_empty() {
169 self.history.join(" ∧ ")
170 } else {
171 format!("{} ∧ {}", self.history.join(" ∧ "), precedes.join(" ∧ "))
172 }
173 }
174
175 pub fn turn_count(&self) -> usize {
177 self.history.len()
178 }
179
180 pub fn world_state(&self) -> &WorldState {
182 &self.world_state
183 }
184
185 pub fn world_state_mut(&mut self) -> &mut WorldState {
187 &mut self.world_state
188 }
189
190 pub fn reset(&mut self) {
192 self.world_state = WorldState::new();
193 self.history.clear();
194 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn test_session_basic() {
204 let mut session = Session::new();
205 let out = session.eval("John walked.").unwrap();
206 assert!(out.contains("Walk"), "Should have Walk predicate");
207 }
208
209 #[test]
210 fn test_session_multiple_sentences() {
211 let mut session = Session::new();
212 session.eval("John walked.").unwrap();
213 session.eval("Mary ran.").unwrap();
214
215 assert_eq!(session.turn_count(), 2);
216
217 let history = session.history();
218 assert!(history.contains("Walk"));
219 assert!(history.contains("Run"));
220 assert!(history.contains("Precedes"));
221 }
222}