use thiserror::Error;
#[derive(Debug, Error, Clone, PartialEq)]
pub enum LocyCompileError {
#[error("cyclic negation among rules: {}", rules.join(", "))]
CyclicNegation { rules: Vec<String> },
#[error("undefined rule: {name}")]
UndefinedRule { name: String },
#[error("prev reference in non-recursive rule '{rule}', field '{field}'")]
PrevInBaseCase { rule: String, field: String },
#[error("non-monotonic aggregate '{aggregate}' in recursive rule '{rule}'")]
NonMonotonicInRecursion { rule: String, aggregate: String },
#[error("BEST BY with monotonic fold '{fold}' in rule '{rule}'")]
BestByWithMonotonicFold { rule: String, fold: String },
#[error("post-FOLD WHERE in rule '{rule}' requires a FOLD clause")]
HavingWithoutFold { rule: String },
#[error("wardedness violation: variable '{variable}' in rule '{rule}' not bound by MATCH")]
WardednessViolation { rule: String, variable: String },
#[error("YIELD schema mismatch in rule '{rule}': {detail}")]
YieldSchemaMismatch { rule: String, detail: String },
#[error("mixed priority in rule '{rule}': some clauses have PRIORITY, others don't")]
MixedPriority { rule: String },
#[error("module not found: {name}")]
ModuleNotFound { name: String },
#[error("import not found: rule '{rule}' in module '{module}'")]
ImportNotFound { module: String, rule: String },
#[error(
"IS arity mismatch in rule '{rule}': reference to '{target}' provides {actual} bindings, but '{target}' yields {expected} columns"
)]
IsArityMismatch {
rule: String,
target: String,
expected: usize,
actual: usize,
},
#[error(
"prev.{field} in rule '{rule}' references unknown column; available columns from IS references: {available}"
)]
PrevFieldNotInSchema {
rule: String,
field: String,
available: String,
},
#[error("rule '{rule}' has {count} PROB columns; at most 1 is allowed")]
MultipleProbColumns { rule: String, count: usize },
#[error(
"CREATE MODEL '{model_name}' parsed but neural_predicates_preview is disabled; \
set LocyConfig::neural_predicates_preview = true to enable"
)]
NeuralPreviewDisabled { model_name: String },
#[error("model name collision: '{name}' is already declared")]
ModelNameCollision { name: String },
#[error(
"model '{name}' arity mismatch in rule '{rule}': expected {expected} input(s), got {actual}"
)]
ModelArityMismatch {
name: String,
rule: String,
expected: usize,
actual: usize,
},
#[error(
"CALIBRATE references unknown model '{name}'; declare it with \
CREATE MODEL first"
)]
CalibrateUnknownModel { name: String },
#[error(
"CALIBRATE on model '{name}': calibration only applies to PROB \
outputs, but '{name}' is declared as {declared}"
)]
CalibrateOnNonProbModel { name: String, declared: String },
#[error(
"CALIBRATE on model '{model_name}': HOLDOUT must be in the open \
interval (0, 1); got {holdout}"
)]
CalibrateInvalidHoldout { model_name: String, holdout: f64 },
#[error(
"CALIBRATE '{model_name}' parsed but neural_predicates_preview is \
disabled; set LocyConfig::neural_predicates_preview = true to enable"
)]
CalibratePreviewDisabled { model_name: String },
#[error(
"VALIDATE references unknown rule '{name}'; declare it with \
CREATE RULE first"
)]
ValidateUnknownRule { name: String },
#[error(
"VALIDATE rule '{name}' has no PROB column; calibration metrics \
only apply to probability outputs"
)]
ValidateRuleHasNoProbColumn { name: String },
#[error("VALIDATE rule '{name}' must request at least one metric")]
ValidateNoMetrics { name: String },
#[error(
"rule '{rule}' invokes neural model '{model}' in a WHERE clause, \
which is not yet supported. Lift the call into YIELD (e.g. \
`YIELD KEY x, {model}(x) AS p`) and apply the filter on the \
materialized rule output instead."
)]
WhereModelInvocationNotYetSupported { rule: String, model: String },
#[error(
"rule '{rule}': neural model '{model}' feature expression \
{expr} is unsupported — only plain variables and direct \
property access (`var.prop`) are accepted today"
)]
UnsupportedFeatureExpression {
rule: String,
model: String,
expr: String,
},
}