naming consistency

main
Ziyang Hu 2 years ago
parent 9cadfc48a7
commit 82dd566717

@ -7,8 +7,8 @@
*/ */
script = _{sys_script | multi_script | query_script} script = _{sys_script | multi_script | query_script}
query_script = {SOI ~ (option | rule | const_rule | algo_rule)+ ~ EOI} query_script = {SOI ~ (option | rule | const_rule | fixed_rule)+ ~ EOI}
query_script_inner = {"{" ~ (option | rule | const_rule | algo_rule)+ ~ "}"} query_script_inner = {"{" ~ (option | rule | const_rule | fixed_rule)+ ~ "}"}
multi_script = {SOI ~ query_script_inner+ ~ EOI} multi_script = {SOI ~ query_script_inner+ ~ EOI}
sys_script = {SOI ~ "::" ~ (compact_op | list_relations_op | list_relation_op | remove_relations_op | trigger_relation_op | sys_script = {SOI ~ "::" ~ (compact_op | list_relations_op | list_relation_op | remove_relations_op | trigger_relation_op |
trigger_relation_show_op | rename_relations_op | running_op | kill_op | explain_op | access_level_op) ~ EOI} trigger_relation_show_op | rename_relations_op | running_op | kill_op | explain_op | access_level_op) ~ EOI}
@ -48,19 +48,19 @@ compound_ident = @{ident ~ ("." ~ ident)?}
rule = {rule_head ~ ":=" ~ rule_body ~ ";"?} rule = {rule_head ~ ":=" ~ rule_body ~ ";"?}
const_rule = {rule_head ~ "<-" ~ expr ~ ";"?} const_rule = {rule_head ~ "<-" ~ expr ~ ";"?}
algo_rule = {rule_head ~ "<~" ~ ident ~ algo_args_list ~ ";"?} fixed_rule = {rule_head ~ "<~" ~ ident ~ fixed_args_list ~ ";"?}
algo_args_list = {"(" ~ (algo_arg ~ ",")* ~ algo_arg? ~ ")"} fixed_args_list = {"(" ~ (fixed_arg ~ ",")* ~ fixed_arg? ~ ")"}
rule_head = {(prog_entry | ident) ~ "[" ~ (head_arg ~ ",")* ~ head_arg? ~ "]"} rule_head = {(prog_entry | ident) ~ "[" ~ (head_arg ~ ",")* ~ head_arg? ~ "]"}
head_arg = {aggr_arg | var} head_arg = {aggr_arg | var}
aggr_arg = {ident ~ "(" ~ var ~ ("," ~ expr)* ~ ")"} aggr_arg = {ident ~ "(" ~ var ~ ("," ~ expr)* ~ ")"}
algo_arg = _{algo_rel | algo_opt_pair} fixed_arg = _{fixed_rel | fixed_opt_pair}
algo_opt_pair = {ident ~ ":" ~ expr} fixed_opt_pair = {ident ~ ":" ~ expr}
algo_rel = {algo_rule_rel | algo_relation_rel | algo_named_relation_rel } fixed_rel = {fixed_rule_rel | fixed_relation_rel | fixed_named_relation_rel }
algo_rule_rel = {ident ~ "[" ~ (var ~ ",")* ~ var? ~ "]"} fixed_rule_rel = {ident ~ "[" ~ (var ~ ",")* ~ var? ~ "]"}
algo_relation_rel = {relation_ident ~ "[" ~ (var ~ ",")* ~ var? ~ "]"} fixed_relation_rel = {relation_ident ~ "[" ~ (var ~ ",")* ~ var? ~ "]"}
algo_named_relation_rel = {relation_ident ~ "{" ~ (algo_named_relation_arg_pair ~ ",")* ~ algo_named_relation_arg_pair? ~ "}"} fixed_named_relation_rel = {relation_ident ~ "{" ~ (fixed_named_relation_arg_pair ~ ",")* ~ fixed_named_relation_arg_pair? ~ "}"}
algo_named_relation_arg_pair = {ident ~ (":" ~ ident)?} fixed_named_relation_arg_pair = {ident ~ (":" ~ ident)?}
rule_body = {(disjunction ~ ",")* ~ disjunction?} rule_body = {(disjunction ~ ",")* ~ disjunction?}
rule_apply = {underscore_ident ~ "[" ~ apply_args ~ "]"} rule_apply = {underscore_ident ~ "[" ~ apply_args ~ "]"}

@ -17,12 +17,12 @@ use smallvec::SmallVec;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use thiserror::Error; use thiserror::Error;
use crate::algo::{AlgoHandle, AlgoImpl};
use crate::data::aggr::Aggregation; use crate::data::aggr::Aggregation;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::relation::StoredRelationMetadata; use crate::data::relation::StoredRelationMetadata;
use crate::data::symb::{Symbol, PROG_ENTRY}; use crate::data::symb::{Symbol, PROG_ENTRY};
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::fixed_rule::{FixedRule, FixedRuleHandle};
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::relation::InputRelationHandle; use crate::runtime::relation::InputRelationHandle;
use crate::runtime::temp_store::EpochStore; use crate::runtime::temp_store::EpochStore;
@ -187,78 +187,80 @@ impl TempSymbGen {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum InputInlineRulesOrAlgo { pub(crate) enum InputInlineRulesOrFixed {
Rules { rules: Vec<InputInlineRule> }, Rules { rules: Vec<InputInlineRule> },
Algo { algo: AlgoApply }, Fixed { fixed: FixedRuleApply },
} }
impl InputInlineRulesOrAlgo { impl InputInlineRulesOrFixed {
pub(crate) fn first_span(&self) -> SourceSpan { pub(crate) fn first_span(&self) -> SourceSpan {
match self { match self {
InputInlineRulesOrAlgo::Rules { rules, .. } => rules[0].span, InputInlineRulesOrFixed::Rules { rules, .. } => rules[0].span,
InputInlineRulesOrAlgo::Algo { algo, .. } => algo.span, InputInlineRulesOrFixed::Fixed { fixed, .. } => fixed.span,
} }
} }
} }
pub(crate) struct AlgoApply { pub(crate) struct FixedRuleApply {
pub(crate) algo: AlgoHandle, pub(crate) fixed_handle: FixedRuleHandle,
pub(crate) rule_args: Vec<AlgoRuleArg>, pub(crate) rule_args: Vec<FixedRuleArg>,
pub(crate) options: Rc<BTreeMap<SmartString<LazyCompact>, Expr>>, pub(crate) options: Rc<BTreeMap<SmartString<LazyCompact>, Expr>>,
pub(crate) head: Vec<Symbol>, pub(crate) head: Vec<Symbol>,
pub(crate) arity: usize, pub(crate) arity: usize,
pub(crate) span: SourceSpan, pub(crate) span: SourceSpan,
pub(crate) algo_impl: Arc<Box<dyn AlgoImpl>>, pub(crate) fixed_impl: Arc<Box<dyn FixedRule>>,
} }
impl AlgoApply { impl FixedRuleApply {
pub(crate) fn arity(&self) -> Result<usize> { pub(crate) fn arity(&self) -> Result<usize> {
self.algo_impl.as_ref().arity(&self.options, &self.head, self.span) self.fixed_impl
.as_ref()
.arity(&self.options, &self.head, self.span)
} }
} }
impl Debug for AlgoApply { impl Debug for FixedRuleApply {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AlgoApply") f.debug_struct("FixedRuleApply")
.field("algo", &self.algo.name) .field("name", &self.fixed_handle.name)
.field("rules", &self.rule_args) .field("rules", &self.rule_args)
.field("options", &self.options) .field("options", &self.options)
.finish() .finish()
} }
} }
pub(crate) struct MagicAlgoApply { pub(crate) struct MagicFixedRuleApply {
pub(crate) algo: AlgoHandle, pub(crate) fixed_handle: FixedRuleHandle,
pub(crate) rule_args: Vec<MagicAlgoRuleArg>, pub(crate) rule_args: Vec<MagicFixedRuleRuleArg>,
pub(crate) options: Rc<BTreeMap<SmartString<LazyCompact>, Expr>>, pub(crate) options: Rc<BTreeMap<SmartString<LazyCompact>, Expr>>,
pub(crate) span: SourceSpan, pub(crate) span: SourceSpan,
pub(crate) arity: usize, pub(crate) arity: usize,
pub(crate) algo_impl: Arc<Box<dyn AlgoImpl>>, pub(crate) fixed_impl: Arc<Box<dyn FixedRule>>,
} }
#[derive(Error, Diagnostic, Debug)] #[derive(Error, Diagnostic, Debug)]
#[error("Cannot find a required named option '{name}' for '{algo_name}'")] #[error("Cannot find a required named option '{name}' for '{rule_name}'")]
#[diagnostic(code(algo::arg_not_found))] #[diagnostic(code(fixed_rule::arg_not_found))]
pub(crate) struct AlgoOptionNotFoundError { pub(crate) struct FixedRuleOptionNotFoundError {
pub(crate) name: String, pub(crate) name: String,
#[label] #[label]
pub(crate) span: SourceSpan, pub(crate) span: SourceSpan,
pub(crate) algo_name: String, pub(crate) rule_name: String,
} }
#[derive(Error, Diagnostic, Debug)] #[derive(Error, Diagnostic, Debug)]
#[error("Wrong value for option '{name}' of '{algo_name}'")] #[error("Wrong value for option '{name}' of '{rule_name}'")]
#[diagnostic(code(algo::arg_wrong))] #[diagnostic(code(fixed_rule::arg_wrong))]
pub(crate) struct WrongAlgoOptionError { pub(crate) struct WrongFixedRuleOptionError {
pub(crate) name: String, pub(crate) name: String,
#[label] #[label]
pub(crate) span: SourceSpan, pub(crate) span: SourceSpan,
pub(crate) algo_name: String, pub(crate) rule_name: String,
#[help] #[help]
pub(crate) help: String, pub(crate) help: String,
} }
impl MagicAlgoApply { impl MagicFixedRuleApply {
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn relation_with_min_len( pub(crate) fn relation_with_min_len(
&self, &self,
@ -266,11 +268,11 @@ impl MagicAlgoApply {
len: usize, len: usize,
tx: &SessionTx<'_>, tx: &SessionTx<'_>,
stores: &BTreeMap<MagicSymbol, EpochStore>, stores: &BTreeMap<MagicSymbol, EpochStore>,
) -> Result<&MagicAlgoRuleArg> { ) -> Result<&MagicFixedRuleRuleArg> {
#[derive(Error, Diagnostic, Debug)] #[derive(Error, Diagnostic, Debug)]
#[error("Input relation to algorithm has insufficient arity")] #[error("Input relation to fixed rule has insufficient arity")]
#[diagnostic(help("Arity should be at least {0} but is {1}"))] #[diagnostic(help("Arity should be at least {0} but is {1}"))]
#[diagnostic(code(algo::input_relation_bad_arity))] #[diagnostic(code(fixed_rule::input_relation_bad_arity))]
struct InputRelationArityError(usize, usize, #[label] SourceSpan); struct InputRelationArityError(usize, usize, #[label] SourceSpan);
let rel = self.relation(idx)?; let rel = self.relation(idx)?;
@ -281,39 +283,39 @@ impl MagicAlgoApply {
); );
Ok(rel) Ok(rel)
} }
pub(crate) fn relation(&self, idx: usize) -> Result<&MagicAlgoRuleArg> { pub(crate) fn relation(&self, idx: usize) -> Result<&MagicFixedRuleRuleArg> {
#[derive(Error, Diagnostic, Debug)] #[derive(Error, Diagnostic, Debug)]
#[error("Cannot find a required positional argument at index {idx} for '{algo_name}'")] #[error("Cannot find a required positional argument at index {idx} for '{rule_name}'")]
#[diagnostic(code(algo::not_enough_args))] #[diagnostic(code(fixed_rule::not_enough_args))]
pub(crate) struct AlgoNotEnoughRelationError { pub(crate) struct FixedRuleNotEnoughRelationError {
idx: usize, idx: usize,
#[label] #[label]
span: SourceSpan, span: SourceSpan,
algo_name: String, rule_name: String,
} }
Ok(self Ok(self
.rule_args .rule_args
.get(idx) .get(idx)
.ok_or_else(|| AlgoNotEnoughRelationError { .ok_or_else(|| FixedRuleNotEnoughRelationError {
idx, idx,
span: self.span, span: self.span,
algo_name: self.algo.name.to_string(), rule_name: self.fixed_handle.name.to_string(),
})?) })?)
} }
} }
impl Debug for MagicAlgoApply { impl Debug for MagicFixedRuleApply {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AlgoApply") f.debug_struct("FixedRuleApply")
.field("algo", &self.algo.name) .field("name", &self.fixed_handle.name)
.field("rules", &self.rule_args) .field("rules", &self.rule_args)
.field("options", &self.options) .field("options", &self.options)
.finish() .finish()
} }
} }
pub(crate) enum AlgoRuleArg { pub(crate) enum FixedRuleArg {
InMem { InMem {
name: Symbol, name: Symbol,
bindings: Vec<Symbol>, bindings: Vec<Symbol>,
@ -331,24 +333,24 @@ pub(crate) enum AlgoRuleArg {
}, },
} }
impl Debug for AlgoRuleArg { impl Debug for FixedRuleArg {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self) write!(f, "{}", self)
} }
} }
impl Display for AlgoRuleArg { impl Display for FixedRuleArg {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self { match self {
AlgoRuleArg::InMem { name, bindings, .. } => { FixedRuleArg::InMem { name, bindings, .. } => {
write!(f, "{}", name)?; write!(f, "{}", name)?;
f.debug_list().entries(bindings).finish()?; f.debug_list().entries(bindings).finish()?;
} }
AlgoRuleArg::Stored { name, bindings, .. } => { FixedRuleArg::Stored { name, bindings, .. } => {
write!(f, ":{}", name)?; write!(f, ":{}", name)?;
f.debug_list().entries(bindings).finish()?; f.debug_list().entries(bindings).finish()?;
} }
AlgoRuleArg::NamedStored { name, bindings, .. } => { FixedRuleArg::NamedStored { name, bindings, .. } => {
write!(f, "*")?; write!(f, "*")?;
let mut sf = f.debug_struct(name); let mut sf = f.debug_struct(name);
for (k, v) in bindings { for (k, v) in bindings {
@ -362,7 +364,7 @@ impl Display for AlgoRuleArg {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum MagicAlgoRuleArg { pub(crate) enum MagicFixedRuleRuleArg {
InMem { InMem {
name: MagicSymbol, name: MagicSymbol,
bindings: Vec<Symbol>, bindings: Vec<Symbol>,
@ -375,24 +377,25 @@ pub(crate) enum MagicAlgoRuleArg {
}, },
} }
impl MagicAlgoRuleArg { impl MagicFixedRuleRuleArg {
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn bindings(&self) -> &[Symbol] { pub(crate) fn bindings(&self) -> &[Symbol] {
match self { match self {
MagicAlgoRuleArg::InMem { bindings, .. } MagicFixedRuleRuleArg::InMem { bindings, .. }
| MagicAlgoRuleArg::Stored { bindings, .. } => bindings, | MagicFixedRuleRuleArg::Stored { bindings, .. } => bindings,
} }
} }
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn span(&self) -> SourceSpan { pub(crate) fn span(&self) -> SourceSpan {
match self { match self {
MagicAlgoRuleArg::InMem { span, .. } | MagicAlgoRuleArg::Stored { span, .. } => *span, MagicFixedRuleRuleArg::InMem { span, .. }
| MagicFixedRuleRuleArg::Stored { span, .. } => *span,
} }
} }
pub(crate) fn get_binding_map(&self, starting: usize) -> BTreeMap<Symbol, usize> { pub(crate) fn get_binding_map(&self, starting: usize) -> BTreeMap<Symbol, usize> {
let bindings = match self { let bindings = match self {
MagicAlgoRuleArg::InMem { bindings, .. } MagicFixedRuleRuleArg::InMem { bindings, .. }
| MagicAlgoRuleArg::Stored { bindings, .. } => bindings, | MagicFixedRuleRuleArg::Stored { bindings, .. } => bindings,
}; };
bindings bindings
.iter() .iter()
@ -404,7 +407,7 @@ impl MagicAlgoRuleArg {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct InputProgram { pub(crate) struct InputProgram {
pub(crate) prog: BTreeMap<Symbol, InputInlineRulesOrAlgo>, pub(crate) prog: BTreeMap<Symbol, InputInlineRulesOrFixed>,
pub(crate) out_opts: QueryOutOptions, pub(crate) out_opts: QueryOutOptions,
} }
@ -412,7 +415,7 @@ impl Display for InputProgram {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for (name, rules) in &self.prog { for (name, rules) in &self.prog {
match rules { match rules {
InputInlineRulesOrAlgo::Rules { rules, .. } => { InputInlineRulesOrFixed::Rules { rules, .. } => {
for InputInlineRule { for InputInlineRule {
head, aggr, body, .. head, aggr, body, ..
} in rules } in rules
@ -443,10 +446,10 @@ impl Display for InputProgram {
writeln!(f, ";")?; writeln!(f, ";")?;
} }
} }
InputInlineRulesOrAlgo::Algo { InputInlineRulesOrFixed::Fixed {
algo: fixed:
AlgoApply { FixedRuleApply {
algo, fixed_handle: handle,
rule_args, rule_args,
options, options,
head, head,
@ -456,7 +459,7 @@ impl Display for InputProgram {
write!(f, "{}", name)?; write!(f, "{}", name)?;
f.debug_list().entries(head).finish()?; f.debug_list().entries(head).finish()?;
write!(f, " <~ ")?; write!(f, " <~ ")?;
write!(f, "{}(", algo.name)?; write!(f, "{}(", handle.name)?;
let mut first = true; let mut first = true;
for rule_arg in rule_args { for rule_arg in rule_args {
if first { if first {
@ -499,8 +502,8 @@ impl InputProgram {
pub(crate) fn get_entry_arity(&self) -> Result<usize> { pub(crate) fn get_entry_arity(&self) -> Result<usize> {
if let Some(entry) = self.prog.get(&Symbol::new(PROG_ENTRY, SourceSpan(0, 0))) { if let Some(entry) = self.prog.get(&Symbol::new(PROG_ENTRY, SourceSpan(0, 0))) {
return match entry { return match entry {
InputInlineRulesOrAlgo::Rules { rules } => Ok(rules.last().unwrap().head.len()), InputInlineRulesOrFixed::Rules { rules } => Ok(rules.last().unwrap().head.len()),
InputInlineRulesOrAlgo::Algo { algo: algo_apply } => algo_apply.arity(), InputInlineRulesOrFixed::Fixed { fixed } => fixed.arity(),
}; };
} }
@ -520,7 +523,7 @@ impl InputProgram {
pub(crate) fn get_entry_out_head(&self) -> Result<Vec<Symbol>> { pub(crate) fn get_entry_out_head(&self) -> Result<Vec<Symbol>> {
if let Some(entry) = self.prog.get(&Symbol::new(PROG_ENTRY, SourceSpan(0, 0))) { if let Some(entry) = self.prog.get(&Symbol::new(PROG_ENTRY, SourceSpan(0, 0))) {
return match entry { return match entry {
InputInlineRulesOrAlgo::Rules { rules } => { InputInlineRulesOrFixed::Rules { rules } => {
let head = &rules.last().unwrap().head; let head = &rules.last().unwrap().head;
let mut ret = Vec::with_capacity(head.len()); let mut ret = Vec::with_capacity(head.len());
let aggrs = &rules.last().unwrap().aggr; let aggrs = &rules.last().unwrap().aggr;
@ -543,11 +546,11 @@ impl InputProgram {
} }
Ok(ret) Ok(ret)
} }
InputInlineRulesOrAlgo::Algo { algo: algo_apply } => { InputInlineRulesOrFixed::Fixed { fixed } => {
if algo_apply.head.is_empty() { if fixed.head.is_empty() {
Err(EntryHeadNotExplicitlyDefinedError(entry.first_span()).into()) Err(EntryHeadNotExplicitlyDefinedError(entry.first_span()).into())
} else { } else {
Ok(algo_apply.head.to_vec()) Ok(fixed.head.to_vec())
} }
} }
}; };
@ -560,9 +563,9 @@ impl InputProgram {
tx: &SessionTx<'_>, tx: &SessionTx<'_>,
) -> Result<(NormalFormProgram, QueryOutOptions)> { ) -> Result<(NormalFormProgram, QueryOutOptions)> {
let mut prog: BTreeMap<Symbol, _> = Default::default(); let mut prog: BTreeMap<Symbol, _> = Default::default();
for (k, rules_or_algo) in self.prog { for (k, rules_or_fixed) in self.prog {
match rules_or_algo { match rules_or_fixed {
InputInlineRulesOrAlgo::Rules { rules } => { InputInlineRulesOrFixed::Rules { rules } => {
let mut collected_rules = vec![]; let mut collected_rules = vec![];
for rule in rules { for rule in rules {
let mut counter = -1; let mut counter = -1;
@ -615,13 +618,13 @@ impl InputProgram {
} }
prog.insert( prog.insert(
k.clone(), k.clone(),
NormalFormAlgoOrRules::Rules { NormalFormRulesOrFixed::Rules {
rules: collected_rules, rules: collected_rules,
}, },
); );
} }
InputInlineRulesOrAlgo::Algo { algo: algo_apply } => { InputInlineRulesOrFixed::Fixed { fixed } => {
prog.insert(k.clone(), NormalFormAlgoOrRules::Algo { algo: algo_apply }); prog.insert(k.clone(), NormalFormRulesOrFixed::Fixed { fixed });
} }
} }
} }
@ -633,58 +636,58 @@ impl InputProgram {
pub(crate) struct StratifiedNormalFormProgram(pub(crate) Vec<NormalFormProgram>); pub(crate) struct StratifiedNormalFormProgram(pub(crate) Vec<NormalFormProgram>);
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum NormalFormAlgoOrRules { pub(crate) enum NormalFormRulesOrFixed {
Rules { rules: Vec<NormalFormInlineRule> }, Rules { rules: Vec<NormalFormInlineRule> },
Algo { algo: AlgoApply }, Fixed { fixed: FixedRuleApply },
} }
impl NormalFormAlgoOrRules { impl NormalFormRulesOrFixed {
pub(crate) fn rules(&self) -> Option<&[NormalFormInlineRule]> { pub(crate) fn rules(&self) -> Option<&[NormalFormInlineRule]> {
match self { match self {
NormalFormAlgoOrRules::Rules { rules: r } => Some(r), NormalFormRulesOrFixed::Rules { rules: r } => Some(r),
NormalFormAlgoOrRules::Algo { algo: _ } => None, NormalFormRulesOrFixed::Fixed { fixed: _ } => None,
} }
} }
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct NormalFormProgram { pub(crate) struct NormalFormProgram {
pub(crate) prog: BTreeMap<Symbol, NormalFormAlgoOrRules>, pub(crate) prog: BTreeMap<Symbol, NormalFormRulesOrFixed>,
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct StratifiedMagicProgram(pub(crate) Vec<MagicProgram>); pub(crate) struct StratifiedMagicProgram(pub(crate) Vec<MagicProgram>);
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum MagicRulesOrAlgo { pub(crate) enum MagicRulesOrFixed {
Rules { rules: Vec<MagicInlineRule> }, Rules { rules: Vec<MagicInlineRule> },
Algo { algo: MagicAlgoApply }, Fixed { fixed: MagicFixedRuleApply },
} }
impl Default for MagicRulesOrAlgo { impl Default for MagicRulesOrFixed {
fn default() -> Self { fn default() -> Self {
Self::Rules { rules: vec![] } Self::Rules { rules: vec![] }
} }
} }
impl MagicRulesOrAlgo { impl MagicRulesOrFixed {
pub(crate) fn arity(&self) -> Result<usize> { pub(crate) fn arity(&self) -> Result<usize> {
Ok(match self { Ok(match self {
MagicRulesOrAlgo::Rules { rules } => rules.first().unwrap().head.len(), MagicRulesOrFixed::Rules { rules } => rules.first().unwrap().head.len(),
MagicRulesOrAlgo::Algo { algo } => algo.arity, MagicRulesOrFixed::Fixed { fixed } => fixed.arity,
}) })
} }
pub(crate) fn mut_rules(&mut self) -> Option<&mut Vec<MagicInlineRule>> { pub(crate) fn mut_rules(&mut self) -> Option<&mut Vec<MagicInlineRule>> {
match self { match self {
MagicRulesOrAlgo::Rules { rules } => Some(rules), MagicRulesOrFixed::Rules { rules } => Some(rules),
MagicRulesOrAlgo::Algo { algo: _ } => None, MagicRulesOrFixed::Fixed { fixed: _ } => None,
} }
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct MagicProgram { pub(crate) struct MagicProgram {
pub(crate) prog: BTreeMap<MagicSymbol, MagicRulesOrAlgo>, pub(crate) prog: BTreeMap<MagicSymbol, MagicRulesOrFixed>,
} }
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)] #[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]

@ -17,8 +17,8 @@ use priority_queue::PriorityQueue;
use rayon::prelude::*; use rayon::prelude::*;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::shortest_path_dijkstra::dijkstra_keep_ties; use crate::fixed_rule::algos::shortest_path_dijkstra::dijkstra_keep_ties;
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -28,10 +28,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct BetweennessCentrality; pub(crate) struct BetweennessCentrality;
impl AlgoImpl for BetweennessCentrality { impl FixedRule for BetweennessCentrality {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
@ -100,10 +100,10 @@ impl AlgoImpl for BetweennessCentrality {
pub(crate) struct ClosenessCentrality; pub(crate) struct ClosenessCentrality;
impl AlgoImpl for ClosenessCentrality { impl FixedRule for ClosenessCentrality {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -14,7 +14,7 @@ use ordered_float::OrderedFloat;
use priority_queue::PriorityQueue; use priority_queue::PriorityQueue;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoInputRelation, AlgoPayload, BadExprValueError, NodeNotFoundError}; use crate::fixed_rule::{FixedRule, FixedRuleInputRelation, FixedRulePayload, BadExprValueError, NodeNotFoundError};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple; use crate::data::tuple::Tuple;
@ -25,10 +25,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct ShortestPathAStar; pub(crate) struct ShortestPathAStar;
impl AlgoImpl for ShortestPathAStar { impl FixedRule for ShortestPathAStar {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
@ -72,8 +72,8 @@ impl AlgoImpl for ShortestPathAStar {
fn astar( fn astar(
starting: &Tuple, starting: &Tuple,
goal: &Tuple, goal: &Tuple,
edges: AlgoInputRelation<'_, '_>, edges: FixedRuleInputRelation<'_, '_>,
nodes: AlgoInputRelation<'_, '_>, nodes: FixedRuleInputRelation<'_, '_>,
heuristic: &Expr, heuristic: &Expr,
poison: Poison, poison: Poison,
) -> Result<(f64, Vec<DataValue>)> { ) -> Result<(f64, Vec<DataValue>)> {

@ -11,7 +11,7 @@ use std::collections::{BTreeMap, BTreeSet, VecDeque};
use miette::Result; use miette::Result;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload, NodeNotFoundError}; use crate::fixed_rule::{FixedRule, FixedRulePayload, NodeNotFoundError};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -21,10 +21,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct Bfs; pub(crate) struct Bfs;
impl AlgoImpl for Bfs { impl FixedRule for Bfs {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -11,7 +11,7 @@ use std::collections::BTreeMap;
use miette::Result; use miette::Result;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -21,10 +21,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct DegreeCentrality; pub(crate) struct DegreeCentrality;
impl AlgoImpl for DegreeCentrality { impl FixedRule for DegreeCentrality {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -11,7 +11,7 @@ use std::collections::{BTreeMap, BTreeSet};
use miette::Result; use miette::Result;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload, NodeNotFoundError}; use crate::fixed_rule::{FixedRule, FixedRulePayload, NodeNotFoundError};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -21,10 +21,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct Dfs; pub(crate) struct Dfs;
impl AlgoImpl for Dfs { impl FixedRule for Dfs {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -15,7 +15,7 @@ use ordered_float::OrderedFloat;
use priority_queue::PriorityQueue; use priority_queue::PriorityQueue;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -25,10 +25,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct MinimumSpanningForestKruskal; pub(crate) struct MinimumSpanningForestKruskal;
impl AlgoImpl for MinimumSpanningForestKruskal { impl FixedRule for MinimumSpanningForestKruskal {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -13,7 +13,7 @@ use miette::Result;
use rand::prelude::*; use rand::prelude::*;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -23,10 +23,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct LabelPropagation; pub(crate) struct LabelPropagation;
impl AlgoImpl for LabelPropagation { impl FixedRule for LabelPropagation {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -13,7 +13,7 @@ use log::debug;
use miette::Result; use miette::Result;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -23,10 +23,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct CommunityDetectionLouvain; pub(crate) struct CommunityDetectionLouvain;
impl AlgoImpl for CommunityDetectionLouvain { impl FixedRule for CommunityDetectionLouvain {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
@ -255,7 +255,7 @@ fn louvain_step(
mod tests { mod tests {
use itertools::Itertools; use itertools::Itertools;
use crate::algo::louvain::louvain; use crate::fixed_rule::algos::louvain::louvain;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
#[test] #[test]

@ -0,0 +1,37 @@
/*
* Copyright 2022, The Cozo Project Authors.
*
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#[cfg(feature = "graph-algo")]
pub(crate) mod all_pairs_shortest_path;
#[cfg(feature = "graph-algo")]
pub(crate) mod astar;
#[cfg(feature = "graph-algo")]
pub(crate) mod bfs;
#[cfg(feature = "graph-algo")]
pub(crate) mod degree_centrality;
#[cfg(feature = "graph-algo")]
pub(crate) mod dfs;
#[cfg(feature = "graph-algo")]
pub(crate) mod kruskal;
#[cfg(feature = "graph-algo")]
pub(crate) mod label_propagation;
#[cfg(feature = "graph-algo")]
pub(crate) mod louvain;
#[cfg(feature = "graph-algo")]
pub(crate) mod pagerank;
#[cfg(feature = "graph-algo")]
pub(crate) mod prim;
#[cfg(feature = "graph-algo")]
pub(crate) mod shortest_path_dijkstra;
pub(crate) mod strongly_connected_components;
#[cfg(feature = "graph-algo")]
pub(crate) mod top_sort;
#[cfg(feature = "graph-algo")]
pub(crate) mod triangles;
#[cfg(feature = "graph-algo")]
pub(crate) mod yen;

@ -17,7 +17,7 @@ use miette::Result;
use nalgebra::{Dynamic, OMatrix, U1}; use nalgebra::{Dynamic, OMatrix, U1};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -27,11 +27,11 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct PageRank; pub(crate) struct PageRank;
impl AlgoImpl for PageRank { impl FixedRule for PageRank {
#[allow(unused_variables)] #[allow(unused_variables)]
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -16,7 +16,7 @@ use priority_queue::PriorityQueue;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use thiserror::Error; use thiserror::Error;
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -26,10 +26,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct MinimumSpanningTreePrim; pub(crate) struct MinimumSpanningTreePrim;
impl AlgoImpl for MinimumSpanningTreePrim { impl FixedRule for MinimumSpanningTreePrim {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -19,7 +19,7 @@ use rayon::prelude::*;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -29,10 +29,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct ShortestPathDijkstra; pub(crate) struct ShortestPathDijkstra;
impl AlgoImpl for ShortestPathDijkstra { impl FixedRule for ShortestPathDijkstra {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -14,9 +14,9 @@ use itertools::Itertools;
use miette::Result; use miette::Result;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicFixedRuleApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple; use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -37,10 +37,10 @@ impl StronglyConnectedComponent {
} }
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
impl AlgoImpl for StronglyConnectedComponent { impl FixedRule for StronglyConnectedComponent {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -11,7 +11,7 @@ use std::collections::BTreeMap;
use miette::Result; use miette::Result;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -21,10 +21,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct TopSort; pub(crate) struct TopSort;
impl AlgoImpl for TopSort { impl FixedRule for TopSort {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -13,7 +13,7 @@ use miette::Result;
use rayon::prelude::*; use rayon::prelude::*;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -23,10 +23,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct ClusteringCoefficients; pub(crate) struct ClusteringCoefficients;
impl AlgoImpl for ClusteringCoefficients { impl FixedRule for ClusteringCoefficients {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -14,8 +14,8 @@ use miette::Result;
use rayon::prelude::*; use rayon::prelude::*;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::shortest_path_dijkstra::dijkstra; use crate::fixed_rule::algos::shortest_path_dijkstra::dijkstra;
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -25,10 +25,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct KShortestPathYen; pub(crate) struct KShortestPathYen;
impl AlgoImpl for KShortestPathYen { impl FixedRule for KShortestPathYen {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -14,104 +14,73 @@ use miette::{bail, ensure, Diagnostic, Result};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use thiserror::Error; use thiserror::Error;
#[cfg(feature = "graph-algo")]
use crate::algo::all_pairs_shortest_path::{BetweennessCentrality, ClosenessCentrality};
#[cfg(feature = "graph-algo")]
use crate::algo::astar::ShortestPathAStar;
#[cfg(feature = "graph-algo")]
use crate::algo::bfs::Bfs;
use crate::algo::constant::Constant;
use crate::algo::csv::CsvReader;
#[cfg(feature = "graph-algo")]
use crate::algo::degree_centrality::DegreeCentrality;
#[cfg(feature = "graph-algo")]
use crate::algo::dfs::Dfs;
use crate::algo::jlines::JsonReader;
#[cfg(feature = "graph-algo")]
use crate::algo::kruskal::MinimumSpanningForestKruskal;
#[cfg(feature = "graph-algo")]
use crate::algo::label_propagation::LabelPropagation;
#[cfg(feature = "graph-algo")]
use crate::algo::louvain::CommunityDetectionLouvain;
#[cfg(feature = "graph-algo")]
use crate::algo::pagerank::PageRank;
#[cfg(feature = "graph-algo")]
use crate::algo::prim::MinimumSpanningTreePrim;
#[cfg(feature = "graph-algo")]
use crate::algo::random_walk::RandomWalk;
use crate::algo::reorder_sort::ReorderSort;
#[cfg(feature = "graph-algo")]
use crate::algo::shortest_path_dijkstra::ShortestPathDijkstra;
#[cfg(feature = "graph-algo")]
use crate::algo::strongly_connected_components::StronglyConnectedComponent;
#[cfg(feature = "graph-algo")]
use crate::algo::top_sort::TopSort;
#[cfg(feature = "graph-algo")]
use crate::algo::triangles::ClusteringCoefficients;
#[cfg(feature = "graph-algo")]
use crate::algo::yen::KShortestPathYen;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{ use crate::data::program::{
AlgoOptionNotFoundError, MagicAlgoApply, MagicAlgoRuleArg, MagicSymbol, WrongAlgoOptionError, FixedRuleOptionNotFoundError, MagicFixedRuleApply, MagicFixedRuleRuleArg, MagicSymbol,
WrongFixedRuleOptionError,
}; };
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::TupleIter; use crate::data::tuple::TupleIter;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan;
use crate::runtime::db::Poison;
use crate::runtime::temp_store::{EpochStore, RegularTempStore};
use crate::runtime::transact::SessionTx;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod all_pairs_shortest_path; use crate::fixed_rule::algos::all_pairs_shortest_path::{
BetweennessCentrality, ClosenessCentrality,
};
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod astar; use crate::fixed_rule::algos::astar::ShortestPathAStar;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod bfs; use crate::fixed_rule::algos::bfs::Bfs;
pub(crate) mod constant;
pub(crate) mod csv;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod degree_centrality; use crate::fixed_rule::algos::degree_centrality::DegreeCentrality;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod dfs; use crate::fixed_rule::algos::dfs::Dfs;
pub(crate) mod jlines;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod kruskal; use crate::fixed_rule::algos::kruskal::MinimumSpanningForestKruskal;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod label_propagation; use crate::fixed_rule::algos::label_propagation::LabelPropagation;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod louvain; use crate::fixed_rule::algos::louvain::CommunityDetectionLouvain;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod pagerank; use crate::fixed_rule::algos::pagerank::PageRank;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod prim; use crate::fixed_rule::algos::prim::MinimumSpanningTreePrim;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod random_walk; use crate::fixed_rule::algos::shortest_path_dijkstra::ShortestPathDijkstra;
pub(crate) mod reorder_sort;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod shortest_path_dijkstra; use crate::fixed_rule::algos::strongly_connected_components::StronglyConnectedComponent;
pub(crate) mod strongly_connected_components;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod top_sort; use crate::fixed_rule::algos::top_sort::TopSort;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod triangles; use crate::fixed_rule::algos::triangles::ClusteringCoefficients;
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
pub(crate) mod yen; use crate::fixed_rule::algos::yen::KShortestPathYen;
use crate::fixed_rule::utilities::constant::Constant;
use crate::fixed_rule::utilities::csv::CsvReader;
use crate::fixed_rule::utilities::jlines::JsonReader;
use crate::fixed_rule::utilities::random_walk::RandomWalk;
use crate::fixed_rule::utilities::reorder_sort::ReorderSort;
use crate::parse::SourceSpan;
use crate::runtime::db::Poison;
use crate::runtime::temp_store::{EpochStore, RegularTempStore};
use crate::runtime::transact::SessionTx;
pub(crate) mod algos;
pub(crate) mod utilities;
pub struct AlgoPayload<'a, 'b> { pub struct FixedRulePayload<'a, 'b> {
pub(crate) manifest: &'a MagicAlgoApply, pub(crate) manifest: &'a MagicFixedRuleApply,
pub(crate) stores: &'a BTreeMap<MagicSymbol, EpochStore>, pub(crate) stores: &'a BTreeMap<MagicSymbol, EpochStore>,
pub(crate) tx: &'a SessionTx<'b>, pub(crate) tx: &'a SessionTx<'b>,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct AlgoInputRelation<'a, 'b> { pub struct FixedRuleInputRelation<'a, 'b> {
arg_manifest: &'a MagicAlgoRuleArg, arg_manifest: &'a MagicFixedRuleRuleArg,
stores: &'a BTreeMap<MagicSymbol, EpochStore>, stores: &'a BTreeMap<MagicSymbol, EpochStore>,
tx: &'a SessionTx<'b>, tx: &'a SessionTx<'b>,
} }
impl<'a, 'b> AlgoInputRelation<'a, 'b> { impl<'a, 'b> FixedRuleInputRelation<'a, 'b> {
pub fn arity(&self) -> Result<usize> { pub fn arity(&self) -> Result<usize> {
self.arg_manifest.arity(self.tx, self.stores) self.arg_manifest.arity(self.tx, self.stores)
} }
@ -133,10 +102,34 @@ impl<'a, 'b> AlgoInputRelation<'a, 'b> {
self.arg_manifest.get_binding_map(offset) self.arg_manifest.get_binding_map(offset)
} }
pub fn iter(&self) -> Result<TupleIter<'a>> { pub fn iter(&self) -> Result<TupleIter<'a>> {
self.arg_manifest.iter(self.tx, self.stores) Ok(match &self.arg_manifest {
MagicFixedRuleRuleArg::InMem { name, .. } => {
let store = self.stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?;
Box::new(store.all_iter().map(|t| Ok(t.into_tuple())))
}
MagicFixedRuleRuleArg::Stored { name, .. } => {
let relation = self.tx.get_relation(name, false)?;
Box::new(relation.scan_all(self.tx))
}
})
} }
pub fn prefix_iter(&self, prefix: &DataValue) -> Result<TupleIter<'_>> { pub fn prefix_iter(&self, prefix: &DataValue) -> Result<TupleIter<'_>> {
self.arg_manifest.prefix_iter(prefix, self.tx, self.stores) Ok(match self.arg_manifest {
MagicFixedRuleRuleArg::InMem { name, .. } => {
let store = self.stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?;
let t = vec![prefix.clone()];
Box::new(store.prefix_iter(&t).map(|t| Ok(t.into_tuple())))
}
MagicFixedRuleRuleArg::Stored { name, .. } => {
let relation = self.tx.get_relation(name, false)?;
let t = vec![prefix.clone()];
Box::new(relation.scan_prefix(self.tx, &t))
}
})
} }
pub fn span(&self) -> SourceSpan { pub fn span(&self) -> SourceSpan {
self.arg_manifest.span() self.arg_manifest.span()
@ -145,8 +138,38 @@ impl<'a, 'b> AlgoInputRelation<'a, 'b> {
&self, &self,
undirected: bool, undirected: bool,
) -> Result<(Vec<Vec<usize>>, Vec<DataValue>, BTreeMap<DataValue, usize>)> { ) -> Result<(Vec<Vec<usize>>, Vec<DataValue>, BTreeMap<DataValue, usize>)> {
self.arg_manifest let mut graph: Vec<Vec<usize>> = vec![];
.convert_edge_to_graph(undirected, self.tx, self.stores) let mut indices: Vec<DataValue> = vec![];
let mut inv_indices: BTreeMap<DataValue, usize> = Default::default();
for tuple in self.iter()? {
let mut tuple = tuple?.into_iter();
let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let from_idx = if let Some(idx) = inv_indices.get(&from) {
*idx
} else {
inv_indices.insert(from.clone(), graph.len());
indices.push(from.clone());
graph.push(vec![]);
graph.len() - 1
};
let to_idx = if let Some(idx) = inv_indices.get(&to) {
*idx
} else {
inv_indices.insert(to.clone(), graph.len());
indices.push(to.clone());
graph.push(vec![]);
graph.len() - 1
};
let from_target = graph.get_mut(from_idx).unwrap();
from_target.push(to_idx);
if undirected {
let to_target = graph.get_mut(to_idx).unwrap();
to_target.push(from_idx);
}
}
Ok((graph, indices, inv_indices))
} }
pub fn convert_edge_to_weighted_graph( pub fn convert_edge_to_weighted_graph(
&self, &self,
@ -158,26 +181,95 @@ impl<'a, 'b> AlgoInputRelation<'a, 'b> {
BTreeMap<DataValue, usize>, BTreeMap<DataValue, usize>,
bool, bool,
)> { )> {
self.arg_manifest.convert_edge_to_weighted_graph( let mut graph: Vec<Vec<(usize, f64)>> = vec![];
undirected, let mut indices: Vec<DataValue> = vec![];
allow_negative_edges, let mut inv_indices: BTreeMap<DataValue, usize> = Default::default();
self.tx, let mut has_neg_edge = false;
self.stores,
for tuple in self.iter()? {
let mut tuple = tuple?.into_iter();
let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let weight = match tuple.next() {
None => 1.0,
Some(d) => match d.get_float() {
Some(f) => {
ensure!(
f.is_finite(),
BadEdgeWeightError(
d,
self.arg_manifest
.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or_else(|| self.span())
) )
);
if f < 0. {
if !allow_negative_edges {
bail!(BadEdgeWeightError(
d,
self.arg_manifest
.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or_else(|| self.span())
));
}
has_neg_edge = true;
}
f
}
None => {
bail!(BadEdgeWeightError(
d,
self.arg_manifest
.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or_else(|| self.span())
))
}
},
};
let from_idx = if let Some(idx) = inv_indices.get(&from) {
*idx
} else {
inv_indices.insert(from.clone(), graph.len());
indices.push(from.clone());
graph.push(vec![]);
graph.len() - 1
};
let to_idx = if let Some(idx) = inv_indices.get(&to) {
*idx
} else {
inv_indices.insert(to.clone(), graph.len());
indices.push(to.clone());
graph.push(vec![]);
graph.len() - 1
};
let from_target = graph.get_mut(from_idx).unwrap();
from_target.push((to_idx, weight));
if undirected {
let to_target = graph.get_mut(to_idx).unwrap();
to_target.push((from_idx, weight));
}
}
Ok((graph, indices, inv_indices, has_neg_edge))
} }
} }
impl<'a, 'b> AlgoPayload<'a, 'b> { impl<'a, 'b> FixedRulePayload<'a, 'b> {
pub fn get_input(&self, idx: usize) -> Result<AlgoInputRelation<'a, 'b>> { pub fn get_input(&self, idx: usize) -> Result<FixedRuleInputRelation<'a, 'b>> {
let arg_manifest = self.manifest.relation(idx)?; let arg_manifest = self.manifest.relation(idx)?;
Ok(AlgoInputRelation { Ok(FixedRuleInputRelation {
arg_manifest, arg_manifest,
stores: self.stores, stores: self.stores,
tx: self.tx, tx: self.tx,
}) })
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.manifest.algo.name &self.manifest.fixed_handle.name
} }
pub fn span(&self) -> SourceSpan { pub fn span(&self) -> SourceSpan {
self.manifest.span self.manifest.span
@ -187,10 +279,10 @@ impl<'a, 'b> AlgoPayload<'a, 'b> {
Some(ex) => Ok(ex.clone()), Some(ex) => Ok(ex.clone()),
None => match default { None => match default {
Some(ex) => Ok(ex), Some(ex) => Ok(ex),
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.manifest.span, span: self.manifest.span,
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
}, },
@ -205,19 +297,19 @@ impl<'a, 'b> AlgoPayload<'a, 'b> {
match self.manifest.options.get(name) { match self.manifest.options.get(name) {
Some(ex) => match ex.clone().eval_to_const()? { Some(ex) => match ex.clone().eval_to_const()? {
DataValue::Str(s) => Ok(s), DataValue::Str(s) => Ok(s),
_ => Err(WrongAlgoOptionError { _ => Err(WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: ex.span(), span: ex.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a string is required".to_string(), help: "a string is required".to_string(),
} }
.into()), .into()),
}, },
None => match default { None => match default {
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.manifest.span, span: self.manifest.span,
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
Some(s) => Ok(SmartString::from(s)), Some(s) => Ok(SmartString::from(s)),
@ -232,36 +324,36 @@ impl<'a, 'b> AlgoPayload<'a, 'b> {
Some(i) => { Some(i) => {
ensure!( ensure!(
i > 0, i > 0,
WrongAlgoOptionError { WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: v.span(), span: v.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a positive integer is required".to_string(), help: "a positive integer is required".to_string(),
} }
); );
Ok(i as usize) Ok(i as usize)
} }
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.span(), span: self.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
}, },
_ => Err(WrongAlgoOptionError { _ => Err(WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: v.span(), span: v.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a positive integer is required".to_string(), help: "a positive integer is required".to_string(),
} }
.into()), .into()),
}, },
None => match default { None => match default {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.manifest.span, span: self.manifest.span,
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
}, },
@ -274,36 +366,36 @@ impl<'a, 'b> AlgoPayload<'a, 'b> {
Some(i) => { Some(i) => {
ensure!( ensure!(
i >= 0, i >= 0,
WrongAlgoOptionError { WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: v.span(), span: v.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a non-negative integer is required".to_string(), help: "a non-negative integer is required".to_string(),
} }
); );
Ok(i as usize) Ok(i as usize)
} }
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.manifest.span, span: self.manifest.span,
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
}, },
_ => Err(WrongAlgoOptionError { _ => Err(WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: v.span(), span: v.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a non-negative integer is required".to_string(), help: "a non-negative integer is required".to_string(),
} }
.into()), .into()),
}, },
None => match default { None => match default {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.manifest.span, span: self.manifest.span,
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
}, },
@ -316,29 +408,29 @@ impl<'a, 'b> AlgoPayload<'a, 'b> {
let f = n.get_float(); let f = n.get_float();
ensure!( ensure!(
(0. ..=1.).contains(&f), (0. ..=1.).contains(&f),
WrongAlgoOptionError { WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: v.span(), span: v.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a number between 0. and 1. is required".to_string(), help: "a number between 0. and 1. is required".to_string(),
} }
); );
Ok(f) Ok(f)
} }
_ => Err(WrongAlgoOptionError { _ => Err(WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: v.span(), span: v.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a number between 0. and 1. is required".to_string(), help: "a number between 0. and 1. is required".to_string(),
} }
.into()), .into()),
}, },
None => match default { None => match default {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.manifest.span, span: self.manifest.span,
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
}, },
@ -348,20 +440,20 @@ impl<'a, 'b> AlgoPayload<'a, 'b> {
match self.manifest.options.get(name) { match self.manifest.options.get(name) {
Some(v) => match v.clone().eval_to_const() { Some(v) => match v.clone().eval_to_const() {
Ok(DataValue::Bool(b)) => Ok(b), Ok(DataValue::Bool(b)) => Ok(b),
_ => Err(WrongAlgoOptionError { _ => Err(WrongFixedRuleOptionError {
name: name.to_string(), name: name.to_string(),
span: v.span(), span: v.span(),
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
help: "a boolean value is required".to_string(), help: "a boolean value is required".to_string(),
} }
.into()), .into()),
}, },
None => match default { None => match default {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(AlgoOptionNotFoundError { None => Err(FixedRuleOptionNotFoundError {
name: name.to_string(), name: name.to_string(),
span: self.manifest.span, span: self.manifest.span,
algo_name: self.manifest.algo.name.to_string(), rule_name: self.manifest.fixed_handle.name.to_string(),
} }
.into()), .into()),
}, },
@ -370,7 +462,7 @@ impl<'a, 'b> AlgoPayload<'a, 'b> {
} }
/// Trait for an implementation of an algorithm or a utility /// Trait for an implementation of an algorithm or a utility
pub trait AlgoImpl: Send + Sync { pub trait FixedRule: Send + Sync {
/// Called to initialize the options given. /// Called to initialize the options given.
/// Will always be called once, before anything else. /// Will always be called once, before anything else.
/// You can mutate the options if you need to. /// You can mutate the options if you need to.
@ -395,7 +487,7 @@ pub trait AlgoImpl: Send + Sync {
/// for user-initiated termination. /// for user-initiated termination.
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &'_ mut RegularTempStore, out: &'_ mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()>; ) -> Result<()>;
@ -411,141 +503,141 @@ pub(crate) struct CannotDetermineArity(
); );
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct AlgoHandle { pub(crate) struct FixedRuleHandle {
pub(crate) name: Symbol, pub(crate) name: Symbol,
} }
lazy_static! { lazy_static! {
pub(crate) static ref DEFAULT_ALGOS: Arc<BTreeMap<String, Arc<Box<dyn AlgoImpl>>>> = { pub(crate) static ref DEFAULT_FIXED_RULES: Arc<BTreeMap<String, Arc<Box<dyn FixedRule>>>> = {
Arc::new(BTreeMap::from([ Arc::new(BTreeMap::from([
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"ClusteringCoefficients".to_string(), "ClusteringCoefficients".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(ClusteringCoefficients)), Arc::<Box<dyn FixedRule>>::new(Box::new(ClusteringCoefficients)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"DegreeCentrality".to_string(), "DegreeCentrality".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(DegreeCentrality)), Arc::<Box<dyn FixedRule>>::new(Box::new(DegreeCentrality)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"ClosenessCentrality".to_string(), "ClosenessCentrality".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(ClosenessCentrality)), Arc::<Box<dyn FixedRule>>::new(Box::new(ClosenessCentrality)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"BetweennessCentrality".to_string(), "BetweennessCentrality".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(BetweennessCentrality)), Arc::<Box<dyn FixedRule>>::new(Box::new(BetweennessCentrality)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"DepthFirstSearch".to_string(), "DepthFirstSearch".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(Dfs)), Arc::<Box<dyn FixedRule>>::new(Box::new(Dfs)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"DFS".to_string(), "DFS".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(Dfs)), Arc::<Box<dyn FixedRule>>::new(Box::new(Dfs)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"BreadthFirstSearch".to_string(), "BreadthFirstSearch".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(Bfs)), Arc::<Box<dyn FixedRule>>::new(Box::new(Bfs)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"BFS".to_string(), "BFS".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(Bfs)), Arc::<Box<dyn FixedRule>>::new(Box::new(Bfs)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"ShortestPathDijkstra".to_string(), "ShortestPathDijkstra".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(ShortestPathDijkstra)), Arc::<Box<dyn FixedRule>>::new(Box::new(ShortestPathDijkstra)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"ShortestPathAStar".to_string(), "ShortestPathAStar".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(ShortestPathAStar)), Arc::<Box<dyn FixedRule>>::new(Box::new(ShortestPathAStar)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"KShortestPathYen".to_string(), "KShortestPathYen".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(KShortestPathYen)), Arc::<Box<dyn FixedRule>>::new(Box::new(KShortestPathYen)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"MinimumSpanningTreePrim".to_string(), "MinimumSpanningTreePrim".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(MinimumSpanningTreePrim)), Arc::<Box<dyn FixedRule>>::new(Box::new(MinimumSpanningTreePrim)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"MinimumSpanningForestKruskal".to_string(), "MinimumSpanningForestKruskal".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(MinimumSpanningForestKruskal)), Arc::<Box<dyn FixedRule>>::new(Box::new(MinimumSpanningForestKruskal)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"TopSort".to_string(), "TopSort".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(TopSort)), Arc::<Box<dyn FixedRule>>::new(Box::new(TopSort)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"ConnectedComponents".to_string(), "ConnectedComponents".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(StronglyConnectedComponent::new(false))), Arc::<Box<dyn FixedRule>>::new(Box::new(StronglyConnectedComponent::new(false))),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"StronglyConnectedComponents".to_string(), "StronglyConnectedComponents".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(StronglyConnectedComponent::new(true))), Arc::<Box<dyn FixedRule>>::new(Box::new(StronglyConnectedComponent::new(true))),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"SCC".to_string(), "SCC".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(StronglyConnectedComponent::new(true))), Arc::<Box<dyn FixedRule>>::new(Box::new(StronglyConnectedComponent::new(true))),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"PageRank".to_string(), "PageRank".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(PageRank)), Arc::<Box<dyn FixedRule>>::new(Box::new(PageRank)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"CommunityDetectionLouvain".to_string(), "CommunityDetectionLouvain".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(CommunityDetectionLouvain)), Arc::<Box<dyn FixedRule>>::new(Box::new(CommunityDetectionLouvain)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"LabelPropagation".to_string(), "LabelPropagation".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(LabelPropagation)), Arc::<Box<dyn FixedRule>>::new(Box::new(LabelPropagation)),
), ),
#[cfg(feature = "graph-algo")] #[cfg(feature = "graph-algo")]
( (
"RandomWalk".to_string(), "RandomWalk".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(RandomWalk)), Arc::<Box<dyn FixedRule>>::new(Box::new(RandomWalk)),
), ),
( (
"ReorderSort".to_string(), "ReorderSort".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(ReorderSort)), Arc::<Box<dyn FixedRule>>::new(Box::new(ReorderSort)),
), ),
( (
"JsonReader".to_string(), "JsonReader".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(JsonReader)), Arc::<Box<dyn FixedRule>>::new(Box::new(JsonReader)),
), ),
( (
"CsvReader".to_string(), "CsvReader".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(CsvReader)), Arc::<Box<dyn FixedRule>>::new(Box::new(CsvReader)),
), ),
( (
"Constant".to_string(), "Constant".to_string(),
Arc::<Box<dyn AlgoImpl>>::new(Box::new(Constant)), Arc::<Box<dyn FixedRule>>::new(Box::new(Constant)),
), ),
])) ]))
}; };
} }
impl AlgoHandle { impl FixedRuleHandle {
pub(crate) fn new(name: &str, span: SourceSpan) -> Self { pub(crate) fn new(name: &str, span: SourceSpan) -> Self {
AlgoHandle { FixedRuleHandle {
name: Symbol::new(name, span), name: Symbol::new(name, span),
} }
} }
@ -602,191 +694,27 @@ pub(crate) struct BadExprValueError(
); );
#[derive(Error, Diagnostic, Debug)] #[derive(Error, Diagnostic, Debug)]
#[error("The requested algorithm '{0}' is not found")] #[error("The requested fixed rule '{0}' is not found")]
#[diagnostic(code(parser::algo_not_found))] #[diagnostic(code(parser::fixed_rule_not_found))]
pub(crate) struct AlgoNotFoundError(pub(crate) String, #[label] pub(crate) SourceSpan); pub(crate) struct FixedRuleNotFoundError(pub(crate) String, #[label] pub(crate) SourceSpan);
impl MagicAlgoRuleArg {
#[allow(dead_code)]
pub(crate) fn convert_edge_to_weighted_graph<'a>(
&'a self,
undirected: bool,
allow_negative_edges: bool,
tx: &'a SessionTx<'_>,
stores: &'a BTreeMap<MagicSymbol, EpochStore>,
) -> Result<(
Vec<Vec<(usize, f64)>>,
Vec<DataValue>,
BTreeMap<DataValue, usize>,
bool,
)> {
let mut graph: Vec<Vec<(usize, f64)>> = vec![];
let mut indices: Vec<DataValue> = vec![];
let mut inv_indices: BTreeMap<DataValue, usize> = Default::default();
let mut has_neg_edge = false;
for tuple in self.iter(tx, stores)? { impl MagicFixedRuleRuleArg {
let mut tuple = tuple?.into_iter();
let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let weight = match tuple.next() {
None => 1.0,
Some(d) => match d.get_float() {
Some(f) => {
ensure!(
f.is_finite(),
BadEdgeWeightError(
d,
self.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or_else(|| self.span())
)
);
if f < 0. {
if !allow_negative_edges {
bail!(BadEdgeWeightError(
d,
self.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or_else(|| self.span())
));
}
has_neg_edge = true;
}
f
}
None => {
bail!(BadEdgeWeightError(
d,
self.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or_else(|| self.span())
))
}
},
};
let from_idx = if let Some(idx) = inv_indices.get(&from) {
*idx
} else {
inv_indices.insert(from.clone(), graph.len());
indices.push(from.clone());
graph.push(vec![]);
graph.len() - 1
};
let to_idx = if let Some(idx) = inv_indices.get(&to) {
*idx
} else {
inv_indices.insert(to.clone(), graph.len());
indices.push(to.clone());
graph.push(vec![]);
graph.len() - 1
};
let from_target = graph.get_mut(from_idx).unwrap();
from_target.push((to_idx, weight));
if undirected {
let to_target = graph.get_mut(to_idx).unwrap();
to_target.push((from_idx, weight));
}
}
Ok((graph, indices, inv_indices, has_neg_edge))
}
pub(crate) fn convert_edge_to_graph<'a>(
&'a self,
undirected: bool,
tx: &'a SessionTx<'_>,
stores: &'a BTreeMap<MagicSymbol, EpochStore>,
) -> Result<(Vec<Vec<usize>>, Vec<DataValue>, BTreeMap<DataValue, usize>)> {
let mut graph: Vec<Vec<usize>> = vec![];
let mut indices: Vec<DataValue> = vec![];
let mut inv_indices: BTreeMap<DataValue, usize> = Default::default();
for tuple in self.iter(tx, stores)? {
let mut tuple = tuple?.into_iter();
let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let from_idx = if let Some(idx) = inv_indices.get(&from) {
*idx
} else {
inv_indices.insert(from.clone(), graph.len());
indices.push(from.clone());
graph.push(vec![]);
graph.len() - 1
};
let to_idx = if let Some(idx) = inv_indices.get(&to) {
*idx
} else {
inv_indices.insert(to.clone(), graph.len());
indices.push(to.clone());
graph.push(vec![]);
graph.len() - 1
};
let from_target = graph.get_mut(from_idx).unwrap();
from_target.push(to_idx);
if undirected {
let to_target = graph.get_mut(to_idx).unwrap();
to_target.push(from_idx);
}
}
Ok((graph, indices, inv_indices))
}
pub(crate) fn prefix_iter<'a>(
&'a self,
prefix: &DataValue,
tx: &'a SessionTx<'_>,
stores: &'a BTreeMap<MagicSymbol, EpochStore>,
) -> Result<TupleIter<'a>> {
Ok(match self {
MagicAlgoRuleArg::InMem { name, .. } => {
let store = stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?;
let t = vec![prefix.clone()];
Box::new(store.prefix_iter(&t).map(|t| Ok(t.into_tuple())))
}
MagicAlgoRuleArg::Stored { name, .. } => {
let relation = tx.get_relation(name, false)?;
let t = vec![prefix.clone()];
Box::new(relation.scan_prefix(tx, &t))
}
})
}
pub(crate) fn arity( pub(crate) fn arity(
&self, &self,
tx: &SessionTx<'_>, tx: &SessionTx<'_>,
stores: &BTreeMap<MagicSymbol, EpochStore>, stores: &BTreeMap<MagicSymbol, EpochStore>,
) -> Result<usize> { ) -> Result<usize> {
Ok(match self { Ok(match self {
MagicAlgoRuleArg::InMem { name, .. } => { MagicFixedRuleRuleArg::InMem { name, .. } => {
let store = stores.get(name).ok_or_else(|| { let store = stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span) RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?; })?;
store.arity store.arity
} }
MagicAlgoRuleArg::Stored { name, .. } => { MagicFixedRuleRuleArg::Stored { name, .. } => {
let handle = tx.get_relation(name, false)?; let handle = tx.get_relation(name, false)?;
handle.arity() handle.arity()
} }
}) })
} }
pub(crate) fn iter<'a>(
&'a self,
tx: &'a SessionTx<'_>,
stores: &'a BTreeMap<MagicSymbol, EpochStore>,
) -> Result<TupleIter<'a>> {
Ok(match self {
MagicAlgoRuleArg::InMem { name, .. } => {
let store = stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?;
Box::new(store.all_iter().map(|t| Ok(t.into_tuple())))
}
MagicAlgoRuleArg::Stored { name, .. } => {
let relation = tx.get_relation(name, false)?;
Box::new(relation.scan_all(tx))
}
})
}
} }

@ -12,9 +12,9 @@ use miette::{bail, ensure, Diagnostic, Result};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use thiserror::Error; use thiserror::Error;
use crate::algo::{AlgoImpl, AlgoPayload}; use crate::fixed_rule::{FixedRule, FixedRulePayload};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::WrongAlgoOptionError; use crate::data::program::WrongFixedRuleOptionError;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
@ -23,10 +23,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct Constant; pub(crate) struct Constant;
impl AlgoImpl for Constant { impl FixedRule for Constant {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
_poison: Poison, _poison: Poison,
) -> Result<()> { ) -> Result<()> {
@ -76,18 +76,18 @@ impl AlgoImpl for Constant {
options: &mut BTreeMap<SmartString<LazyCompact>, Expr>, options: &mut BTreeMap<SmartString<LazyCompact>, Expr>,
span: SourceSpan, span: SourceSpan,
) -> Result<()> { ) -> Result<()> {
let data = options.get("data").ok_or_else(|| WrongAlgoOptionError { let data = options.get("data").ok_or_else(|| WrongFixedRuleOptionError {
name: "data".to_string(), name: "data".to_string(),
span: Default::default(), span: Default::default(),
algo_name: "Constant".to_string(), rule_name: "Constant".to_string(),
help: "a list of lists is required".to_string(), help: "a list of lists is required".to_string(),
})?; })?;
let data = match data.clone().eval_to_const()? { let data = match data.clone().eval_to_const()? {
DataValue::List(l) => l, DataValue::List(l) => l,
_ => bail!(WrongAlgoOptionError { _ => bail!(WrongFixedRuleOptionError {
name: "data".to_string(), name: "data".to_string(),
span: Default::default(), span: Default::default(),
algo_name: "Constant".to_string(), rule_name: "Constant".to_string(),
help: "a list of lists is required".to_string(), help: "a list of lists is required".to_string(),
}), }),
}; };

@ -13,11 +13,11 @@ use miette::{bail, ensure, IntoDiagnostic, Result};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
#[cfg(feature = "requests")] #[cfg(feature = "requests")]
use crate::algo::jlines::get_file_content_from_url; use crate::fixed_rule::utilities::jlines::get_file_content_from_url;
use crate::algo::{AlgoImpl, AlgoPayload, CannotDetermineArity}; use crate::fixed_rule::{FixedRule, FixedRulePayload, CannotDetermineArity};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::functions::{op_to_float, op_to_uuid}; use crate::data::functions::{op_to_float, op_to_uuid};
use crate::data::program::{AlgoOptionNotFoundError, WrongAlgoOptionError}; use crate::data::program::{FixedRuleOptionNotFoundError, WrongFixedRuleOptionError};
use crate::data::relation::{ColType, NullableColType}; use crate::data::relation::{ColType, NullableColType};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -27,10 +27,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct CsvReader; pub(crate) struct CsvReader;
impl AlgoImpl for CsvReader { impl FixedRule for CsvReader {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
_poison: Poison, _poison: Poison,
) -> Result<()> { ) -> Result<()> {
@ -38,10 +38,10 @@ impl AlgoImpl for CsvReader {
let delimiter = delimiter.as_bytes(); let delimiter = delimiter.as_bytes();
ensure!( ensure!(
delimiter.len() == 1, delimiter.len() == 1,
WrongAlgoOptionError { WrongFixedRuleOptionError {
name: "delimiter".to_string(), name: "delimiter".to_string(),
span: payload.span(), span: payload.span(),
algo_name: "CsvReader".to_string(), rule_name: "CsvReader".to_string(),
help: "'delimiter' must be a single-byte string".to_string() help: "'delimiter' must be a single-byte string".to_string()
} }
); );
@ -63,10 +63,10 @@ impl AlgoImpl for CsvReader {
let mut types = vec![]; let mut types = vec![];
for type_str in types_opts.get_list().unwrap() { for type_str in types_opts.get_list().unwrap() {
let type_str = type_str.get_string().unwrap(); let type_str = type_str.get_string().unwrap();
let typ = parse_type(type_str).map_err(|e| WrongAlgoOptionError { let typ = parse_type(type_str).map_err(|e| WrongFixedRuleOptionError {
name: "types".to_string(), name: "types".to_string(),
span: payload.span(), span: payload.span(),
algo_name: "CsvReader".to_string(), rule_name: "CsvReader".to_string(),
help: e.to_string(), help: e.to_string(),
})?; })?;
types.push(typ); types.push(typ);
@ -197,10 +197,10 @@ impl AlgoImpl for CsvReader {
}; };
let columns = options let columns = options
.get("types") .get("types")
.ok_or_else(|| AlgoOptionNotFoundError { .ok_or_else(|| FixedRuleOptionNotFoundError {
name: "types".to_string(), name: "types".to_string(),
span, span,
algo_name: "CsvReader".to_string(), rule_name: "CsvReader".to_string(),
})?; })?;
let columns = columns.clone().eval_to_const()?; let columns = columns.clone().eval_to_const()?;
if let Some(l) = columns.get_list() { if let Some(l) = columns.get_list() {

@ -20,7 +20,7 @@ use minreq::Response;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use thiserror::Error; use thiserror::Error;
use crate::algo::{AlgoImpl, AlgoPayload, CannotDetermineArity}; use crate::fixed_rule::{FixedRule, FixedRulePayload, CannotDetermineArity};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::json::JsonValue; use crate::data::json::JsonValue;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
@ -31,10 +31,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct JsonReader; pub(crate) struct JsonReader;
impl AlgoImpl for JsonReader { impl FixedRule for JsonReader {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
_poison: Poison, _poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -0,0 +1,13 @@
/*
* Copyright 2022, The Cozo Project Authors.
*
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
pub(crate) mod constant;
pub(crate) mod csv;
pub(crate) mod jlines;
pub(crate) mod random_walk;
pub(crate) mod reorder_sort;

@ -14,7 +14,7 @@ use rand::distributions::WeightedIndex;
use rand::prelude::*; use rand::prelude::*;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload, BadExprValueError, NodeNotFoundError}; use crate::fixed_rule::{FixedRule, FixedRulePayload, BadExprValueError, NodeNotFoundError};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
@ -24,10 +24,10 @@ use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct RandomWalk; pub(crate) struct RandomWalk;
impl AlgoImpl for RandomWalk { impl FixedRule for RandomWalk {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {

@ -12,22 +12,22 @@ use itertools::Itertools;
use miette::{bail, Result}; use miette::{bail, Result};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::algo::{AlgoImpl, AlgoPayload, CannotDetermineArity};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::functions::OP_LIST; use crate::data::functions::OP_LIST;
use crate::data::program::WrongAlgoOptionError; use crate::data::program::WrongFixedRuleOptionError;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::fixed_rule::{FixedRule, FixedRulePayload, CannotDetermineArity};
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
use crate::runtime::temp_store::RegularTempStore; use crate::runtime::temp_store::RegularTempStore;
pub(crate) struct ReorderSort; pub(crate) struct ReorderSort;
impl AlgoImpl for ReorderSort { impl FixedRule for ReorderSort {
fn run( fn run(
&self, &self,
payload: AlgoPayload<'_, '_>, payload: FixedRulePayload<'_, '_>,
out: &mut RegularTempStore, out: &mut RegularTempStore,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
@ -46,10 +46,10 @@ impl AlgoImpl for ReorderSort {
.collect_vec(), .collect_vec(),
Expr::Apply { op, args, .. } if *op == OP_LIST => args.to_vec(), Expr::Apply { op, args, .. } if *op == OP_LIST => args.to_vec(),
_ => { _ => {
bail!(WrongAlgoOptionError { bail!(WrongFixedRuleOptionError {
name: "out".to_string(), name: "out".to_string(),
span: payload.span(), span: payload.span(),
algo_name: payload.name().to_string(), rule_name: payload.name().to_string(),
help: "This option must evaluate to a list".to_string() help: "This option must evaluate to a list".to_string()
}) })
} }

@ -62,17 +62,17 @@ pub use storage::sqlite::{new_cozo_sqlite, SqliteStorage};
pub use storage::tikv::{new_cozo_tikv, TiKvStorage}; pub use storage::tikv::{new_cozo_tikv, TiKvStorage};
pub use storage::{Storage, StoreTx}; pub use storage::{Storage, StoreTx};
pub use runtime::temp_store::RegularTempStore; pub use runtime::temp_store::RegularTempStore;
pub use algo::AlgoImpl; pub use fixed_rule::FixedRule;
use crate::data::json::JsonValue; use crate::data::json::JsonValue;
pub(crate) mod algo;
pub(crate) mod data; pub(crate) mod data;
pub(crate) mod parse; pub(crate) mod parse;
pub(crate) mod query; pub(crate) mod query;
pub(crate) mod runtime; pub(crate) mod runtime;
pub(crate) mod storage; pub(crate) mod storage;
pub(crate) mod utils; pub(crate) mod utils;
pub(crate) mod fixed_rule;
#[derive(Clone)] #[derive(Clone)]
/// A dispatcher for concrete storage implementations, wrapping [Db]. This is done so that /// A dispatcher for concrete storage implementations, wrapping [Db]. This is done so that

@ -21,7 +21,7 @@ use crate::data::value::DataValue;
use crate::parse::query::parse_query; use crate::parse::query::parse_query;
use crate::parse::schema::parse_nullable_type; use crate::parse::schema::parse_nullable_type;
use crate::parse::sys::{parse_sys, SysOp}; use crate::parse::sys::{parse_sys, SysOp};
use crate::AlgoImpl; use crate::FixedRule;
pub(crate) mod expr; pub(crate) mod expr;
pub(crate) mod query; pub(crate) mod query;
@ -106,7 +106,7 @@ pub(crate) fn parse_type(src: &str) -> Result<NullableColType> {
pub(crate) fn parse_script( pub(crate) fn parse_script(
src: &str, src: &str,
param_pool: &BTreeMap<String, DataValue>, param_pool: &BTreeMap<String, DataValue>,
algorithms: &BTreeMap<String, Arc<Box<dyn AlgoImpl>>>, algorithms: &BTreeMap<String, Arc<Box<dyn FixedRule>>>,
) -> Result<CozoScript> { ) -> Result<CozoScript> {
let parsed = CozoScriptParser::parse(Rule::script, src) let parsed = CozoScriptParser::parse(Rule::script, src)
.map_err(|err| { .map_err(|err| {

@ -19,23 +19,23 @@ use miette::{bail, ensure, Diagnostic, LabeledSpan, Report, Result};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use thiserror::Error; use thiserror::Error;
use crate::algo::constant::Constant;
use crate::algo::{AlgoHandle, AlgoNotFoundError};
use crate::data::aggr::{parse_aggr, Aggregation}; use crate::data::aggr::{parse_aggr, Aggregation};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{ use crate::data::program::{
AlgoApply, AlgoRuleArg, InputAtom, InputInlineRule, InputInlineRulesOrAlgo, FixedRuleApply, FixedRuleArg, InputAtom, InputInlineRule, InputInlineRulesOrFixed,
InputNamedFieldRelationApplyAtom, InputProgram, InputRelationApplyAtom, InputRuleApplyAtom, InputNamedFieldRelationApplyAtom, InputProgram, InputRelationApplyAtom, InputRuleApplyAtom,
QueryAssertion, QueryOutOptions, RelationOp, SortDir, Unification, QueryAssertion, QueryOutOptions, RelationOp, SortDir, Unification,
}; };
use crate::data::relation::{ColType, ColumnDef, NullableColType, StoredRelationMetadata}; use crate::data::relation::{ColType, ColumnDef, NullableColType, StoredRelationMetadata};
use crate::data::symb::{Symbol, PROG_ENTRY}; use crate::data::symb::{Symbol, PROG_ENTRY};
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::fixed_rule::utilities::constant::Constant;
use crate::fixed_rule::{FixedRuleHandle, FixedRuleNotFoundError};
use crate::parse::expr::build_expr; use crate::parse::expr::build_expr;
use crate::parse::schema::parse_schema; use crate::parse::schema::parse_schema;
use crate::parse::{ExtractSpan, Pair, Pairs, Rule, SourceSpan}; use crate::parse::{ExtractSpan, Pair, Pairs, Rule, SourceSpan};
use crate::runtime::relation::InputRelationHandle; use crate::runtime::relation::InputRelationHandle;
use crate::AlgoImpl; use crate::FixedRule;
#[derive(Error, Diagnostic, Debug)] #[derive(Error, Diagnostic, Debug)]
#[error("Query option {0} is not constant")] #[error("Query option {0} is not constant")]
@ -94,9 +94,9 @@ fn merge_spans(symbs: &[Symbol]) -> SourceSpan {
pub(crate) fn parse_query( pub(crate) fn parse_query(
src: Pairs<'_>, src: Pairs<'_>,
param_pool: &BTreeMap<String, DataValue>, param_pool: &BTreeMap<String, DataValue>,
algorithms: &BTreeMap<String, Arc<Box<dyn AlgoImpl>>>, fixedrithms: &BTreeMap<String, Arc<Box<dyn FixedRule>>>,
) -> Result<InputProgram> { ) -> Result<InputProgram> {
let mut progs: BTreeMap<Symbol, InputInlineRulesOrAlgo> = Default::default(); let mut progs: BTreeMap<Symbol, InputInlineRulesOrFixed> = Default::default();
let mut out_opts: QueryOutOptions = Default::default(); let mut out_opts: QueryOutOptions = Default::default();
let mut stored_relation = None; let mut stored_relation = None;
@ -107,12 +107,12 @@ pub(crate) fn parse_query(
match progs.entry(name) { match progs.entry(name) {
Entry::Vacant(e) => { Entry::Vacant(e) => {
e.insert(InputInlineRulesOrAlgo::Rules { rules: vec![rule] }); e.insert(InputInlineRulesOrFixed::Rules { rules: vec![rule] });
} }
Entry::Occupied(mut e) => { Entry::Occupied(mut e) => {
let key = e.key().to_string(); let key = e.key().to_string();
match e.get_mut() { match e.get_mut() {
InputInlineRulesOrAlgo::Rules { rules: rs } => { InputInlineRulesOrFixed::Rules { rules: rs } => {
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
#[error("Rule {0} has multiple definitions with conflicting heads")] #[error("Rule {0} has multiple definitions with conflicting heads")]
#[diagnostic(code(parser::head_aggr_mismatch))] #[diagnostic(code(parser::head_aggr_mismatch))]
@ -134,32 +134,32 @@ pub(crate) fn parse_query(
rs.push(rule); rs.push(rule);
} }
InputInlineRulesOrAlgo::Algo { algo } => { InputInlineRulesOrFixed::Fixed { fixed } => {
let algo_span = algo.span; let fixed_span = fixed.span;
bail!(MultipleRuleDefinitionError( bail!(MultipleRuleDefinitionError(
e.key().name.to_string(), e.key().name.to_string(),
vec![rule.span, algo_span] vec![rule.span, fixed_span]
)) ))
} }
} }
} }
} }
} }
Rule::algo_rule => { Rule::fixed_rule => {
let rule_span = pair.extract_span(); let rule_span = pair.extract_span();
let (name, apply) = parse_algo_rule(pair, param_pool, algorithms)?; let (name, apply) = parse_fixed_rule(pair, param_pool, fixedrithms)?;
match progs.entry(name) { match progs.entry(name) {
Entry::Vacant(e) => { Entry::Vacant(e) => {
e.insert(InputInlineRulesOrAlgo::Algo { algo: apply }); e.insert(InputInlineRulesOrFixed::Fixed { fixed: apply });
} }
Entry::Occupied(e) => { Entry::Occupied(e) => {
let found_name = e.key().name.to_string(); let found_name = e.key().name.to_string();
let mut found_span = match e.get() { let mut found_span = match e.get() {
InputInlineRulesOrAlgo::Rules { rules } => { InputInlineRulesOrFixed::Rules { rules } => {
rules.iter().map(|r| r.span).collect_vec() rules.iter().map(|r| r.span).collect_vec()
} }
InputInlineRulesOrAlgo::Algo { algo } => vec![algo.span], InputInlineRulesOrFixed::Fixed { fixed } => vec![fixed.span],
}; };
found_span.push(rule_span); found_span.push(rule_span);
bail!(MultipleRuleDefinitionError(found_name, found_span)); bail!(MultipleRuleDefinitionError(found_name, found_span));
@ -173,11 +173,11 @@ pub(crate) fn parse_query(
if let Some(found) = progs.get(&name) { if let Some(found) = progs.get(&name) {
let mut found_span = match found { let mut found_span = match found {
InputInlineRulesOrAlgo::Rules { rules } => { InputInlineRulesOrFixed::Rules { rules } => {
rules.iter().map(|r| r.span).collect_vec() rules.iter().map(|r| r.span).collect_vec()
} }
InputInlineRulesOrAlgo::Algo { algo } => { InputInlineRulesOrFixed::Fixed { fixed } => {
vec![algo.span] vec![fixed.span]
} }
}; };
found_span.push(span); found_span.push(span);
@ -199,12 +199,12 @@ pub(crate) fn parse_query(
let data = build_expr(src.next().unwrap(), param_pool)?; let data = build_expr(src.next().unwrap(), param_pool)?;
let mut options = BTreeMap::new(); let mut options = BTreeMap::new();
options.insert(SmartString::from("data"), data); options.insert(SmartString::from("data"), data);
let handle = AlgoHandle { let handle = FixedRuleHandle {
name: Symbol::new("Constant", span), name: Symbol::new("Constant", span),
}; };
let algo_impl = Box::new(Constant); let fixed_impl = Box::new(Constant);
algo_impl.init_options(&mut options, span)?; fixed_impl.init_options(&mut options, span)?;
let arity = algo_impl.arity(&options, &head, span)?; let arity = fixed_impl.arity(&options, &head, span)?;
ensure!(arity != 0, EmptyRowForConstRule(span)); ensure!(arity != 0, EmptyRowForConstRule(span));
ensure!( ensure!(
@ -213,15 +213,15 @@ pub(crate) fn parse_query(
); );
progs.insert( progs.insert(
name, name,
InputInlineRulesOrAlgo::Algo { InputInlineRulesOrFixed::Fixed {
algo: AlgoApply { fixed: FixedRuleApply {
algo: handle, fixed_handle: handle,
rule_args: vec![], rule_args: vec![],
options: Rc::new(options), options: Rc::new(options),
head, head,
arity, arity,
span, span,
algo_impl: Arc::new(algo_impl), fixed_impl: Arc::new(fixed_impl),
}, },
}, },
); );
@ -652,55 +652,55 @@ fn parse_rule_head_arg(
}) })
} }
fn parse_algo_rule( fn parse_fixed_rule(
src: Pair<'_>, src: Pair<'_>,
param_pool: &BTreeMap<String, DataValue>, param_pool: &BTreeMap<String, DataValue>,
algorithms: &BTreeMap<String, Arc<Box<dyn AlgoImpl>>>, fixedrithms: &BTreeMap<String, Arc<Box<dyn FixedRule>>>,
) -> Result<(Symbol, AlgoApply)> { ) -> Result<(Symbol, FixedRuleApply)> {
let mut src = src.into_inner(); let mut src = src.into_inner();
let (out_symbol, head, aggr) = parse_rule_head(src.next().unwrap(), param_pool)?; let (out_symbol, head, aggr) = parse_rule_head(src.next().unwrap(), param_pool)?;
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
#[error("Algorithm rule cannot be combined with aggregation")] #[error("fixedrithm rule cannot be combined with aggregation")]
#[diagnostic(code(parser::algo_aggr_conflict))] #[diagnostic(code(parser::fixed_aggr_conflict))]
struct AggrInAlgoError(#[label] SourceSpan); struct AggrInfixedError(#[label] SourceSpan);
for (a, v) in aggr.iter().zip(head.iter()) { for (a, v) in aggr.iter().zip(head.iter()) {
ensure!(a.is_none(), AggrInAlgoError(v.span)) ensure!(a.is_none(), AggrInfixedError(v.span))
} }
let name_pair = src.next().unwrap(); let name_pair = src.next().unwrap();
let algo_name = &name_pair.as_str(); let fixed_name = &name_pair.as_str();
let mut rule_args: Vec<AlgoRuleArg> = vec![]; let mut rule_args: Vec<FixedRuleArg> = vec![];
let mut options: BTreeMap<SmartString<LazyCompact>, Expr> = Default::default(); let mut options: BTreeMap<SmartString<LazyCompact>, Expr> = Default::default();
let args_list = src.next().unwrap(); let args_list = src.next().unwrap();
let args_list_span = args_list.extract_span(); let args_list_span = args_list.extract_span();
for nxt in args_list.into_inner() { for nxt in args_list.into_inner() {
match nxt.as_rule() { match nxt.as_rule() {
Rule::algo_rel => { Rule::fixed_rel => {
let inner = nxt.into_inner().next().unwrap(); let inner = nxt.into_inner().next().unwrap();
let span = inner.extract_span(); let span = inner.extract_span();
match inner.as_rule() { match inner.as_rule() {
Rule::algo_rule_rel => { Rule::fixed_rule_rel => {
let mut els = inner.into_inner(); let mut els = inner.into_inner();
let name = els.next().unwrap(); let name = els.next().unwrap();
let bindings = els let bindings = els
.map(|v| Symbol::new(v.as_str(), v.extract_span())) .map(|v| Symbol::new(v.as_str(), v.extract_span()))
.collect_vec(); .collect_vec();
rule_args.push(AlgoRuleArg::InMem { rule_args.push(FixedRuleArg::InMem {
name: Symbol::new(name.as_str(), name.extract_span()), name: Symbol::new(name.as_str(), name.extract_span()),
bindings, bindings,
span, span,
}) })
} }
Rule::algo_relation_rel => { Rule::fixed_relation_rel => {
let mut els = inner.into_inner(); let mut els = inner.into_inner();
let name = els.next().unwrap(); let name = els.next().unwrap();
let bindings = els let bindings = els
.map(|v| Symbol::new(v.as_str(), v.extract_span())) .map(|v| Symbol::new(v.as_str(), v.extract_span()))
.collect_vec(); .collect_vec();
rule_args.push(AlgoRuleArg::Stored { rule_args.push(FixedRuleArg::Stored {
name: Symbol::new( name: Symbol::new(
name.as_str().strip_prefix('*').unwrap(), name.as_str().strip_prefix('*').unwrap(),
name.extract_span(), name.extract_span(),
@ -709,7 +709,7 @@ fn parse_algo_rule(
span, span,
}) })
} }
Rule::algo_named_relation_rel => { Rule::fixed_named_relation_rel => {
let mut els = inner.into_inner(); let mut els = inner.into_inner();
let name = els.next().unwrap(); let name = els.next().unwrap();
let bindings = els let bindings = els
@ -725,7 +725,7 @@ fn parse_algo_rule(
}) })
.collect(); .collect();
rule_args.push(AlgoRuleArg::NamedStored { rule_args.push(FixedRuleArg::NamedStored {
name: Symbol::new( name: Symbol::new(
name.as_str().strip_prefix(':').unwrap(), name.as_str().strip_prefix(':').unwrap(),
name.extract_span(), name.extract_span(),
@ -737,7 +737,7 @@ fn parse_algo_rule(
_ => unreachable!(), _ => unreachable!(),
} }
} }
Rule::algo_opt_pair => { Rule::fixed_opt_pair => {
let mut inner = nxt.into_inner(); let mut inner = nxt.into_inner();
let name = inner.next().unwrap().as_str(); let name = inner.next().unwrap().as_str();
let val = inner.next().unwrap(); let val = inner.next().unwrap();
@ -748,12 +748,13 @@ fn parse_algo_rule(
} }
} }
let algo = AlgoHandle::new(algo_name, name_pair.extract_span()); let fixed = FixedRuleHandle::new(fixed_name, name_pair.extract_span());
let algo_impl = algorithms.get(&algo.name as &str) let fixed_impl = fixedrithms
.ok_or_else(|| AlgoNotFoundError(algo.name.to_string(), name_pair.extract_span()))?; .get(&fixed.name as &str)
algo_impl.init_options(&mut options, args_list_span)?; .ok_or_else(|| FixedRuleNotFoundError(fixed.name.to_string(), name_pair.extract_span()))?;
let arity = algo_impl.arity(&options, &head, name_pair.extract_span())?; fixed_impl.init_options(&mut options, args_list_span)?;
let arity = fixed_impl.arity(&options, &head, name_pair.extract_span())?;
ensure!( ensure!(
head.is_empty() || arity == head.len(), head.is_empty() || arity == head.len(),
@ -762,14 +763,14 @@ fn parse_algo_rule(
Ok(( Ok((
out_symbol, out_symbol,
AlgoApply { FixedRuleApply {
algo, fixed_handle: fixed,
rule_args, rule_args,
options: Rc::new(options), options: Rc::new(options),
head, head,
arity, arity,
span: args_list_span, span: args_list_span,
algo_impl: algo_impl.clone(), fixed_impl: fixed_impl.clone(),
}, },
)) ))
} }
@ -797,9 +798,9 @@ fn make_empty_const_rule(prog: &mut InputProgram, bindings: &[Symbol]) {
); );
prog.prog.insert( prog.prog.insert(
entry_symbol, entry_symbol,
InputInlineRulesOrAlgo::Algo { InputInlineRulesOrFixed::Fixed {
algo: AlgoApply { fixed: FixedRuleApply {
algo: AlgoHandle { fixed_handle: FixedRuleHandle {
name: Symbol::new("Constant", Default::default()), name: Symbol::new("Constant", Default::default()),
}, },
rule_args: vec![], rule_args: vec![],
@ -807,7 +808,7 @@ fn make_empty_const_rule(prog: &mut InputProgram, bindings: &[Symbol]) {
head: bindings.to_vec(), head: bindings.to_vec(),
arity: bindings.len(), arity: bindings.len(),
span: Default::default(), span: Default::default(),
algo_impl: Arc::new(Box::new(Constant)), fixed_impl: Arc::new(Box::new(Constant)),
}, },
}, },
); );

@ -19,7 +19,7 @@ use crate::data::value::DataValue;
use crate::parse::query::parse_query; use crate::parse::query::parse_query;
use crate::parse::{ExtractSpan, Pairs, Rule, SourceSpan}; use crate::parse::{ExtractSpan, Pairs, Rule, SourceSpan};
use crate::runtime::relation::AccessLevel; use crate::runtime::relation::AccessLevel;
use crate::AlgoImpl; use crate::FixedRule;
pub(crate) enum SysOp { pub(crate) enum SysOp {
Compact, Compact,
@ -43,7 +43,7 @@ struct ProcessIdError(String, #[label] SourceSpan);
pub(crate) fn parse_sys( pub(crate) fn parse_sys(
mut src: Pairs<'_>, mut src: Pairs<'_>,
param_pool: &BTreeMap<String, DataValue>, param_pool: &BTreeMap<String, DataValue>,
algorithms: &BTreeMap<String, Arc<Box<dyn AlgoImpl>>>, algorithms: &BTreeMap<String, Arc<Box<dyn FixedRule>>>,
) -> Result<SysOp> { ) -> Result<SysOp> {
let inner = src.next().unwrap(); let inner = src.next().unwrap();
Ok(match inner.as_rule() { Ok(match inner.as_rule() {

@ -15,7 +15,7 @@ use thiserror::Error;
use crate::data::aggr::Aggregation; use crate::data::aggr::Aggregation;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{ use crate::data::program::{
MagicAlgoApply, MagicAtom, MagicInlineRule, MagicRulesOrAlgo, MagicSymbol, MagicFixedRuleApply, MagicAtom, MagicInlineRule, MagicRulesOrFixed, MagicSymbol,
StratifiedMagicProgram, StratifiedMagicProgram,
}; };
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
@ -30,7 +30,7 @@ pub(crate) type CompiledProgram = BTreeMap<MagicSymbol, CompiledRuleSet>;
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum CompiledRuleSet { pub(crate) enum CompiledRuleSet {
Rules(Vec<CompiledRule>), Rules(Vec<CompiledRule>),
Algo(MagicAlgoApply), Fixed(MagicFixedRuleApply),
} }
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
@ -44,7 +44,7 @@ impl CompiledRuleSet {
pub(crate) fn arity(&self) -> usize { pub(crate) fn arity(&self) -> usize {
match self { match self {
CompiledRuleSet::Rules(rs) => rs[0].aggr.len(), CompiledRuleSet::Rules(rs) => rs[0].aggr.len(),
CompiledRuleSet::Algo(algo) => algo.arity, CompiledRuleSet::Fixed(fixed) => fixed.arity,
} }
} }
pub(crate) fn aggr_kind(&self) -> AggrKind { pub(crate) fn aggr_kind(&self) -> AggrKind {
@ -72,7 +72,7 @@ impl CompiledRuleSet {
(true, false) => AggrKind::Meet, (true, false) => AggrKind::Meet,
} }
} }
CompiledRuleSet::Algo(_) => AggrKind::None, CompiledRuleSet::Fixed(_) => AggrKind::None,
} }
} }
} }
@ -118,7 +118,7 @@ impl<'a> SessionTx<'a> {
.into_iter() .into_iter()
.map(|(k, body)| -> Result<(MagicSymbol, CompiledRuleSet)> { .map(|(k, body)| -> Result<(MagicSymbol, CompiledRuleSet)> {
match body { match body {
MagicRulesOrAlgo::Rules { rules: body } => { MagicRulesOrFixed::Rules { rules: body } => {
let mut collected = Vec::with_capacity(body.len()); let mut collected = Vec::with_capacity(body.len());
for rule in body.iter() { for rule in body.iter() {
let header = &rule.head; let header = &rule.head;
@ -139,8 +139,8 @@ impl<'a> SessionTx<'a> {
Ok((k, CompiledRuleSet::Rules(collected))) Ok((k, CompiledRuleSet::Rules(collected)))
} }
MagicRulesOrAlgo::Algo { algo: algo_apply } => { MagicRulesOrFixed::Fixed { fixed } => {
Ok((k, CompiledRuleSet::Algo(algo_apply))) Ok((k, CompiledRuleSet::Fixed(fixed)))
} }
} }
}) })

@ -13,7 +13,7 @@ use itertools::Itertools;
use log::{debug, trace}; use log::{debug, trace};
use miette::Result; use miette::Result;
use crate::algo::AlgoPayload; use crate::fixed_rule::FixedRulePayload;
use crate::data::aggr::Aggregation; use crate::data::aggr::Aggregation;
use crate::data::program::{MagicSymbol, NoEntryError}; use crate::data::program::{MagicSymbol, NoEntryError};
use crate::data::symb::{Symbol, PROG_ENTRY}; use crate::data::symb::{Symbol, PROG_ENTRY};
@ -152,15 +152,15 @@ impl<'a> SessionTx<'a> {
new.wrap() new.wrap()
} }
}, },
CompiledRuleSet::Algo(algo_apply) => { CompiledRuleSet::Fixed(fixed) => {
let algo_impl = algo_apply.algo_impl.as_ref(); let fixed_impl = fixed.fixed_impl.as_ref();
let mut out = RegularTempStore::default(); let mut out = RegularTempStore::default();
let payload = AlgoPayload { let payload = FixedRulePayload {
manifest: algo_apply, manifest: fixed,
stores, stores,
tx: self, tx: self,
}; };
algo_impl.run(payload, &mut out, poison.clone())?; fixed_impl.run(payload, &mut out, poison.clone())?;
out.wrap() out.wrap()
} }
}; };
@ -199,7 +199,7 @@ impl<'a> SessionTx<'a> {
} }
} }
CompiledRuleSet::Algo(_) => { CompiledRuleSet::Fixed(_) => {
// no need to do anything, algos are only calculated once // no need to do anything, algos are only calculated once
RegularTempStore::default().wrap() RegularTempStore::default().wrap()
} }

@ -12,7 +12,7 @@ use std::fmt::Debug;
use miette::Result; use miette::Result;
use itertools::Itertools; use itertools::Itertools;
use crate::algo::strongly_connected_components::TarjanScc; use crate::fixed_rule::algos::strongly_connected_components::TarjanScc;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
pub(crate) type Graph<T> = BTreeMap<T, Vec<T>>; pub(crate) type Graph<T> = BTreeMap<T, Vec<T>>;

@ -15,9 +15,9 @@ use smallvec::SmallVec;
use smartstring::SmartString; use smartstring::SmartString;
use crate::data::program::{ use crate::data::program::{
AlgoRuleArg, MagicAlgoApply, MagicAlgoRuleArg, MagicAtom, MagicInlineRule, MagicProgram, FixedRuleArg, MagicFixedRuleApply, MagicFixedRuleRuleArg, MagicAtom, MagicInlineRule, MagicProgram,
MagicRelationApplyAtom, MagicRuleApplyAtom, MagicRulesOrAlgo, MagicSymbol, MagicRelationApplyAtom, MagicRuleApplyAtom, MagicRulesOrFixed, MagicSymbol,
NormalFormAlgoOrRules, NormalFormAtom, NormalFormInlineRule, NormalFormProgram, NormalFormRulesOrFixed, NormalFormAtom, NormalFormInlineRule, NormalFormProgram,
StratifiedMagicProgram, StratifiedNormalFormProgram, StratifiedMagicProgram, StratifiedNormalFormProgram,
}; };
use crate::data::symb::{Symbol, PROG_ENTRY}; use crate::data::symb::{Symbol, PROG_ENTRY};
@ -29,7 +29,7 @@ impl NormalFormProgram {
pub(crate) fn exempt_aggr_rules_for_magic_sets(&self, exempt_rules: &mut BTreeSet<Symbol>) { pub(crate) fn exempt_aggr_rules_for_magic_sets(&self, exempt_rules: &mut BTreeSet<Symbol>) {
for (name, rule_set) in self.prog.iter() { for (name, rule_set) in self.prog.iter() {
match rule_set { match rule_set {
NormalFormAlgoOrRules::Rules { rules: rule_set } => { NormalFormRulesOrFixed::Rules { rules: rule_set } => {
'outer: for rule in rule_set.iter() { 'outer: for rule in rule_set.iter() {
for aggr in rule.aggr.iter() { for aggr in rule.aggr.iter() {
if aggr.is_some() { if aggr.is_some() {
@ -39,7 +39,7 @@ impl NormalFormProgram {
} }
} }
} }
NormalFormAlgoOrRules::Algo { algo: _ } => {} NormalFormRulesOrFixed::Fixed { fixed: _ } => {}
} }
} }
} }
@ -67,13 +67,13 @@ impl MagicProgram {
}; };
for (rule_head, ruleset) in self.prog { for (rule_head, ruleset) in self.prog {
match ruleset { match ruleset {
MagicRulesOrAlgo::Rules { rules: ruleset } => { MagicRulesOrFixed::Rules { rules: ruleset } => {
magic_rewrite_ruleset(rule_head, ruleset, &mut ret_prog); magic_rewrite_ruleset(rule_head, ruleset, &mut ret_prog);
} }
MagicRulesOrAlgo::Algo { algo: algo_apply } => { MagicRulesOrFixed::Fixed { fixed } => {
ret_prog ret_prog
.prog .prog
.insert(rule_head, MagicRulesOrAlgo::Algo { algo: algo_apply }); .insert(rule_head, MagicRulesOrFixed::Fixed { fixed });
} }
} }
} }
@ -138,7 +138,7 @@ fn magic_rewrite_ruleset(
ret_prog.prog.insert( ret_prog.prog.insert(
sup_kw.clone(), sup_kw.clone(),
MagicRulesOrAlgo::Rules { MagicRulesOrFixed::Rules {
rules: vec![MagicInlineRule { rules: vec![MagicInlineRule {
head: sup_args.clone(), head: sup_args.clone(),
aggr: sup_aggr, aggr: sup_aggr,
@ -257,7 +257,7 @@ impl NormalFormProgram {
let mut downstream_rules: BTreeSet<Symbol> = Default::default(); let mut downstream_rules: BTreeSet<Symbol> = Default::default();
for rules in self.prog.values() { for rules in self.prog.values() {
match rules { match rules {
NormalFormAlgoOrRules::Rules { rules } => { NormalFormRulesOrFixed::Rules { rules } => {
for rule in rules { for rule in rules {
for atom in rule.body.iter() { for atom in rule.body.iter() {
match atom { match atom {
@ -272,9 +272,9 @@ impl NormalFormProgram {
} }
} }
} }
NormalFormAlgoOrRules::Algo { algo } => { NormalFormRulesOrFixed::Fixed { fixed } => {
for rel in algo.rule_args.iter() { for rel in fixed.rule_args.iter() {
if let AlgoRuleArg::InMem { name, .. } = rel { if let FixedRuleArg::InMem { name, .. } = rel {
downstream_rules.insert(name.clone()); downstream_rules.insert(name.clone());
} }
} }
@ -302,42 +302,42 @@ impl NormalFormProgram {
continue; continue;
} }
match rules { match rules {
NormalFormAlgoOrRules::Algo { algo: algo_apply } => { NormalFormRulesOrFixed::Fixed { fixed } => {
adorned_prog.prog.insert( adorned_prog.prog.insert(
MagicSymbol::Muggle { MagicSymbol::Muggle {
inner: rule_name.clone(), inner: rule_name.clone(),
}, },
MagicRulesOrAlgo::Algo { MagicRulesOrFixed::Fixed {
algo: MagicAlgoApply { fixed: MagicFixedRuleApply {
span: algo_apply.span, span: fixed.span,
algo: algo_apply.algo.clone(), fixed_handle: fixed.fixed_handle.clone(),
algo_impl: algo_apply.algo_impl.clone(), fixed_impl: fixed.fixed_impl.clone(),
rule_args: algo_apply rule_args: fixed
.rule_args .rule_args
.iter() .iter()
.map(|r| -> Result<MagicAlgoRuleArg> { .map(|r| -> Result<MagicFixedRuleRuleArg> {
Ok(match r { Ok(match r {
AlgoRuleArg::InMem { FixedRuleArg::InMem {
name, name,
bindings, bindings,
span, span,
} => MagicAlgoRuleArg::InMem { } => MagicFixedRuleRuleArg::InMem {
name: MagicSymbol::Muggle { name: MagicSymbol::Muggle {
inner: name.clone(), inner: name.clone(),
}, },
bindings: bindings.clone(), bindings: bindings.clone(),
span: *span, span: *span,
}, },
AlgoRuleArg::Stored { FixedRuleArg::Stored {
name, name,
bindings, bindings,
span, span,
} => MagicAlgoRuleArg::Stored { } => MagicFixedRuleRuleArg::Stored {
name: name.clone(), name: name.clone(),
bindings: bindings.clone(), bindings: bindings.clone(),
span: *span, span: *span,
}, },
AlgoRuleArg::NamedStored { FixedRuleArg::NamedStored {
name, name,
bindings, bindings,
span, span,
@ -374,7 +374,7 @@ impl NormalFormProgram {
Some(k) => k.clone(), Some(k) => k.clone(),
}) })
.collect_vec(); .collect_vec();
MagicAlgoRuleArg::Stored { MagicFixedRuleRuleArg::Stored {
name: name.clone(), name: name.clone(),
bindings: new_bindings, bindings: new_bindings,
span: *span, span: *span,
@ -383,13 +383,13 @@ impl NormalFormProgram {
}) })
}) })
.try_collect()?, .try_collect()?,
options: algo_apply.options.clone(), options: fixed.options.clone(),
arity: algo_apply.arity, arity: fixed.arity,
}, },
}, },
); );
} }
NormalFormAlgoOrRules::Rules { rules } => { NormalFormRulesOrFixed::Rules { rules } => {
let mut adorned_rules = Vec::with_capacity(rules.len()); let mut adorned_rules = Vec::with_capacity(rules.len());
for rule in rules { for rule in rules {
let adorned_rule = rule.adorn( let adorned_rule = rule.adorn(
@ -403,7 +403,7 @@ impl NormalFormProgram {
MagicSymbol::Muggle { MagicSymbol::Muggle {
inner: rule_name.clone(), inner: rule_name.clone(),
}, },
MagicRulesOrAlgo::Rules { MagicRulesOrFixed::Rules {
rules: adorned_rules, rules: adorned_rules,
}, },
); );
@ -436,7 +436,7 @@ impl NormalFormProgram {
} }
adorned_prog.prog.insert( adorned_prog.prog.insert(
head, head,
MagicRulesOrAlgo::Rules { MagicRulesOrFixed::Rules {
rules: adorned_rules, rules: adorned_rules,
}, },
); );

@ -15,14 +15,14 @@ use miette::{bail, Diagnostic, Result, WrapErr};
use smartstring::SmartString; use smartstring::SmartString;
use thiserror::Error; use thiserror::Error;
use crate::algo::constant::Constant; use crate::fixed_rule::FixedRuleHandle;
use crate::algo::AlgoHandle;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{AlgoApply, InputInlineRulesOrAlgo, InputProgram, RelationOp}; use crate::data::program::{FixedRuleApply, InputInlineRulesOrFixed, InputProgram, RelationOp};
use crate::data::relation::{ColumnDef, NullableColType}; use crate::data::relation::{ColumnDef, NullableColType};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::{Tuple, ENCODED_KEY_MIN_LEN}; use crate::data::tuple::{Tuple, ENCODED_KEY_MIN_LEN};
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::fixed_rule::utilities::constant::Constant;
use crate::parse::parse_script; use crate::parse::parse_script;
use crate::runtime::relation::{AccessLevel, InputRelationHandle, InsufficientAccessLevel}; use crate::runtime::relation::{AccessLevel, InputRelationHandle, InsufficientAccessLevel};
use crate::runtime::transact::SessionTx; use crate::runtime::transact::SessionTx;
@ -43,8 +43,6 @@ impl<'a> SessionTx<'a> {
meta: &InputRelationHandle, meta: &InputRelationHandle,
headers: &[Symbol], headers: &[Symbol],
) -> Result<Vec<(Vec<u8>, Vec<u8>)>> { ) -> Result<Vec<(Vec<u8>, Vec<u8>)>> {
// TODO
let algorithms = BTreeMap::new();
let mut to_clear = vec![]; let mut to_clear = vec![];
let mut replaced_old_triggers = None; let mut replaced_old_triggers = None;
if op == RelationOp::Replace { if op == RelationOp::Replace {
@ -60,7 +58,7 @@ impl<'a> SessionTx<'a> {
replaced_old_triggers = Some((old_handle.put_triggers, old_handle.rm_triggers)) replaced_old_triggers = Some((old_handle.put_triggers, old_handle.rm_triggers))
} }
for trigger in &old_handle.replace_triggers { for trigger in &old_handle.replace_triggers {
let program = parse_script(trigger, &Default::default(), &algorithms)? let program = parse_script(trigger, &Default::default(), &db.algorithms)?
.get_single_program()?; .get_single_program()?;
let (_, cleanups) = db.run_query(self, program).map_err(|err| { let (_, cleanups) = db.run_query(self, program).map_err(|err| {
@ -437,9 +435,9 @@ fn make_const_rule(
let bindings_arity = bindings.len(); let bindings_arity = bindings.len();
program.prog.insert( program.prog.insert(
rule_symbol, rule_symbol,
InputInlineRulesOrAlgo::Algo { InputInlineRulesOrFixed::Fixed {
algo: AlgoApply { fixed: FixedRuleApply {
algo: AlgoHandle { fixed_handle: FixedRuleHandle {
name: Symbol::new("Constant", Default::default()), name: Symbol::new("Constant", Default::default()),
}, },
rule_args: vec![], rule_args: vec![],
@ -447,7 +445,7 @@ fn make_const_rule(
head: bindings, head: bindings,
arity: bindings_arity, arity: bindings_arity,
span: Default::default(), span: Default::default(),
algo_impl: Arc::new(Box::new(Constant)), fixed_impl: Arc::new(Box::new(Constant)),
}, },
}, },
); );

@ -14,7 +14,7 @@ use miette::{ensure, Diagnostic, Result};
use thiserror::Error; use thiserror::Error;
use crate::data::program::{ use crate::data::program::{
AlgoRuleArg, MagicSymbol, NormalFormAlgoOrRules, NormalFormAtom, NormalFormProgram, FixedRuleArg, MagicSymbol, NormalFormRulesOrFixed, NormalFormAtom, NormalFormProgram,
StratifiedNormalFormProgram, StratifiedNormalFormProgram,
}; };
use crate::data::symb::{Symbol, PROG_ENTRY}; use crate::data::symb::{Symbol, PROG_ENTRY};
@ -43,7 +43,7 @@ fn convert_normal_form_program_to_graph(
.prog .prog
.iter() .iter()
.filter_map(|(k, ruleset)| match ruleset { .filter_map(|(k, ruleset)| match ruleset {
NormalFormAlgoOrRules::Rules { rules: ruleset } => { NormalFormRulesOrFixed::Rules { rules: ruleset } => {
let has_aggr = ruleset let has_aggr = ruleset
.iter() .iter()
.any(|rule| rule.aggr.iter().any(|a| a.is_some())); .any(|rule| rule.aggr.iter().any(|a| a.is_some()));
@ -60,22 +60,22 @@ fn convert_normal_form_program_to_graph(
None None
} }
} }
NormalFormAlgoOrRules::Algo { algo: _ } => None, NormalFormRulesOrFixed::Fixed { fixed: _ } => None,
}) })
.collect(); .collect();
let algo_rules: BTreeSet<_> = nf_prog let fixed_rules: BTreeSet<_> = nf_prog
.prog .prog
.iter() .iter()
.filter_map(|(k, ruleset)| match ruleset { .filter_map(|(k, ruleset)| match ruleset {
NormalFormAlgoOrRules::Rules { rules: _ } => None, NormalFormRulesOrFixed::Rules { rules: _ } => None,
NormalFormAlgoOrRules::Algo { algo: _ } => Some(k), NormalFormRulesOrFixed::Fixed { fixed: _ } => Some(k),
}) })
.collect(); .collect();
nf_prog nf_prog
.prog .prog
.iter() .iter()
.map(|(k, ruleset)| match ruleset { .map(|(k, ruleset)| match ruleset {
NormalFormAlgoOrRules::Rules { rules: ruleset } => { NormalFormRulesOrFixed::Rules { rules: ruleset } => {
let mut ret: BTreeMap<&Symbol, bool> = BTreeMap::default(); let mut ret: BTreeMap<&Symbol, bool> = BTreeMap::default();
let has_aggr = ruleset let has_aggr = ruleset
.iter() .iter()
@ -93,18 +93,18 @@ fn convert_normal_form_program_to_graph(
for (found_key, is_negated) in contained { for (found_key, is_negated) in contained {
let found_key_is_meet = let found_key_is_meet =
meet_rules.contains(found_key) && found_key != k; meet_rules.contains(found_key) && found_key != k;
let found_key_is_algo = algo_rules.contains(found_key); let found_key_is_fixed_rule = fixed_rules.contains(found_key);
match ret.entry(found_key) { match ret.entry(found_key) {
Entry::Vacant(e) => { Entry::Vacant(e) => {
if has_aggr { if has_aggr {
if is_meet && k == found_key { if is_meet && k == found_key {
e.insert(found_key_is_algo || is_negated); e.insert(found_key_is_fixed_rule || is_negated);
} else { } else {
e.insert(true); e.insert(true);
} }
} else { } else {
e.insert( e.insert(
found_key_is_algo || found_key_is_meet || is_negated, found_key_is_fixed_rule || found_key_is_meet || is_negated,
); );
} }
} }
@ -112,12 +112,12 @@ fn convert_normal_form_program_to_graph(
let old = *e.get(); let old = *e.get();
let new_val = if has_aggr { let new_val = if has_aggr {
if is_meet && k == found_key { if is_meet && k == found_key {
found_key_is_algo || found_key_is_meet || is_negated found_key_is_fixed_rule || found_key_is_meet || is_negated
} else { } else {
true true
} }
} else { } else {
found_key_is_algo || found_key_is_meet || is_negated found_key_is_fixed_rule || found_key_is_meet || is_negated
}; };
e.insert(old || new_val); e.insert(old || new_val);
} }
@ -127,14 +127,14 @@ fn convert_normal_form_program_to_graph(
} }
(k, ret) (k, ret)
} }
NormalFormAlgoOrRules::Algo { algo } => { NormalFormRulesOrFixed::Fixed { fixed } => {
let mut ret: BTreeMap<&Symbol, bool> = BTreeMap::default(); let mut ret: BTreeMap<&Symbol, bool> = BTreeMap::default();
for rel in &algo.rule_args { for rel in &fixed.rule_args {
match rel { match rel {
AlgoRuleArg::InMem { name, .. } => { FixedRuleArg::InMem { name, .. } => {
ret.insert(name, true); ret.insert(name, true);
} }
AlgoRuleArg::Stored { .. } | AlgoRuleArg::NamedStored { .. } => {} FixedRuleArg::Stored { .. } | FixedRuleArg::NamedStored { .. } => {}
} }
} }
(k, ret) (k, ret)

@ -38,8 +38,8 @@ use crate::query::ra::{
use crate::runtime::relation::{AccessLevel, InsufficientAccessLevel, RelationHandle, RelationId}; use crate::runtime::relation::{AccessLevel, InsufficientAccessLevel, RelationHandle, RelationId};
use crate::runtime::transact::SessionTx; use crate::runtime::transact::SessionTx;
use crate::storage::{Storage, StoreTx}; use crate::storage::{Storage, StoreTx};
use crate::{decode_tuple_from_kv, AlgoImpl}; use crate::{decode_tuple_from_kv, FixedRule};
use crate::algo::DEFAULT_ALGOS; use crate::fixed_rule::DEFAULT_FIXED_RULES;
struct RunningQueryHandle { struct RunningQueryHandle {
started_at: f64, started_at: f64,
@ -72,7 +72,7 @@ pub struct Db<S> {
relation_store_id: Arc<AtomicU64>, relation_store_id: Arc<AtomicU64>,
queries_count: Arc<AtomicU64>, queries_count: Arc<AtomicU64>,
running_queries: Arc<Mutex<BTreeMap<u64, RunningQueryHandle>>>, running_queries: Arc<Mutex<BTreeMap<u64, RunningQueryHandle>>>,
pub(crate) algorithms: Arc<BTreeMap<String, Arc<Box<dyn AlgoImpl>>>>, pub(crate) algorithms: Arc<BTreeMap<String, Arc<Box<dyn FixedRule>>>>,
} }
impl<S> Debug for Db<S> { impl<S> Debug for Db<S> {
@ -118,7 +118,7 @@ impl<'s, S: Storage<'s>> Db<S> {
relation_store_id: Arc::new(Default::default()), relation_store_id: Arc::new(Default::default()),
queries_count: Arc::new(Default::default()), queries_count: Arc::new(Default::default()),
running_queries: Arc::new(Mutex::new(Default::default())), running_queries: Arc::new(Mutex::new(Default::default())),
algorithms: DEFAULT_ALGOS.clone(), algorithms: DEFAULT_FIXED_RULES.clone(),
}; };
Ok(ret) Ok(ret)
} }
@ -626,7 +626,7 @@ impl<'s, S: Storage<'s>> Db<S> {
ret.extend(ret_for_relation) ret.extend(ret_for_relation)
} }
} }
CompiledRuleSet::Algo(_) => ret.push(json!({ CompiledRuleSet::Fixed(_) => ret.push(json!({
STRATUM: stratum, STRATUM: stratum,
ATOM_IDX: 0, ATOM_IDX: 0,
OP: "algo", OP: "algo",

Loading…
Cancel
Save