use crate::analysis;
use logicaffeine_base::Arena;
use crate::arena_ctx::AstContext;
use crate::drs::WorldState;
use crate::error::ParseError;
use logicaffeine_base::Interner;
use crate::lexer::Lexer;
use crate::mwe;
use crate::parser::Parser;
use crate::registry::SymbolRegistry;
use crate::semantics;
use crate::OutputFormat;
pub struct Session {
world_state: WorldState,
interner: Interner,
registry: SymbolRegistry,
mwe_trie: mwe::MweTrie,
history: Vec<String>,
format: OutputFormat,
}
impl Default for Session {
fn default() -> Self {
Self::new()
}
}
impl Session {
pub fn new() -> Self {
Session {
world_state: WorldState::new(),
interner: Interner::new(),
registry: SymbolRegistry::new(),
mwe_trie: mwe::build_mwe_trie(),
history: Vec::new(),
format: OutputFormat::Unicode,
}
}
pub fn with_format(format: OutputFormat) -> Self {
Session {
world_state: WorldState::new(),
interner: Interner::new(),
registry: SymbolRegistry::new(),
mwe_trie: mwe::build_mwe_trie(),
history: Vec::new(),
format,
}
}
pub fn eval(&mut self, input: &str) -> Result<String, ParseError> {
let event_var_name = self.world_state.next_event_var();
let event_var_symbol = self.interner.intern(&event_var_name);
let mut lexer = Lexer::new(input, &mut self.interner);
let tokens = lexer.tokenize();
let tokens = mwe::apply_mwe_pipeline(tokens, &self.mwe_trie, &mut self.interner);
let type_registry = {
let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut self.interner);
discovery.run()
};
let expr_arena = Arena::new();
let term_arena = Arena::new();
let np_arena = Arena::new();
let sym_arena = Arena::new();
let role_arena = Arena::new();
let pp_arena = Arena::new();
let ast_ctx = AstContext::new(
&expr_arena,
&term_arena,
&np_arena,
&sym_arena,
&role_arena,
&pp_arena,
);
let mut parser = Parser::new(
tokens,
&mut self.world_state,
&mut self.interner,
ast_ctx,
type_registry,
);
parser.set_discourse_event_var(event_var_symbol);
parser.swap_drs_with_world_state();
let ast = parser.parse()?;
parser.swap_drs_with_world_state();
self.world_state.end_sentence();
let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut self.interner);
let output = ast.transpile(&mut self.registry, &self.interner, self.format);
self.history.push(output.clone());
Ok(output)
}
pub fn history(&self) -> String {
if self.history.is_empty() {
return String::new();
}
let event_history = self.world_state.event_history();
let mut precedes = Vec::new();
for i in 0..event_history.len().saturating_sub(1) {
precedes.push(format!("Precedes({}, {})", event_history[i], event_history[i + 1]));
}
if precedes.is_empty() {
self.history.join(" ∧ ")
} else {
format!("{} ∧ {}", self.history.join(" ∧ "), precedes.join(" ∧ "))
}
}
pub fn turn_count(&self) -> usize {
self.history.len()
}
pub fn world_state(&self) -> &WorldState {
&self.world_state
}
pub fn world_state_mut(&mut self) -> &mut WorldState {
&mut self.world_state
}
pub fn reset(&mut self) {
self.world_state = WorldState::new();
self.history.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_session_basic() {
let mut session = Session::new();
let out = session.eval("John walked.").unwrap();
assert!(out.contains("Walk"), "Should have Walk predicate");
}
#[test]
fn test_session_multiple_sentences() {
let mut session = Session::new();
session.eval("John walked.").unwrap();
session.eval("Mary ran.").unwrap();
assert_eq!(session.turn_count(), 2);
let history = session.history();
assert!(history.contains("Walk"));
assert!(history.contains("Run"));
assert!(history.contains("Precedes"));
}
}