use crate::edb::{Fact, Relation};
use crate::idb::{Rule, RuleSet};
use crate::syntax::{
CHAR_COLON, CHAR_LEFT_PAREN, CHAR_PERIOD, CHAR_RIGHT_PAREN, COMMA_SEPARATOR, PRAGMA_ID_FD,
PRAGMA_ID_INPUT, PRAGMA_ID_OUTPUT,
};
use crate::visitor::{ProgramVisitor, ProgramWriter, QueryVisitor, RelationVisitor, RuleVisitor};
use crate::{Collection, Labeled, Program, ProgramCore, Query};
use std::cell::RefCell;
use std::io::Write;
#[derive(Debug)]
pub struct NativeFormatter<W: Write> {
writer: RefCell<W>,
}
pub fn make_native_writer<W: Write>(writer: W) -> NativeFormatter<W> {
NativeFormatter {
writer: RefCell::new(writer),
}
}
impl<W: Write> ProgramWriter for NativeFormatter<W> {}
impl<W: Write> ProgramVisitor for NativeFormatter<W> {
fn start_program(&self, program: &Program) -> crate::Result<()> {
let writer = &mut self.writer.borrow_mut();
write!(writer, "{}", program.features())?;
for edb in [true, false] {
let relations = if edb {
program.extensional()
} else {
program.intensional()
};
if !relations.is_empty() {
for relation in relations.iter() {
writeln!(writer, "{}", relation.to_schema_decl(edb, false))?;
if let Some(file_pragma) = relation.file_pragma() {
let pragma_id = if edb {
PRAGMA_ID_INPUT
} else {
PRAGMA_ID_OUTPUT
};
write!(
writer,
"{}{}{}{}{}{:?}{}{}{}{}",
CHAR_PERIOD,
pragma_id,
CHAR_LEFT_PAREN,
relation.label(),
COMMA_SEPARATOR,
file_pragma.file_name(),
COMMA_SEPARATOR,
file_pragma.file_format().label(),
CHAR_RIGHT_PAREN,
CHAR_PERIOD,
)?;
}
for dependency in relation.schema().functional_dependencies() {
writeln!(
writer,
"{}{} {}{} {}{}",
CHAR_PERIOD,
PRAGMA_ID_FD,
relation.label(),
CHAR_COLON,
dependency,
CHAR_PERIOD,
)?;
}
}
writeln!(writer)?;
}
}
Ok(())
}
fn relation_visitor(&self) -> Option<&dyn RelationVisitor> {
Some(self)
}
fn rule_visitor(&self) -> Option<&dyn RuleVisitor> {
Some(self)
}
fn query_visitor(&self) -> Option<&dyn QueryVisitor> {
Some(self)
}
}
impl<W: Write> RelationVisitor for NativeFormatter<W> {
fn fact(&self, fact: &Fact) -> crate::Result<()> {
writeln!(self.writer.borrow_mut(), "{}", fact)?;
Ok(())
}
fn end_relation(&self, relation: &Relation, _: bool) -> crate::Result<()> {
if !relation.is_empty() {
writeln!(self.writer.borrow_mut())?;
}
Ok(())
}
}
impl<W: Write> RuleVisitor for NativeFormatter<W> {
fn rule(&self, rule: &Rule) -> crate::Result<()> {
writeln!(self.writer.borrow_mut(), "{}", rule)?;
Ok(())
}
fn end_rules(&self, _: &RuleSet) -> crate::Result<()> {
writeln!(self.writer.borrow_mut())?;
Ok(())
}
}
impl<W: Write> QueryVisitor for NativeFormatter<W> {
fn query(&self, query: &Query) -> crate::Result<()> {
writeln!(self.writer.borrow_mut(), "{}", query)?;
Ok(())
}
}