error messages for algo module

main
Ziyang Hu 2 years ago
parent 03bf010bb8
commit 8c76681e49

@ -2,8 +2,9 @@ use std::collections::BTreeMap;
use either::Either;
use itertools::Itertools;
use miette::{bail, ensure, miette, Result};
use miette::{bail, ensure, Diagnostic, Result};
use smartstring::{LazyCompact, SmartString};
use thiserror::Error;
use crate::algo::all_pairs_shortest_path::{BetweennessCentrality, ClosenessCentrality};
use crate::algo::astar::ShortestPathAStar;
@ -136,11 +137,45 @@ impl AlgoHandle {
"label_propagation" => Box::new(LabelPropagation),
"random_walk" => Box::new(RandomWalk),
"reorder_sort" => Box::new(ReorderSort),
name => bail!("algorithm '{}' not found", name),
name => bail!(AlgoNotFoundError(name.to_string(), self.name.span)),
})
}
}
#[derive(Error, Diagnostic, Debug)]
#[error("The relation cannot be interpreted as an edge")]
#[diagnostic(code(algo::not_an_edge))]
#[diagnostic(help("Edge relation requires tuples of length at least two"))]
struct NotAnEdgeError(#[label] SourceSpan);
#[derive(Error, Diagnostic, Debug)]
#[error(
"The value {0:?} at the third position in the relation cannot be interpreted as edge weights"
)]
#[diagnostic(code(algo::invalid_edge_weight))]
#[diagnostic(help(
"Edge weights must be finite numbers. Some algorithm also requires positivity."
))]
struct BadEdgeWeightError(DataValue, #[label] SourceSpan);
#[derive(Error, Diagnostic, Debug)]
#[error("The requested rule '{0}' cannot be found")]
#[diagnostic(code(algo::rule_not_found))]
struct RuleNotFoundError(String, #[label] SourceSpan);
#[derive(Error, Diagnostic, Debug)]
#[error("Invalid reverse scanning of triples")]
#[diagnostic(code(algo::invalid_reverse_triple_scan))]
#[diagnostic(help(
"Inverse scanning of triples requires the type to be 'ref', or the value be indexed"
))]
struct InvalidInverseTripleUse(String, #[label] SourceSpan);
#[derive(Error, Diagnostic, Debug)]
#[error("The requested algorithm '{0}' is not found")]
#[diagnostic(code(parser::algo_not_found))]
pub(crate) struct AlgoNotFoundError(pub(crate) String, #[label] pub(crate) SourceSpan);
impl MagicAlgoRuleArg {
pub(crate) fn convert_edge_to_weighted_graph(
&self,
@ -161,26 +196,45 @@ impl MagicAlgoRuleArg {
for tuple in self.iter(tx, stores)? {
let mut tuple = tuple?.0.into_iter();
let from = tuple
.next()
.ok_or_else(|| miette!("edges relation too short"))?;
let to = tuple
.next()
.ok_or_else(|| miette!("edges relation too short"))?;
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(), "edge weight must be finite, got {}", f);
ensure!(
f.is_finite(),
BadEdgeWeightError(
d,
self.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or(self.span())
)
);
if f < 0. {
if !allow_negative_edges {
bail!("edge weight must be non-negative, got {}", f);
bail!(BadEdgeWeightError(
d,
self.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or(self.span())
));
}
has_neg_edge = true;
}
f
}
None => bail!("edge weight must be a number, got {:?}", d),
None => {
bail!(BadEdgeWeightError(
d,
self.bindings()
.get(2)
.map(|s| s.span)
.unwrap_or(self.span())
))
}
},
};
let from_idx = if let Some(idx) = inv_indices.get(&from) {
@ -220,12 +274,8 @@ impl MagicAlgoRuleArg {
for tuple in self.iter(tx, stores)? {
let mut tuple = tuple?.0.into_iter();
let from = tuple
.next()
.ok_or_else(|| miette!("edges relation too short"))?;
let to = tuple
.next()
.ok_or_else(|| miette!("edges relation too short"))?;
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 {
@ -260,9 +310,9 @@ impl MagicAlgoRuleArg {
) -> Result<TupleIter<'a>> {
Ok(match self {
MagicAlgoRuleArg::InMem { name, .. } => {
let store = stores
.get(name)
.ok_or_else(|| miette!("rule not found: {:?}", name))?;
let store = stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?;
let t = Tuple(vec![prefix.clone()]);
Box::new(store.scan_prefix(&t))
}
@ -271,53 +321,63 @@ impl MagicAlgoRuleArg {
let t = Tuple(vec![prefix.clone()]);
Box::new(relation.scan_prefix(tx, &t))
}
MagicAlgoRuleArg::Triple { name, dir, vld, .. } => {
if *dir == TripleDir::Bwd && !name.val_type.is_ref_type() {
MagicAlgoRuleArg::Triple {
attr,
dir,
vld,
span,
..
} => {
if *dir == TripleDir::Bwd && !attr.val_type.is_ref_type() {
ensure!(
name.indexing.should_index(),
"reverse scanning of triple values requires indexing: {:?}",
name.name
attr.indexing.should_index(),
InvalidInverseTripleUse(attr.name.to_string(), *span)
);
if name.with_history {
if attr.with_history {
Box::new(
tx.triple_av_before_scan(name.id, prefix, *vld)
tx.triple_av_before_scan(attr.id, prefix, *vld)
.map_ok(|(_, v, eid)| Tuple(vec![v, eid.as_datavalue()])),
)
} else {
Box::new(
tx.triple_av_scan(name.id, prefix)
tx.triple_av_scan(attr.id, prefix)
.map_ok(|(_, v, eid)| Tuple(vec![v, eid.as_datavalue()])),
)
}
} else {
let id = prefix.get_int().ok_or_else(|| {
miette!(
"prefix scanning of triple requires integer id, got {:?}",
prefix
)
})?;
#[derive(Error, Diagnostic, Debug)]
#[error("Encountered bad prefix value {0:?} during triple prefix scanning")]
#[diagnostic(code(algo::invalid_triple_prefix))]
#[diagnostic(help(
"Triple prefix should be an entity ID represented by an integer"
))]
struct InvalidTriplePrefixError(DataValue, #[label] SourceSpan);
let id = prefix
.get_int()
.ok_or_else(|| InvalidTriplePrefixError(prefix.clone(), self.span()))?;
let id = EntityId(id as u64);
match dir {
TripleDir::Fwd => {
if name.with_history {
if attr.with_history {
Box::new(
tx.triple_ae_before_scan(name.id, id, *vld)
tx.triple_ae_before_scan(attr.id, id, *vld)
.map_ok(|(_, eid, v)| Tuple(vec![eid.as_datavalue(), v])),
)
} else {
Box::new(
tx.triple_ae_scan(name.id, id)
tx.triple_ae_scan(attr.id, id)
.map_ok(|(_, eid, v)| Tuple(vec![eid.as_datavalue(), v])),
)
}
}
TripleDir::Bwd => {
if name.with_history {
Box::new(tx.triple_vref_a_before_scan(id, name.id, *vld).map_ok(
if attr.with_history {
Box::new(tx.triple_vref_a_before_scan(id, attr.id, *vld).map_ok(
|(v, _, eid)| Tuple(vec![v.as_datavalue(), eid.as_datavalue()]),
))
} else {
Box::new(tx.triple_vref_a_scan(id, name.id).map_ok(
Box::new(tx.triple_vref_a_scan(id, attr.id).map_ok(
|(v, _, eid)| Tuple(vec![v.as_datavalue(), eid.as_datavalue()]),
))
}
@ -334,9 +394,9 @@ impl MagicAlgoRuleArg {
) -> Result<usize> {
Ok(match self {
MagicAlgoRuleArg::InMem { name, .. } => {
let store = stores
.get(name)
.ok_or_else(|| miette!("rule not found: {:?}", name))?;
let store = stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?;
store.arity
}
MagicAlgoRuleArg::Stored { name, .. } => {
@ -353,16 +413,21 @@ impl MagicAlgoRuleArg {
) -> Result<TupleIter<'a>> {
Ok(match self {
MagicAlgoRuleArg::InMem { name, .. } => {
let store = stores
.get(name)
.ok_or_else(|| miette!("rule not found: {:?}", name))?;
let store = stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?;
Box::new(store.scan_all())
}
MagicAlgoRuleArg::Stored { name, .. } => {
let relation = tx.get_relation(name)?;
Box::new(relation.scan_all(tx)?)
}
MagicAlgoRuleArg::Triple { name, dir, vld, .. } => match dir {
MagicAlgoRuleArg::Triple {
attr: name,
dir,
vld,
..
} => match dir {
TripleDir::Fwd => {
if name.with_history {
Box::new(

@ -224,15 +224,18 @@ pub(crate) enum AlgoRuleArg {
InMem {
name: Symbol,
bindings: Vec<Symbol>,
span: SourceSpan,
},
Stored {
name: Symbol,
bindings: Vec<Symbol>,
span: SourceSpan,
},
Triple {
name: Symbol,
bindings: Vec<Symbol>,
dir: TripleDir,
span: SourceSpan,
},
}
@ -241,20 +244,37 @@ pub(crate) enum MagicAlgoRuleArg {
InMem {
name: MagicSymbol,
bindings: Vec<Symbol>,
span: SourceSpan,
},
Stored {
name: Symbol,
bindings: Vec<Symbol>,
span: SourceSpan,
},
Triple {
name: Attribute,
attr: Attribute,
bindings: Vec<Symbol>,
dir: TripleDir,
vld: Validity,
span: SourceSpan,
},
}
impl MagicAlgoRuleArg {
pub(crate) fn bindings(&self) -> &[Symbol] {
match self {
MagicAlgoRuleArg::InMem { bindings, .. }
| MagicAlgoRuleArg::Stored { bindings, .. }
| MagicAlgoRuleArg::Triple { bindings, .. } => bindings,
}
}
pub(crate) fn span(&self) -> SourceSpan {
match self {
MagicAlgoRuleArg::InMem { span, .. }
| MagicAlgoRuleArg::Stored { span, .. }
| MagicAlgoRuleArg::Triple { span, .. } => *span,
}
}
pub(crate) fn get_binding_map(&self, starting: usize) -> BTreeMap<Symbol, usize> {
let bindings = match self {
MagicAlgoRuleArg::InMem { bindings, .. }

@ -10,7 +10,7 @@ use miette::{bail, ensure, miette, Diagnostic, LabeledSpan, Report, Result};
use smartstring::{LazyCompact, SmartString};
use thiserror::Error;
use crate::algo::AlgoHandle;
use crate::algo::{AlgoHandle, AlgoNotFoundError};
use crate::data::aggr::{parse_aggr, Aggregation};
use crate::data::expr::Expr;
use crate::data::id::Validity;
@ -581,6 +581,7 @@ fn parse_algo_rule(
match nxt.as_rule() {
Rule::algo_rel => {
let inner = nxt.into_inner().next().unwrap();
let span = inner.extract_span();
match inner.as_rule() {
Rule::algo_rule_rel => {
let mut els = inner.into_inner();
@ -591,6 +592,7 @@ fn parse_algo_rule(
rule_args.push(AlgoRuleArg::InMem {
name: Symbol::new(name.as_str(), name.extract_span()),
bindings,
span
})
}
Rule::algo_relation_rel => {
@ -605,6 +607,7 @@ fn parse_algo_rule(
name.extract_span(),
),
bindings,
span
})
}
Rule::algo_triple_rel => {
@ -628,6 +631,7 @@ fn parse_algo_rule(
Symbol::new(snd.as_str(), snd.extract_span()),
],
dir,
span
});
}
_ => unreachable!(),
@ -647,7 +651,7 @@ fn parse_algo_rule(
let algo = AlgoHandle::new(algo_name, name_pair.extract_span());
let algo_arity = algo
.arity(Left(&rule_args), &options)
.ok_or_else(|| miette!("bad algo arity"))?;
.ok_or_else(|| AlgoNotFoundError(algo.name.to_string(), algo.name.span))?;
ensure!(
head.is_empty() || algo_arity == head.len(),
"algo head must have the same length as the return, or be omitted"

@ -3,6 +3,7 @@ use std::collections::{BTreeMap, BTreeSet};
use itertools::Itertools;
use miette::{ensure, miette, Context, Result};
use crate::algo::AlgoNotFoundError;
use crate::data::aggr::Aggregation;
use crate::data::expr::Expr;
use crate::data::program::{
@ -96,7 +97,9 @@ impl SessionTx {
name.clone(),
self.new_rule_store(
name.clone(),
ruleset.arity().ok_or_else(|| miette!("bad algo arity"))?,
ruleset.arity().ok_or_else(|| {
AlgoNotFoundError(name.symbol().to_string(), name.symbol().span)
})?,
),
);
}
@ -366,21 +369,27 @@ impl SessionTx {
MagicAtom::Unification(u) => {
if seen_variables.contains(&u.binding) {
let expr = if u.one_many_unif {
Expr::build_is_in(vec![
Expr::Binding {
var: u.binding.clone(),
tuple_pos: None,
},
u.expr.clone(),
], u.span)
Expr::build_is_in(
vec![
Expr::Binding {
var: u.binding.clone(),
tuple_pos: None,
},
u.expr.clone(),
],
u.span,
)
} else {
Expr::build_equate(vec![
Expr::Binding {
var: u.binding.clone(),
tuple_pos: None,
},
u.expr.clone(),
], u.span)
Expr::build_equate(
vec![
Expr::Binding {
var: u.binding.clone(),
tuple_pos: None,
},
u.expr.clone(),
],
u.span,
)
};
if let Some(fs) = ret.get_filters() {
fs.push(expr);

@ -325,24 +325,31 @@ impl NormalFormProgram {
.iter()
.map(|r| -> Result<MagicAlgoRuleArg> {
Ok(match r {
AlgoRuleArg::InMem { name, bindings } => {
MagicAlgoRuleArg::InMem {
name: MagicSymbol::Muggle {
inner: name.clone(),
},
bindings: bindings.clone(),
}
}
AlgoRuleArg::Stored { name, bindings } => {
MagicAlgoRuleArg::Stored {
name: name.clone(),
bindings: bindings.clone(),
}
}
AlgoRuleArg::InMem {
name,
bindings,
span,
} => MagicAlgoRuleArg::InMem {
name: MagicSymbol::Muggle {
inner: name.clone(),
},
bindings: bindings.clone(),
span: *span,
},
AlgoRuleArg::Stored {
name,
bindings,
span,
} => MagicAlgoRuleArg::Stored {
name: name.clone(),
bindings: bindings.clone(),
span: *span,
},
AlgoRuleArg::Triple {
name,
bindings,
dir,
span,
} => {
let attr = tx
.attr_by_name(&name.name)?
@ -350,10 +357,11 @@ impl NormalFormProgram {
miette!("cannot find attribute {}", name)
})?;
MagicAlgoRuleArg::Triple {
name: attr,
attr: attr,
bindings: bindings.clone(),
dir: *dir,
vld: algo_apply.vld.unwrap_or(default_vld),
span: *span,
}
}
})

Loading…
Cancel
Save