flowlog-build 0.2.2

Build-time FlowLog compiler for library mode.
Documentation
mod errors;

use flowlog_build::common::{Config, SourceMap};
use flowlog_build::optimizer::Optimizer;
use flowlog_build::parser::Program;
use flowlog_build::planner::{PlanError, StratumPlanner};
use flowlog_build::stratifier::Stratifier;

use errors::{fixture, render};

fn plan_fixture(name: &str) -> (Result<(), PlanError>, SourceMap) {
    let mut sm = SourceMap::new();
    let path = fixture("planner", name);
    let program = Program::parse(&path, false, &mut sm).expect("fixture should parse cleanly");
    let stratifier =
        Stratifier::from_program(&program, false).expect("fixture should stratify cleanly");

    let config = Config {
        program: path,
        output_dir: Some("-".into()),
        ..Default::default()
    };
    let mut optimizer = Optimizer::new();
    let mut profiler = None;

    for (idx, rule_refs) in stratifier.stratum().iter().enumerate() {
        let rules: Vec<_> = rule_refs.iter().map(|&r| r.clone()).collect();
        if let Err(e) = StratumPlanner::from_rules(
            &config,
            &rules,
            &mut optimizer,
            &mut profiler,
            &stratifier,
            idx,
        ) {
            return (Err(e), sm);
        }
    }
    (Ok(()), sm)
}

#[test]
fn unknown_head_variable() {
    assert_err!(
        plan_fixture("unknown_head_variable.dl"),
        PlanError::UnknownHeadVariable { ref var, .. } if var == "salutation",
        ["unknown head variable", "salutation", "never bound"]
    );
}

#[test]
fn multiple_aggregations_in_head() {
    assert_err!(
        plan_fixture("multiple_aggregations_in_head.dl"),
        PlanError::MultipleAggregationsInHead { ref rel, count: 2, .. } if rel == "totals",
        ["contains 2 aggregations", "at most one is allowed"]
    );
}

#[test]
fn inconsistent_aggregation() {
    assert_err!(
        plan_fixture("inconsistent_aggregation.dl"),
        PlanError::InconsistentAggregation { .. },
        [
            "inconsistent aggregation",
            "totals",
            "conflicting aggregation"
        ]
    );
}