use super::{
IntoChildNodes, Node, Rule, RuleMatcher, define::type_::visit_type_capability, type_::visit_label, visit_kind,
};
use crate::{
common::{Spanned, error::TypeQLError},
parser::{annotation::visit_annotations, define::function::visit_definition_function, type_::visit_label_scoped},
query::schema::Redefine,
schema::definable::{Definable, RoleTypeRename, Type, TypeRename},
};
pub(super) fn visit_query_redefine(node: Node<'_>) -> Redefine {
debug_assert_eq!(node.as_rule(), Rule::query_redefine);
let span = node.span();
let redefinables = node.into_children().skip_expected(Rule::REDEFINE).map(visit_redefinable).collect();
Redefine::new(span, redefinables)
}
fn visit_redefinable(node: Node<'_>) -> Definable {
debug_assert_eq!(node.as_rule(), Rule::redefinable);
let child = node.into_child();
match child.as_rule() {
Rule::redefinable_label => visit_redefinable_label(child),
Rule::redefinable_type => visit_redefinable_type(child),
Rule::definition_function => Definable::Function(visit_definition_function(child)),
_ => unreachable!("{}", TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }),
}
}
fn visit_redefinable_label(node: Node<'_>) -> Definable {
debug_assert_eq!(node.as_rule(), Rule::redefinable_label);
let span = node.span();
let mut children = node.into_children();
let first_child = children.consume_any();
match first_child.as_rule() {
Rule::kind => {
let kind = Some(visit_kind(first_child));
let from = visit_label(children.consume_expected(Rule::label));
children.skip_expected(Rule::LABEL);
let to = visit_label(children.consume_expected(Rule::label));
Definable::TypeRename(TypeRename { kind, from, to, span })
}
Rule::label => {
let kind = None;
let from = visit_label(first_child);
children.skip_expected(Rule::LABEL);
let to = visit_label(children.consume_expected(Rule::label));
Definable::TypeRename(TypeRename { kind, from, to, span })
}
Rule::label_scoped => {
let from = visit_label_scoped(first_child);
children.skip_expected(Rule::LABEL);
let to = visit_label(children.consume_expected(Rule::label));
Definable::RoleTypeRename(RoleTypeRename { from, to, span })
}
_ => {
unreachable!("{}", TypeQLError::IllegalGrammar { input: first_child.as_str().to_owned() })
}
}
}
fn visit_redefinable_type(node: Node<'_>) -> Definable {
let span = node.span();
let mut children = node.into_children();
let kind = children.try_consume_expected(Rule::kind).map(visit_kind);
let label = visit_label(children.consume_expected(Rule::label));
let annotations = children.try_consume_expected(Rule::annotations).map(visit_annotations).unwrap_or_default();
let capabilities = children
.try_consume_expected(Rule::type_capability)
.map(|node| vec![visit_type_capability(node)])
.unwrap_or_default();
debug_assert_eq!(children.try_consume_any(), None);
Definable::TypeDeclaration(Type::new(span, kind, label, annotations, capabilities))
}