diff options
-rw-r--r-- | starts/meaning-vm/level-0/baseref.hpp | 22 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/concept.cpp | 45 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/concept.hpp | 26 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/errors.hpp | 24 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/memorystore.cpp | 2 |
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; } |