use super::{Row, SuiteGroup, TrialTable, Trials};
use crate::bounded::Overflow;
use crate::descriptor::vocabulary::{self, HarnessName, HarnessWord};
use crate::descriptor::{Emitter, Name};
use crate::kind::Kind;
use crate::stamp::{Visibility, declared_reach_tokens};
use crate::token::{
GeneratedDelimiter, GeneratedToken, bound_local, comma, group, metavariable, method_call,
roster, text_pair,
};
const SUBJECT_LOCAL: &str = "subject";
const CHECK_LOCAL: &str = "check";
const ROW_LOCAL: &str = "row";
const ATTACHMENT_LOCAL: &str = "attachment";
const DECLARED_LOCAL: &str = "declared";
fn parsed(
reference: HarnessName,
namespace: &str,
stem: &str,
) -> Result<Vec<GeneratedToken>, Overflow> {
let mut tokens = vocabulary::road(
&[HarnessName::Descriptor, reference, HarnessName::Named],
text_pair(namespace, stem),
)?;
tokens.push(GeneratedToken::alone('?'));
Ok(tokens)
}
fn parsed_name(reference: HarnessName, name: &Name) -> Result<Vec<GeneratedToken>, Overflow> {
parsed(reference, name.namespace(), name.stem())
}
pub fn table_schema_identity() -> Result<Vec<GeneratedToken>, Overflow> {
let published = vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::Schema,
HarnessName::Published,
],
Vec::new(),
)?;
let declared = method_call(
published,
"map_err",
vocabulary::path(&[
HarnessName::Descriptor,
HarnessName::TableRefusal,
HarnessName::SchemaNotDeclared,
]),
)?;
method_call(declared, "and_then", schema_closure()?)
}
fn schema_closure() -> Result<Vec<GeneratedToken>, Overflow> {
let taken = method_call(
vec![GeneratedToken::word(DECLARED_LOCAL)],
HarnessName::Identity.spelling(),
Vec::new(),
)?;
let mapped = method_call(
taken,
"map_err",
vocabulary::path(&[
HarnessName::Descriptor,
HarnessName::TableRefusal,
HarnessName::SchemaNotEncoded,
]),
)?;
let mut tokens = vec![
GeneratedToken::alone('|'),
GeneratedToken::word(DECLARED_LOCAL),
GeneratedToken::alone('|'),
];
tokens.extend(mapped);
Ok(tokens)
}
pub fn row_schema_identity() -> Result<Vec<GeneratedToken>, Overflow> {
let mut tokens = vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::Schema,
HarnessName::Published,
],
Vec::new(),
)?;
tokens.push(GeneratedToken::alone('?'));
tokens.push(GeneratedToken::alone('.'));
tokens.push(GeneratedToken::word(HarnessName::Identity.spelling()));
tokens.push(group(GeneratedDelimiter::Parenthesis, Vec::new())?);
tokens.push(GeneratedToken::alone('?'));
Ok(tokens)
}
#[must_use]
pub fn attachment_metavariable(lens: &str, seat: HarnessWord) -> String {
crate::descriptor::emitting::row_metavariable(lens, seat)
}
pub fn attachment(declared: &Row) -> Result<Vec<GeneratedToken>, Overflow> {
let lens = declared.lens().spelling();
let mut arguments = vec![
GeneratedToken::word(SUBJECT_LOCAL),
GeneratedToken::alone(','),
GeneratedToken::word(CHECK_LOCAL),
GeneratedToken::alone(','),
];
for seat in [
HarnessWord::SubjectRevision,
HarnessWord::CheckRevision,
HarnessWord::Call,
] {
arguments.extend(metavariable(&attachment_metavariable(lens, seat)));
arguments.push(GeneratedToken::alone(','));
}
vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::Attachment,
HarnessName::Attached,
],
arguments,
)
}
pub fn origin(emitter: Emitter) -> Result<Vec<GeneratedToken>, Overflow> {
let door = parsed(HarnessName::DoorRef, emitter.namespace, emitter.door)?;
let projection = parsed(
HarnessName::ProjectionRef,
emitter.namespace,
<TrialTable as Kind>::NAME,
)?;
let facts = vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::ProducerFacts,
HarnessName::Emitted,
],
comma(door, projection),
)?;
vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::Origin,
HarnessName::Generated,
],
facts,
)
}
pub fn classification(declared: &Row) -> Result<Vec<GeneratedToken>, Overflow> {
let roles = labels(HarnessName::RoleRef, declared.roles())?;
let tags = labels(HarnessName::TagRef, declared.tags())?;
let mut tokens = vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::Classification,
HarnessName::Authored,
],
comma(roster(roles)?, roster(tags)?),
)?;
tokens.push(GeneratedToken::alone('?'));
Ok(tokens)
}
fn labels(reference: HarnessName, names: &[Name]) -> Result<Vec<GeneratedToken>, Overflow> {
let mut tokens: Vec<GeneratedToken> = Vec::new();
for name in names {
tokens.extend(parsed_name(reference, name)?);
tokens.push(GeneratedToken::alone(','));
}
Ok(tokens)
}
pub fn declared_row(
declared: &Row,
suite: &Name,
emitter: Emitter,
) -> Result<Vec<GeneratedToken>, Overflow> {
let references = declared.references();
let mut arguments = parsed_name(HarnessName::ClaimRef, &references.claim)?;
arguments.push(GeneratedToken::alone(','));
arguments.extend(parsed_name(HarnessName::ExecutionSuite, suite)?);
arguments.push(GeneratedToken::alone(','));
arguments.extend(classification(declared)?);
arguments.push(GeneratedToken::alone(','));
arguments.push(GeneratedToken::word(SUBJECT_LOCAL));
arguments.push(GeneratedToken::alone(','));
arguments.push(GeneratedToken::word(CHECK_LOCAL));
arguments.push(GeneratedToken::alone(','));
arguments.extend(parsed_name(
HarnessName::PopulationRef,
&references.population,
)?);
arguments.push(GeneratedToken::alone(','));
arguments.extend(origin(emitter)?);
arguments.push(GeneratedToken::alone(','));
let mut tokens = vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::RowType,
HarnessName::Declared,
],
arguments,
)?;
tokens.push(GeneratedToken::alone('?'));
Ok(tokens)
}
pub fn provenance(emitter: Emitter) -> Result<Vec<GeneratedToken>, Overflow> {
let mut seats = vocabulary::key(HarnessWord::Producer);
seats.extend(parsed(
HarnessName::ProducerName,
emitter.namespace,
emitter.producer,
)?);
seats.push(GeneratedToken::alone(','));
seats.extend(vocabulary::key(HarnessWord::Schema));
seats.extend(row_schema_identity()?);
seats.push(GeneratedToken::alone(','));
let mut tokens = vocabulary::path(&[
HarnessName::Descriptor,
HarnessName::ProvenanceType,
HarnessName::ProducedProvenance,
]);
tokens.push(group(GeneratedDelimiter::Brace, seats)?);
Ok(tokens)
}
pub fn row_expression(
declared: &Row,
suite: &Name,
emitter: Emitter,
) -> Result<Vec<GeneratedToken>, Overflow> {
let references = declared.references();
let mut body = bound_local(
SUBJECT_LOCAL,
parsed_name(HarnessName::SubjectRoute, &references.subject)?,
);
body.extend(bound_local(
CHECK_LOCAL,
parsed_name(HarnessName::CheckRef, &references.check)?,
));
body.extend(bound_local(
ROW_LOCAL,
declared_row(declared, suite, emitter)?,
));
body.extend(bound_local(ATTACHMENT_LOCAL, attachment(declared)?));
let mut arguments = vec![
GeneratedToken::word(ROW_LOCAL),
GeneratedToken::alone(','),
GeneratedToken::word(ATTACHMENT_LOCAL),
GeneratedToken::alone(','),
];
arguments.extend(provenance(emitter)?);
arguments.push(GeneratedToken::alone(','));
body.extend(vocabulary::road(
&[
HarnessName::Descriptor,
HarnessName::BindingType,
HarnessName::Bound,
],
arguments,
)?);
Ok(vec![group(GeneratedDelimiter::Brace, body)?])
}
pub fn named_clause(name: &Name) -> Result<Vec<GeneratedToken>, Overflow> {
Ok(vec![
GeneratedToken::word(HarnessName::Named.spelling()),
group(
GeneratedDelimiter::Parenthesis,
text_pair(name.namespace(), name.stem()),
)?,
])
}
pub fn suite_group(seated: &SuiteGroup, emitter: Emitter) -> Result<Vec<GeneratedToken>, Overflow> {
let mut rows: Vec<GeneratedToken> = Vec::new();
for declared in seated.rows() {
rows.push(GeneratedToken::word(declared.lens().spelling()));
rows.push(GeneratedToken::alone(':'));
rows.extend(row_expression(declared, seated.suite(), emitter)?);
rows.push(GeneratedToken::alone(','));
}
let mut tokens = vec![
GeneratedToken::word(HarnessWord::Suite.spelling()),
GeneratedToken::word(seated.seat().spelling()),
];
tokens.extend(named_clause(seated.suite())?);
tokens.push(group(GeneratedDelimiter::Brace, rows)?);
Ok(tokens)
}
#[must_use]
pub fn matched_clauses(payload: &Trials) -> Vec<GeneratedToken> {
let mut clauses: Vec<GeneratedToken> = Vec::new();
for host in [
HarnessWord::Invocation,
HarnessWord::Target,
HarnessWord::Clock,
] {
clauses.extend(crate::support::matched_clause(host.spelling(), "expr"));
}
for seated in payload.groups() {
for declared in seated.rows() {
let lens = declared.lens().spelling();
for seat in [
HarnessWord::SubjectRevision,
HarnessWord::CheckRevision,
HarnessWord::Call,
] {
clauses.extend(crate::support::matched_clause(
&attachment_metavariable(lens, seat),
"expr",
));
}
}
}
clauses
}
pub fn stamped_module(payload: &Trials, emitter: Emitter) -> Result<Vec<GeneratedToken>, Overflow> {
let mut body = vocabulary::key(HarnessWord::Provenance);
body.push(GeneratedToken::word(HarnessWord::Produced.spelling()));
body.push(group(
GeneratedDelimiter::Parenthesis,
text_pair(emitter.namespace, emitter.producer),
)?);
body.push(GeneratedToken::word(HarnessWord::Against.spelling()));
body.extend(table_schema_identity()?);
body.push(GeneratedToken::alone(','));
for host in [
HarnessWord::Invocation,
HarnessWord::Target,
HarnessWord::Clock,
] {
body.extend(vocabulary::key(host));
body.extend(metavariable(host.spelling()));
body.push(GeneratedToken::alone(','));
}
for seated in payload.groups() {
body.extend(suite_group(seated, emitter)?);
}
let mut tokens = declared_reach_tokens(Visibility::Crate)?;
tokens.push(GeneratedToken::word("mod"));
tokens.push(GeneratedToken::word(payload.module().spelling()));
tokens.extend(named_clause(payload.table())?);
tokens.push(group(GeneratedDelimiter::Brace, body)?);
Ok(tokens)
}