Skip to content

Commit

Permalink
add pretty printer and ability to evaluate binding from string.
Browse files Browse the repository at this point in the history
  • Loading branch information
yliuuuu committed Jan 16, 2024
1 parent 824031f commit 4676500
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 12 deletions.
55 changes: 43 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
mod pretty;

use crate::pretty::PrettyPrint;

use partiql_eval as eval;
use partiql_eval::env::basic::MapBindings;
use partiql_logical as logical;
use partiql_logical_planner::lower;
use partiql_parser::{Parsed, Parser, ParserResult};
use partiql_value::ion::parse_ion;
use partiql_value::Value;

use wasm_bindgen::prelude::wasm_bindgen;

Expand Down Expand Up @@ -36,23 +40,50 @@ pub fn eval_as_string(statement: &str, env: &str) -> String {
let parsed = parse(statement);
match parsed {
Ok(p) => {
format!("{:?}", eval(&p, env))
}
Err(e) => {
format!("{:?}", e)
let value = eval(&p, env);
match value {
Ok(v) => {
let mut pretty = String::new();
let res = v.pretty(&mut pretty);
match res {
Ok(..) => pretty,
Err(e) => format!("{:?}", e)
}
}
Err(e) => format!("{:?}", e)
}
}
Err(e) => format!("{:?}", e)
}
}

pub(crate) fn parse(statement: &str) -> ParserResult {
Parser::default().parse(statement)
}

fn eval(p: &Parsed, env: &str) -> partiql_value::Value {
fn eval(p: &Parsed, env: &str) -> Result<Value, String> {
let lowered = lower(p);
let env_as_value = parse_ion(env);
let bindings: MapBindings<partiql_value::Value> = MapBindings::from(env_as_value);
evaluate(lowered, bindings)
let env_as_value = get_bindings(env);
match env_as_value {
Ok(bindings) => Ok(evaluate(lowered, bindings)),
Err(e) => Err(format!("{:?}", e))
}
}


fn get_bindings(env: &str) -> Result<MapBindings<Value>, String> {
let parsed = parse(env);
match parsed {
Ok(p) => {
let lowered = lower(&p);
let res = evaluate(lowered, MapBindings::default());
match res {
Value::Tuple(t) => Ok(MapBindings::from(*t)),
_ => Err("Error in Env; Expected a struct containing the input environment".to_string())
}
}
Err(e) => Err(format!("{:?}", e))
}
}

/// Creates a logical plan for the given query and returns the json serialized string.
Expand All @@ -73,15 +104,15 @@ pub fn explain_as_string(statement: &str) -> String {

fn evaluate(
logical: logical::LogicalPlan<logical::BindingsOp>,
bindings: MapBindings<partiql_value::Value>,
) -> partiql_value::Value {
bindings: MapBindings<Value>,
) -> Value {
let planner = eval::plan::EvaluatorPlanner;

let mut plan = planner.compile(&logical);

if let Ok(out) = plan.execute_mut(bindings) {
out.result
} else {
partiql_value::Value::Missing
Value::Missing
}
}
68 changes: 68 additions & 0 deletions src/pretty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use partiql_value::Value;

use std::fmt::Result;
use std::fmt::Write;

pub trait PrettyPrint {
fn pretty(&self, f: &mut String) -> Result;
}

impl PrettyPrint for Value {
fn pretty(&self, s: &mut String) -> Result {
pretty(self, s, 0)
}
}

fn pretty(value: &Value, s: &mut String, cur_indent_size: usize) -> Result {
// For now, defining an indent to be two spaces. We could allow users to pass in an indent string
// for more control.
let indent = " ".repeat(cur_indent_size);
match value {
Value::List(l) => {
writeln!(s, "[")?;
let mut iter = l.iter().peekable();
while let Some(v) = iter.next() {
if iter.peek().is_some() {
write!(s, "{indent} ")?;
pretty(v, s, cur_indent_size + 1)?;
writeln!(s, ",")?;
} else {
write!(s, "{indent} ")?;
pretty(v, s, cur_indent_size + 1)?;
}
}
write!(s, "\n{indent}]")
}
Value::Bag(b) => {
writeln!(s, "<<")?;
let mut iter = b.iter().peekable();
while let Some(v) = iter.next() {
if iter.peek().is_some() {
write!(s, "{indent} ")?;
pretty(v, s, cur_indent_size + 1)?;
writeln!(s, ",")?;
} else {
write!(s, "{indent} ")?;
pretty(v, s, cur_indent_size + 1)?;
}
}
write!(s, "\n{indent}>>")
}
Value::Tuple(t) => {
writeln!(s, "{{")?;
let mut iter = t.pairs().peekable();
while let Some((k, v)) = iter.next() {
if iter.peek().is_some() {
write!(s, "{indent} {k}: ")?;
pretty(v, s, cur_indent_size + 1)?;
writeln!(s, ",")?;
} else {
write!(s, "{indent} {k}: ")?;
pretty(v, s, cur_indent_size + 1)?;
}
}
write!(s, "\n{indent}}}")
}
_ => write!(s, "{value:?}"),
}
}

0 comments on commit 4676500

Please sign in to comment.