|
|
|
@ -1,9 +1,9 @@
|
|
|
|
|
use std::collections::btree_map::Entry;
|
|
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
|
|
|
|
use std::collections::btree_map::Entry;
|
|
|
|
|
use std::fmt::{Debug, Formatter};
|
|
|
|
|
|
|
|
|
|
use either::{Left, Right};
|
|
|
|
|
use miette::{ensure, Diagnostic, Result};
|
|
|
|
|
use miette::{Diagnostic, ensure, Result};
|
|
|
|
|
use smallvec::SmallVec;
|
|
|
|
|
use smartstring::{LazyCompact, SmartString};
|
|
|
|
|
use thiserror::Error;
|
|
|
|
@ -13,7 +13,7 @@ use crate::data::aggr::Aggregation;
|
|
|
|
|
use crate::data::attr::Attribute;
|
|
|
|
|
use crate::data::expr::Expr;
|
|
|
|
|
use crate::data::id::Validity;
|
|
|
|
|
use crate::data::symb::{Symbol, PROG_ENTRY};
|
|
|
|
|
use crate::data::symb::{PROG_ENTRY, Symbol};
|
|
|
|
|
use crate::data::tuple::Tuple;
|
|
|
|
|
use crate::data::value::DataValue;
|
|
|
|
|
use crate::parse::pull::OutPullSpec;
|
|
|
|
@ -515,6 +515,46 @@ impl InputProgram {
|
|
|
|
|
|
|
|
|
|
Err(NoEntryError.into())
|
|
|
|
|
}
|
|
|
|
|
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))) {
|
|
|
|
|
return match entry {
|
|
|
|
|
InputRulesOrAlgo::Rules { rules } => {
|
|
|
|
|
let head = &rules.last().unwrap().head;
|
|
|
|
|
let mut ret = Vec::with_capacity(head.len());
|
|
|
|
|
let aggrs = &rules.last().unwrap().aggr;
|
|
|
|
|
for (symb, aggr) in head.iter().zip(aggrs.iter()) {
|
|
|
|
|
if let Some((aggr, _)) = aggr {
|
|
|
|
|
ret.push(Symbol::new(
|
|
|
|
|
&format!("{}({})", aggr.name.strip_prefix("AGGR_").unwrap().to_ascii_lowercase(),
|
|
|
|
|
symb), symb.span))
|
|
|
|
|
} else {
|
|
|
|
|
ret.push(symb.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(ret)
|
|
|
|
|
}
|
|
|
|
|
InputRulesOrAlgo::Algo { algo: algo_apply } => {
|
|
|
|
|
if algo_apply.head.is_empty() {
|
|
|
|
|
Err(EntryHeadNotExplicitlyDefinedError(entry.first_span()).into())
|
|
|
|
|
} else {
|
|
|
|
|
Ok(algo_apply.head.to_vec())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(ConstRule { bindings, span, .. }) = self.const_rules.get(&MagicSymbol::Muggle {
|
|
|
|
|
inner: Symbol::new(PROG_ENTRY, SourceSpan(0, 0)),
|
|
|
|
|
}) {
|
|
|
|
|
return if bindings.is_empty() {
|
|
|
|
|
Err(EntryHeadNotExplicitlyDefinedError(*span).into())
|
|
|
|
|
} else {
|
|
|
|
|
Ok(bindings.to_vec())
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Err(NoEntryError.into())
|
|
|
|
|
}
|
|
|
|
|
pub(crate) fn get_entry_head(&self) -> Result<&[Symbol]> {
|
|
|
|
|
if let Some(entry) = self.prog.get(&Symbol::new(PROG_ENTRY, SourceSpan(0, 0))) {
|
|
|
|
|
return match entry {
|
|
|
|
|