use crate::{
error::Error,
model::{
annotations::{Annotation, AnnotationProperty, HasAnnotations},
constraints::{ConstraintBody, ControlledLanguageString, FormalConstraint},
definitions::{
DatatypeDef, Definition, DimensionDef, DimensionIdentity, DimensionParent, EntityDef,
EnumDef, EventDef, PropertyDef, RdfDef, SourceEntity, StructureDef, TypeVariant,
UnionDef, ValueVariant,
},
identifiers::IdentifierReference,
members::{Member, MemberDef, MemberKind},
modules::{Import, ImportStatement, MemberImport, Module, ModuleImport},
HasBody, HasOptionalBody,
},
};
use tracing::info;
pub trait SimpleModuleVisitor {
const INCLUDE_NESTED: Result<bool, Error> = Ok(true);
const NO_NESTED: Result<bool, Error> = Ok(false);
fn module_start(&mut self, _thing: &Module) -> Result<bool, Error> {
info!("SimpleModuleWalker::module_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn module_end(&mut self, _thing: &Module) -> Result<(), Error> {
info!("SimpleModuleWalker::module_end(..) -- skipped");
Ok(())
}
fn import_statement_start(&mut self, _thing: &ImportStatement) -> Result<bool, Error> {
info!("SimpleModuleWalker::import_statement_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn import_statement_end(&mut self, _thing: &ImportStatement) -> Result<(), Error> {
info!("SimpleModuleWalker::import_statement_end(..) -- skipped");
Ok(())
}
fn module_import(&mut self, _thing: &ModuleImport) -> Result<(), Error> {
info!("SimpleModuleWalker::module_import(..) -- skipped");
Ok(())
}
fn member_import(&mut self, _thing: &MemberImport) -> Result<(), Error> {
info!("SimpleModuleWalker::member_import(..) -- skipped");
Ok(())
}
fn annotation_start(&mut self, _thing: &Annotation) -> Result<bool, Error> {
info!("SimpleModuleWalker::annotation_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn annotation_end(&mut self, _thing: &Annotation) -> Result<(), Error> {
info!("SimpleModuleWalker::annotation_end(..) -- skipped");
Ok(())
}
fn annotation_property(&mut self, _thing: &AnnotationProperty) -> Result<(), Error> {
info!("SimpleModuleWalker::annotation_property(..) -- skipped");
Ok(())
}
fn informal_constraint(&mut self, _thing: &ControlledLanguageString) -> Result<(), Error> {
info!("SimpleModuleWalker::informal_constraint(..) -- skipped");
Ok(())
}
fn formal_constraint(&mut self, _thing: &FormalConstraint) -> Result<(), Error> {
info!("SimpleModuleWalker::formal_constraint(..) -- skipped");
Ok(())
}
fn definition_start(&mut self, _thing: &Definition) -> Result<bool, Error> {
info!("SimpleModuleWalker::definition_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn definition_end(&mut self, _thing: &Definition) -> Result<(), Error> {
info!("SimpleModuleWalker::definition_end(..) -- skipped");
Ok(())
}
fn datatype_start(&mut self, _thing: &DatatypeDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::datatype_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn datatype_end(&mut self, _thing: &DatatypeDef) -> Result<(), Error> {
info!("SimpleModuleWalker::datatype_end(..) -- skipped");
Ok(())
}
fn dimension_start(&mut self, _thing: &DimensionDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::dimension_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn dimension_end(&mut self, _thing: &DimensionDef) -> Result<(), Error> {
info!("SimpleModuleWalker::dimension_end(..) -- skipped");
Ok(())
}
fn dimension_identity_start(&mut self, _thing: &DimensionIdentity) -> Result<bool, Error> {
info!("SimpleModuleWalker::dimension_identity_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn dimension_identity_end(&mut self, _thing: &DimensionIdentity) -> Result<(), Error> {
info!("SimpleModuleWalker::dimension_identity_end(..) -- skipped");
Ok(())
}
fn source_entity_start(&mut self, _thing: &SourceEntity) -> Result<bool, Error> {
info!("SimpleModuleWalker::source_entity_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn source_entity_end(&mut self, _thing: &SourceEntity) -> Result<(), Error> {
info!("SimpleModuleWalker::source_entity_end(..) -- skipped");
Ok(())
}
fn entity_start(&mut self, _thing: &EntityDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::import(..) -- skipped");
Self::INCLUDE_NESTED
}
fn entity_end(&mut self, _thing: &EntityDef) -> Result<(), Error> {
info!("SimpleModuleWalker::import(..) -- skipped");
Ok(())
}
fn enum_start(&mut self, _thing: &EnumDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::enum_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn enum_end(&mut self, _thing: &EnumDef) -> Result<(), Error> {
info!("SimpleModuleWalker::enum_end(..) -- skipped");
Ok(())
}
fn event_start(&mut self, _thing: &EventDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::event_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn event_end(&mut self, _thing: &EventDef) -> Result<(), Error> {
info!("SimpleModuleWalker::event_end(..) -- skipped");
Ok(())
}
fn property_start(&mut self, _thing: &PropertyDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::property_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn property_end(&mut self, _thing: &PropertyDef) -> Result<(), Error> {
info!("SimpleModuleWalker::property_end(..) -- skipped");
Ok(())
}
fn rdf_start(&mut self, _thing: &RdfDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::rdf_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn rdf_end(&mut self, _thing: &RdfDef) -> Result<(), Error> {
info!("SimpleModuleWalker::rdf_end(..) -- skipped");
Ok(())
}
fn structure_start(&mut self, _thing: &StructureDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::structure_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn structure_end(&mut self, _thing: &StructureDef) -> Result<(), Error> {
info!("SimpleModuleWalker::structure_end(..) -- skipped");
Ok(())
}
fn union_start(&mut self, _thing: &UnionDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::union_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn union_end(&mut self, _thing: &UnionDef) -> Result<(), Error> {
info!("SimpleModuleWalker::union_end(..) -- skipped");
Ok(())
}
fn member_start(&mut self, _thing: &Member) -> Result<bool, Error> {
info!("SimpleModuleWalker::member_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn member_end(&mut self, _thing: &Member) -> Result<(), Error> {
info!("SimpleModuleWalker::member_end(..) -- skipped");
Ok(())
}
fn identity_member_start(&mut self, _thing: &Member) -> Result<bool, Error> {
info!("SimpleModuleWalker::identity_member_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn identity_member_end(&mut self, _thing: &Member) -> Result<(), Error> {
info!("SimpleModuleWalker::identity_member_end(..) -- skipped");
Ok(())
}
fn dimension_parent_start(&mut self, _thing: &DimensionParent) -> Result<bool, Error> {
info!("SimpleModuleWalker::dimension_parent_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn dimension_parent_end(&mut self, _thing: &DimensionParent) -> Result<(), Error> {
info!("SimpleModuleWalker::dimension_parent_end(..) -- skipped");
Ok(())
}
fn member_definition_start(&mut self, _thing: &MemberDef) -> Result<bool, Error> {
info!("SimpleModuleWalker::member_definition_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn member_definition_end(&mut self, _thing: &MemberDef) -> Result<(), Error> {
info!("SimpleModuleWalker::member_definition_end(..) -- skipped");
Ok(())
}
fn property_reference_start(&mut self, _thing: &IdentifierReference) -> Result<bool, Error> {
info!("SimpleModuleWalker::property_reference_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn property_reference_end(&mut self, _thing: &IdentifierReference) -> Result<(), Error> {
info!("SimpleModuleWalker::property_reference_end(..) -- skipped");
Ok(())
}
fn value_variant_start(&mut self, _thing: &ValueVariant) -> Result<bool, Error> {
info!("SimpleModuleWalker::value_variant_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn value_variant_end(&mut self, _thing: &ValueVariant) -> Result<(), Error> {
info!("SimpleModuleWalker::value_variant_end(..) -- skipped");
Ok(())
}
fn type_variant_start(&mut self, _thing: &TypeVariant) -> Result<bool, Error> {
info!("SimpleModuleWalker::type_variant_start(..) -- skipped");
Self::INCLUDE_NESTED
}
fn type_variant_end(&mut self, _thing: &TypeVariant) -> Result<(), Error> {
info!("SimpleModuleWalker::type_variant_end(..) -- skipped");
Ok(())
}
}
macro_rules! walk_annotations {
($walker: expr, $iterator: expr, $visit_annotations: expr) => {
if $visit_annotations {
for annotation in $iterator {
if $walker.annotation_start(annotation)? {
match annotation {
Annotation::Property(property) => {
$walker.annotation_property(&property)?;
}
Annotation::Constraint(cons) => match cons.body() {
ConstraintBody::Informal(constraint) => {
$walker.informal_constraint(&constraint)?;
}
ConstraintBody::Formal(constraint) => {
$walker.formal_constraint(&constraint)?;
}
},
}
$walker.annotation_end(annotation)?;
}
}
}
};
}
pub fn walk_module_simple(
module: &Module,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
visit_members_and_variants: bool,
) -> Result<(), Error> {
if walker.module_start(module)? {
for import in module.imports() {
if walker.import_statement_start(import)? {
for import in import.imports() {
match import {
Import::Module(v) => walker.module_import(v)?,
Import::Member(v) => walker.member_import(v)?,
}
}
walker.import_statement_end(import)?;
}
}
walk_annotations!(walker, module.annotations(), visit_annotations);
for type_def in module.definitions() {
if walker.definition_start(type_def)? {
match &type_def {
Definition::Datatype(def) => walk_datatype_def(def, walker, visit_annotations)?,
Definition::Dimension(def) => walk_dimension_def(
def,
walker,
visit_annotations,
visit_members_and_variants,
)?,
Definition::Entity(def) => {
walk_entity_def(def, walker, visit_annotations, visit_members_and_variants)?
}
Definition::Enum(def) => {
walk_enum_def(def, walker, visit_annotations, visit_members_and_variants)?
}
Definition::Event(def) => {
walk_event_def(def, walker, visit_annotations, visit_members_and_variants)?
}
Definition::Property(def) => walk_property_def(def, walker)?,
Definition::Rdf(def) => walk_rdf_def(def, walker, visit_annotations)?,
Definition::Structure(def) => walk_structure_def(
def,
walker,
visit_annotations,
visit_members_and_variants,
)?,
Definition::TypeClass(_) => todo!(),
Definition::Union(def) => {
walk_union_def(def, walker, visit_annotations, visit_members_and_variants)?
}
}
walker.definition_end(type_def)?;
}
}
walker.module_end(module)?;
}
Ok(())
}
fn walk_datatype_def(
thing: &DatatypeDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
if walker.datatype_start(thing)? {
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
}
walker.datatype_end(thing)?;
}
Ok(())
}
fn walk_dimension_def(
thing: &DimensionDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
visit_members_and_variants: bool,
) -> Result<(), Error> {
if walker.dimension_start(thing)? {
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
walk_dimension_identity(body.identity(), walker, visit_annotations)?;
if visit_members_and_variants {
for parent in body.parents() {
walk_dimension_parent(parent, walker)?;
}
for member in body.members() {
walk_member(member, walker, visit_annotations)?;
}
}
}
walker.dimension_end(thing)?;
}
Ok(())
}
fn walk_dimension_identity(
thing: &DimensionIdentity,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
if walker.dimension_identity_start(thing)? {
match thing {
DimensionIdentity::Source(v) => walk_source_entity(v, walker),
DimensionIdentity::Identity(v) => walk_identity_member(v, walker, visit_annotations),
}?;
walker.dimension_identity_end(thing)?;
}
Ok(())
}
fn walk_source_entity(
thing: &SourceEntity,
walker: &mut impl SimpleModuleVisitor,
) -> Result<(), Error> {
if walker.source_entity_start(thing)? {
walker.source_entity_end(thing)?;
}
Ok(())
}
fn walk_dimension_parent(
thing: &DimensionParent,
walker: &mut impl SimpleModuleVisitor,
) -> Result<(), Error> {
if walker.dimension_parent_start(thing)? {
walker.dimension_parent_end(thing)?;
}
Ok(())
}
fn walk_entity_def(
thing: &EntityDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
visit_members_and_variants: bool,
) -> Result<(), Error> {
if walker.entity_start(thing)? {
if let Some(body) = thing.body() {
walk_identity_member(body.identity(), walker, visit_annotations)?;
walk_annotations!(walker, body.annotations(), visit_annotations);
if visit_members_and_variants {
for member in body.members() {
walk_member(member, walker, visit_annotations)?;
}
}
}
walker.entity_end(thing)?;
}
Ok(())
}
fn walk_enum_def(
thing: &EnumDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
visit_members_and_variants: bool,
) -> Result<(), Error> {
if walker.enum_start(thing)? {
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
if visit_members_and_variants {
for variant in body.variants() {
walk_value_variant(variant, walker, visit_annotations)?;
}
}
}
walker.enum_end(thing)?;
}
Ok(())
}
fn walk_event_def(
thing: &EventDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
visit_members_and_variants: bool,
) -> Result<(), Error> {
if walker.event_start(thing)? {
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
if visit_members_and_variants {
for member in body.members() {
walk_member(member, walker, visit_annotations)?;
}
}
}
walker.event_end(thing)?;
}
Ok(())
}
fn walk_property_def(
thing: &PropertyDef,
walker: &mut impl SimpleModuleVisitor,
) -> Result<(), Error> {
if walker.property_start(thing)? {
let defn = thing.member_def();
if walker.member_definition_start(defn)? {
walker.member_definition_end(defn)?;
}
walker.property_end(thing)?;
}
Ok(())
}
fn walk_rdf_def(
thing: &RdfDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
if walker.rdf_start(thing)? {
walk_annotations!(walker, thing.body().annotations(), visit_annotations);
walker.rdf_end(thing)?;
}
Ok(())
}
fn walk_structure_def(
thing: &StructureDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
visit_members_and_variants: bool,
) -> Result<(), Error> {
if walker.structure_start(thing)? {
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
if visit_members_and_variants {
for member in body.members() {
walk_member(member, walker, visit_annotations)?;
}
}
}
walker.structure_end(thing)?;
}
Ok(())
}
fn walk_union_def(
thing: &UnionDef,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
visit_members_and_variants: bool,
) -> Result<(), Error> {
if walker.union_start(thing)? {
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
if visit_members_and_variants {
for variant in body.variants() {
walk_type_variant(variant, walker, visit_annotations)?;
}
}
}
walker.union_end(thing)?;
}
Ok(())
}
fn walk_member(
thing: &Member,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
if walker.member_start(thing)? {
walk_member_common(thing, walker, visit_annotations)?;
walker.member_end(thing)?;
}
Ok(())
}
fn walk_identity_member(
thing: &Member,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
if walker.identity_member_start(thing)? {
walk_member_common(thing, walker, visit_annotations)?;
walker.identity_member_end(thing)?;
}
Ok(())
}
fn walk_member_common(
thing: &Member,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
match thing.kind() {
MemberKind::Reference(v) => {
if walker.property_reference_start(v)? {
walker.property_reference_end(v)?;
}
}
MemberKind::Definition(v) => {
if walker.member_definition_start(v)? {
if let Some(body) = v.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
}
walker.member_definition_end(v)?;
}
}
}
Ok(())
}
fn walk_value_variant(
thing: &ValueVariant,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
walker.value_variant_start(thing)?;
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
}
walker.value_variant_end(thing)
}
fn walk_type_variant(
thing: &TypeVariant,
walker: &mut impl SimpleModuleVisitor,
visit_annotations: bool,
) -> Result<(), Error> {
walker.type_variant_start(thing)?;
if let Some(body) = thing.body() {
walk_annotations!(walker, body.annotations(), visit_annotations);
}
walker.type_variant_end(thing)
}