summaryrefslogtreecommitdiff
path: root/intellect-framework-from-internet/starts/meaning-vm/level-0/concept.cpp
blob: 66e5af161895cf7835d7df59b3c0ff7298973ea5 (plain)
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
#include "concept.hpp"
#include "errors.hpp"

using namespace intellect::level0;

#define selfref const_cast<concept*>(&self)

concept* concept::id()
{
	return this;
}

void concept::link(concept* type, concept* target)
{
	if (type == 0 || target == 0) { throw null_reference(); }
	links.insert({type, target});
}

bool concept::crucial(concept* type, concept* target)
{
	auto ls = links.equal_range(type);
	bool wascrucial = false;
	bool wasnotcrucial = false;
	for (auto l = ls.first; l != ls.second; ++ l) {
		if (l->second == target) {
			if (crucialparts.count(l)) { wascrucial = true; }
			else { wasnotcrucial = true; }
		}
	}
	if (wascrucial && wasnotcrucial) { throw link_type_not_unique(selfref, type); }
	if ((!wascrucial) && (!wasnotcrucial)) { throw no_such_link_type(selfref, type); }
	return wascrucial;
}

void concept::setcrucial(concept* type, concept* target)
{
	auto ls = links.equal_range(type);
	for (auto l = ls.first; l != ls.second; ++ l) {
		if (l->second == target) {
			if (!crucialparts.count(l)) {
				setcrucial(l);
				return;
			}
		}
	}
	throw no_such_link_type(selfref, type);
}

void concept::unlink(concept* type, concept* target)
{
	auto ls = links.equal_range(type);
	bool wascrucial = false;
	for (auto l = ls.first; l != ls.second; ++ l) {
		if (l->second == target) {
			if (crucialparts.count(l)) { wascrucial = true; continue; }
			links.erase(l);
			return;
		}
	}
	if (wascrucial) { throw crucial_link_type_target(selfref, type, target); }
       	throw no_such_link_type_target(selfref, type, target);
}

void concept::unlink(concept* type)
{
	auto ls = links.equal_range(type);
	if (ls.first == ls.second) {
		throw no_such_link_type(selfref, type);
	}
	auto mid = ls.first;
	++ mid;
	if (mid != ls.second) {
		throw link_type_not_unique(selfref, type);
	}
	unlink(ls.first);
}

void concept::unlink(decltype(links)::iterator it)
{
	if (crucialparts.count(it)) {
		throw crucial_link_type_target(selfref, it->first, it->second);
	}
	links.erase(it++);
}

bool concept::linked(concept* type) const
{
	return links.count(type) > 0;
}

bool concept::linked(concept* type, concept* target) const
{
	for (concept* t : getAll(type)) {
		if (t == target) {
			return true;
		}
	}
	return false;
}

concept::array concept::getAll(concept* type) const
{
	array ret;
	for (
		auto range = links.equal_range(type);
		range.first != range.second;
		++ range.first
	) { 
		ret.emplace_back(range.first->second);
	}
	return ret;
}

concept* concept::get(concept* type) const
{
	auto result = links.equal_range(type);
	if (result.first == result.second) {
		throw no_such_link_type(selfref, type);
	}
	auto test = result.first;
	++ test;
	if (test != result.second) {
		throw link_type_not_unique(selfref, type);
	}
	return result.first->second;
}

void concept::set(concept* type, concept* target)
{
	if (linked(type)) {
		unlink(type);
	}
	link(type, target);
}