use std::io;
use anyhow::Result;
use codespan_reporting::term::termcolor::StandardStream;
use syntree::node::Children;
use syntree::{Span, Tree};
use crate::db;
use crate::error::Error;
use crate::eval::Context;
use crate::numeric::Numeric;
use crate::syntax::parser::{Parser, Syntax};
pub enum Description {
Constant(Box<str>, db::Constant),
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Options {
pub(crate) describe: bool,
}
impl Options {
pub fn describe(self) -> Self {
Self { describe: true }
}
}
pub struct Parsed<'a> {
source: &'a str,
tree: Tree<Syntax, u32, u32>,
}
impl Parsed<'_> {
pub fn emit(&self, o: &mut StandardStream) -> Result<(), io::Error> {
syntree::print::print_with_source(o, &self.tree, self.source)
}
}
pub fn parse(source: &str) -> Result<Parsed<'_>> {
let parser = Parser::new(source);
let tree = parser.parse_root()?;
Ok(Parsed { source, tree })
}
pub fn query<'a>(
parsed: &'a Parsed<'_>,
db: &'a db::Db,
options: Options,
descriptions: &'a mut Vec<Description>,
) -> Query<'a> {
Query {
ctx: Context::new(),
source: parsed.source,
db,
children: parsed.tree.children(),
options,
descriptions,
}
}
pub struct Query<'a> {
#[allow(unused)]
pub(crate) ctx: Context,
pub(crate) source: &'a str,
pub(crate) db: &'a db::Db,
pub(crate) children: Children<'a, Syntax, u32, u32>,
pub(crate) options: Options,
pub(crate) descriptions: &'a mut Vec<Description>,
}
impl<'a> Query<'a> {
pub(crate) fn source_as_str(&self) -> &'a str {
self.source
}
pub(crate) fn source(&self, span: Span<u32>) -> &'a str {
&self.source[span.range()]
}
}
impl Iterator for Query<'_> {
type Item = Result<Numeric, Error>;
fn next(&mut self) -> Option<Self::Item> {
let node = self.children.next()?;
Some(crate::eval::eval(self, node, Default::default()))
}
}