summaryrefslogtreecommitdiff
path: root/starts/meaning-vm/level-0
diff options
context:
space:
mode:
Diffstat (limited to 'starts/meaning-vm/level-0')
-rw-r--r--starts/meaning-vm/level-0/baseref.hpp22
-rw-r--r--starts/meaning-vm/level-0/concept.cpp45
-rw-r--r--starts/meaning-vm/level-0/concept.hpp26
-rw-r--r--starts/meaning-vm/level-0/errors.hpp24
-rw-r--r--starts/meaning-vm/level-0/memorystore.cpp2
5 files changed, 115 insertions, 4 deletions
diff --git a/starts/meaning-vm/level-0/baseref.hpp b/starts/meaning-vm/level-0/baseref.hpp
index 9244492..b6e98e8 100644
--- a/starts/meaning-vm/level-0/baseref.hpp
+++ b/starts/meaning-vm/level-0/baseref.hpp
@@ -13,8 +13,8 @@ namespace level0 {
template <typename ref>
class baseref
{
- struct array; struct links_t;
public:
+ struct array; struct links_t;
baseref(concept *p)
: p(p)
{
@@ -63,6 +63,9 @@ public:
T& val() { return p->val<T>(); }
template <typename T>
void val(T const & v) { p->val<T>(v); }
+ bool hasval() { return p->hasval(); }
+ template <typename T>
+ bool hasvalof() { return p->hasvalof<T>(); }
operator concept*() const { return p; }
concept*& ptr() { return p; }
@@ -91,9 +94,15 @@ public:
operator level9::ref &() { return *reinterpret_cast<level9::ref*>(this); }
bool operator==(ref const & other) const { return self.p == other.p; }
- bool operator!=(ref const & other) const { return self.p == other.p; }
+ bool operator!=(ref const & other) const { return self.p != other.p; }
bool operator<(ref const & other) const { return self.p < other.p; }
+ bool crucial() { return self.p->crucial(); }
+ bool crucial(ref type, ref target) { return self.p->crucial(type.p, target.p); }
+
+ void setcrucial() { self.p->setcrucial(); }
+ void setcrucial(ref type, ref target) { self.p->setcrucial(type.p, target.p); }
+
protected:
concept * p;
@@ -107,16 +116,21 @@ private:
mutit & operator++() { ++ self.it; return self; }
mutit operator++(int i) { return self.it.operator++(i); }
+ mutit & operator--() { -- self.it; return self; }
+ mutit operator--(int i) { return self.it.operator--(i); }
bool operator==(mutit const & other) const { return self.it == other.it; }
bool operator!=(mutit const & other) const { return self.it != other.it; }
val & operator*() { return *(val*)&self.it.operator*(); }
val * operator->() { return (val*)self.it.operator->(); }
+ It & underlying() { return it; }
+
private:
It it;
};
+public:
struct array
{
using iterator = mutated_it<ref,typename concept::array::iterator>;
@@ -134,6 +148,10 @@ private:
decltype(concept::links) & links;
};
+
+ void unlink(typename links_t::iterator & it) { p->unlink(it.underlying()); }
+ bool crucial(typename links_t::iterator it) { return self.p->crucial(it.underlying()); }
+ void setcrucial(typename links_t::iterator it) { self.p->setcrucial(it.underlying()); }
};
template <typename ref>
diff --git a/starts/meaning-vm/level-0/concept.cpp b/starts/meaning-vm/level-0/concept.cpp
index 0661edd..373b3b7 100644
--- a/starts/meaning-vm/level-0/concept.cpp
+++ b/starts/meaning-vm/level-0/concept.cpp
@@ -16,16 +16,49 @@ void concept::link(concept* type, concept* target)
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;
}
}
- throw no_such_link_type_target(selfref, type, target);
+ if (wascrucial) { throw crucial_link_type_target(selfref, type, target); }
+ throw no_such_link_type_target(selfref, type, target);
}
void concept::unlink(concept* type)
@@ -39,7 +72,15 @@ void concept::unlink(concept* type)
if (mid != ls.second) {
throw link_type_not_unique(selfref, type);
}
- links.erase(ls.first);
+ 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
diff --git a/starts/meaning-vm/level-0/concept.hpp b/starts/meaning-vm/level-0/concept.hpp
index d42d36b..e885ccf 100644
--- a/starts/meaning-vm/level-0/concept.hpp
+++ b/starts/meaning-vm/level-0/concept.hpp
@@ -4,6 +4,7 @@
#include <any>
#include <map>
+#include <unordered_set>
#include <vector>
namespace intellect {
@@ -23,6 +24,14 @@ struct concept
void link(concept* type, concept* target);
void unlink(concept* type, concept* target);
void unlink(concept* type);
+ void unlink(decltype(links)::iterator & it);
+
+ bool crucial() { return iscrucial || crucialparts.size(); }
+ bool crucial(concept* type, concept* target);
+ bool crucial(decltype(links)::iterator it) { return crucialparts.count(it); }
+ void setcrucial() { iscrucial = true; }
+ void setcrucial(concept* type, concept* target);
+ void setcrucial(decltype(links)::iterator it) { crucialparts.insert(it); }
bool linked(concept* type) const;
bool linked(concept* type, concept* target) const;
@@ -41,6 +50,23 @@ struct concept
template <typename T>
void val(T const & v) { data = v; }
+
+ bool hasval() { return data.has_value(); }
+
+ template <typename T>
+ bool hasvalof() { return hasval() && data.type() == typeid(T); }
+
+private:
+ // for permanence
+ bool iscrucial;
+ struct linksit_hash
+ {
+ size_t operator()(decltype(links)::iterator const &it) const
+ {
+ return std::hash<decltype(&*it)>()(&*it);
+ }
+ };
+ std::unordered_set<decltype(links)::iterator, linksit_hash> crucialparts;
};
}
diff --git a/starts/meaning-vm/level-0/errors.hpp b/starts/meaning-vm/level-0/errors.hpp
index d46eef7..e599261 100644
--- a/starts/meaning-vm/level-0/errors.hpp
+++ b/starts/meaning-vm/level-0/errors.hpp
@@ -32,6 +32,30 @@ struct no_such_link_type_target : public std::out_of_range
concept* const target;
};
+struct crucial_link_type_target : public std::out_of_range
+{
+ crucial_link_type_target(concept* source, concept* type, concept* target)
+ : std::out_of_range("concept part is crucial"),
+ source(source),
+ type(type),
+ target(type)
+ { }
+
+ concept* const source;
+ concept* const type;
+ concept* const target;
+};
+
+struct crucial_concept : public std::invalid_argument
+{
+ crucial_concept(concept* topic)
+ : std::invalid_argument("concept is crucial"),
+ topic(topic)
+ { }
+
+ concept* const topic;
+};
+
struct link_type_not_unique : public std::invalid_argument
{
link_type_not_unique(concept* source, concept* type)
diff --git a/starts/meaning-vm/level-0/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp
index 04aadd5..1d9e9f6 100644
--- a/starts/meaning-vm/level-0/memorystore.cpp
+++ b/starts/meaning-vm/level-0/memorystore.cpp
@@ -89,6 +89,7 @@ static concept* referenced(ref r, concept* source = 0) {
void basic_dealloc(ref r)
{
+ if (r.crucial()) { throw crucial_concept(r); }
auto it = index().find(r);
if (it == index().end()) { throw no_such_concept(r); }
@@ -106,6 +107,7 @@ void dealloc_from(ref source)
auto ours = source.getAll(concepts::allocates());
for (auto allocation : ours) {
+ if (allocation.crucial()) { throw crucial_concept(allocation); }
source.unlink(concepts::allocates(), allocation);
allocation.unlink(concepts::allocator(), source);
if (allocation.linked(concepts::allocator())) { continue; }