1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use crate::tao::callbacks::implements;
use crate::tao::perspective::KnowledgeGraphNode;
use std::cell::Cell;
use zamm_yin::node_wrappers::CommonNodeTrait;
use zamm_yin::tao::archetype::*;
use zamm_yin::tao::form::FormTrait;
use zamm_yin::tao::relation::attribute::Attribute;

thread_local! {
    static IMPORT_IN_PROGRESS: Cell<bool> = Cell::new(false);
}

/// Returns whether or not we're currently in the process of importing another file.
pub fn import_in_progress() -> bool {
    IMPORT_IN_PROGRESS.with(|i| i.get())
}

fn mark_import(status: bool) {
    IMPORT_IN_PROGRESS.with(|i| i.set(status));
}

/// Defines a new concept with the given name.
#[macro_export]
macro_rules! define {
    ($name:ident) => {
        let mut $name = Tao::archetype().individuate_as_archetype();
        $name.set_internal_name_str(stringify!($name));
        {
            let mut kgn = zamm_yang::tao::perspective::KnowledgeGraphNode::from($name.id());
            if zamm_yang::helper::import_in_progress() {
                kgn.mark_imported();
            } else {
                kgn.mark_newly_defined();
            }
        }
    };
    ($name:ident, $doc:expr) => {
        define!($name);
        $name.implement_with_doc($doc);
    };
}

/// Defines a module for the given concept.
#[macro_export]
macro_rules! module {
    ($name:expr, $doc:expr) => {
        $name.impl_mod($doc)
    };
    ($name:expr, $doc:expr, [$($extension:expr),*]) => {
        {
            let mut new_mod = $name.impl_mod($doc);
            $(
                new_mod.has_extension($extension);
            )*
        }
    };
}

/// Defines a new concept as a child of the given parent type, defined within the current context.
#[macro_export]
macro_rules! define_child {
    ($name:ident, $parent:expr) => {
        define!($name);
        $name.add_parent($parent.into());
    };
    ($name:ident, $parent:expr, $doc:expr) => {
        define!($name, $doc);
        $name.add_parent($parent.into());
    };
}

/// Defines a new flag, and add it as a property of the owner.
#[macro_export]
macro_rules! add_flag {
    ($name:ident, $owner:ident, $doc:expr, $dual_doc:expr) => {
        add_flag!(
            $name <= zamm_yang::tao::relation::flag::Flag::archetype(),
            $owner,
            $doc,
            $dual_doc
        );
    };
    ($name:ident <= $parent:expr, $owner:ident, $doc:expr, $dual_doc:expr) => {
        define_child!($name, $parent);
        zamm_yang::tao::archetype::AttributeArchetype::from($name.id()).set_owner_archetype($owner);
        $owner.add_flag($name);
        {
            let mut new_impl = $name.implement_with_doc($doc);
            new_impl.dual_document($dual_doc);
        }
    };
}

/// Defines a new attribute, and add it as a property of the owner.
#[macro_export]
macro_rules! add_attr {
    ($name:ident, $owner:expr, $value:expr, $doc:expr, $dual_doc:expr) => {
        add_attr!(
            $name <= zamm_yang::tao::relation::attribute::Attribute::archetype(),
            $owner,
            $value,
            $doc,
            $dual_doc
        );
    };
    ($name:ident <= $parent:expr, $owner:expr, $value:expr, $doc:expr, $dual_doc:expr) => {
        define_child!($name, $parent);
        {
            let mut new_aa = zamm_yang::tao::archetype::AttributeArchetype::from($name.id());
            if $owner != zamm_yang::tao::Tao::archetype() {
                new_aa.set_owner_archetype($owner);
            }
            if $value != zamm_yang::tao::Tao::archetype() {
                new_aa.set_value_archetype($value);
            }
            $owner.add_attribute(new_aa);
            let mut new_impl = $name.implement_with_doc($doc);
            new_impl.dual_document($dual_doc);
        }
    };
}

/// Convenience function to convert an `Archetype` to an `AttributeArchetype`.
pub fn aa(archetype: Archetype) -> AttributeArchetype {
    if !(KnowledgeGraphNode::from(archetype.id()).is_attribute_analogue()
        || archetype.has_parent(Attribute::archetype().into())
        || archetype
            .parents()
            .iter()
            .any(|a| KnowledgeGraphNode::from(a.id()).is_attribute_analogue()))
    {
        // currently catches Relation, which is not an attribute but still deserves to have its
        // owner archetype set
        println!("Warning: {:?} is not known to be an attribute.", archetype);
    }
    AttributeArchetype::from(archetype.id())
}

/// Start interpreting new information as imported. New concepts will not be marked as new, but
/// instead as imported.
pub fn start_imports() {
    mark_import(true);
}

/// Mark all concepts introduced thus far as imported ones. Imports are informational-only and will
/// not be acted on.
pub fn end_imports() {
    mark_import(false);
    for i in implements() {
        KnowledgeGraphNode::from(i.id()).mark_imported();
    }
}

/// Backwards compatibility trait to handle API changes for this yang-0.x.* branch.
pub trait BackwardsCompatibility {}