diff options
Diffstat (limited to 'starts')
-rw-r--r-- | starts/meaning-vm/level-0/baseref.hpp | 4 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/concept.cpp | 1 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/memorystore.cpp | 152 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/memorystore.hpp | 41 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/ref.cpp | 4 | ||||
-rw-r--r-- | starts/meaning-vm/level-1/baseref.hpp | 2 | ||||
-rw-r--r-- | starts/meaning-vm/level-1/concepts.cpp | 1 | ||||
-rw-r--r-- | starts/meaning-vm/level-1/concepts.hpp | 1 | ||||
-rw-r--r-- | starts/meaning-vm/level-1/funcs.cpp | 27 | ||||
-rw-r--r-- | starts/meaning-vm/level-1/funcs.hpp | 2 | ||||
-rw-r--r-- | starts/meaning-vm/level-1/sugar.cpp | 9 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/funcs.cpp | 2 | ||||
-rw-r--r-- | starts/meaning-vm/level0.cpp | 38 | ||||
-rw-r--r-- | starts/meaning-vm/level1.cpp | 7 | ||||
-rw-r--r-- | starts/meaning-vm/makefile | 2 |
15 files changed, 229 insertions, 64 deletions
diff --git a/starts/meaning-vm/level-0/baseref.hpp b/starts/meaning-vm/level-0/baseref.hpp index fbb7a28..69880c8 100644 --- a/starts/meaning-vm/level-0/baseref.hpp +++ b/starts/meaning-vm/level-0/baseref.hpp @@ -57,7 +57,7 @@ public: template <typename T> T& vget(ref const & type) const { return p->vget<T>(type.p); } template <typename T> - void vset(ref const & type, T const & v) { p->set(type.p, level0::alloc(v)); } + void vset(ref const & type, T const & v) { p->set(type.p, level0::alloc(self, v)); } template <typename T> T& val() { return p->val<T>(); } @@ -100,7 +100,7 @@ private: 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->(); } + val * operator->() { return (val*)self.it.operator->(); } private: It it; diff --git a/starts/meaning-vm/level-0/concept.cpp b/starts/meaning-vm/level-0/concept.cpp index 9bb772d..0661edd 100644 --- a/starts/meaning-vm/level-0/concept.cpp +++ b/starts/meaning-vm/level-0/concept.cpp @@ -12,6 +12,7 @@ concept* concept::id() void concept::link(concept* type, concept* target) { + if (type == 0 || target == 0) { throw null_reference(); } links.insert({type, target}); } diff --git a/starts/meaning-vm/level-0/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp index adae8b2..220d0c3 100644 --- a/starts/meaning-vm/level-0/memorystore.cpp +++ b/starts/meaning-vm/level-0/memorystore.cpp @@ -3,26 +3,75 @@ #include "errors.hpp" #include "ref.hpp" -#include <unordered_set> +#include <memory> +#include <unordered_map> namespace intellect { namespace level0 { -static auto & concepts() +static auto & index() { - static std::unordered_set<ref, std::hash<concept*>> concepts; - return concepts; + static std::unordered_map<ref, std::unique_ptr<concept>, std::hash<concept*>> index; + return index; } -ref alloc(std::any data) { - concept * r = new concept(); - r->data = data; - concepts().insert(r); + +namespace concepts { + ref allocator() { static ref ret = basic_alloc(); return ret; }; + ref allocates() { static ref ret = basic_alloc(); return ret; }; + ref allocations() { static ref ret = basic_alloc(); return ret; }; + ref level0allocations() { static ref ret = basic_alloc(); return ret; }; +} + +struct init { init() +{ + concepts::allocator().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::allocator()); + + concepts::allocates().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::allocates()); + + concepts::allocations().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::allocations()); + + concepts::level0allocations().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::level0allocations()); +} } _init; + +ref basic_alloc(std::any data) +{ + ref r = new concept(); + r.ptr()->data = data; + index().emplace(r, r.ptr()); + return r; +} + +ref alloc(ref source, std::any data) +{ + ref r = basic_alloc(data); + alloc(r, source); return r; } -static concept* referenced(ref r) { - for (ref r2 : concepts()) { +void alloc(ref r, ref source) +{ + r.link(concepts::allocator(), source); + source.link(concepts::allocates(), r); +} + +void realloc(ref r, ref newsource) +{ + ref oldsource = r.get(concepts::allocator()); + alloc(r, newsource); + dealloc(r, oldsource); +} + +static concept* referenced(ref r, concept* source = 0) { + for (auto & r2pair : index()) { + ref r2 = r2pair.first; + if (r2.ptr() == source) { + continue; + } if (r2 == r) { continue; } @@ -38,28 +87,87 @@ static concept* referenced(ref r) { return 0; } -void dealloc(ref r) { +void basic_dealloc(ref r) +{ + auto it = index().find(r); + if (it == index().end()) { throw no_such_concept(r); } + concept * referenced = intellect::level0::referenced(r); if (referenced) { throw still_referenced_by(r, referenced); } - for ( - auto it = concepts().begin(); - it != concepts().end(); - ++ it) - { - if (*it == r) { - concepts().erase(it); - delete (concept*)r; - return; + + index().erase(it); +} + +void dealloc_from(ref source) +{ + std::remove_reference<decltype(index())>::type forgotten; + + auto ours = source.getAll(concepts::allocates()); + for (auto allocation : ours) { + source.unlink(concepts::allocates(), allocation); + allocation.unlink(concepts::allocator(), source); + if (allocation.linked(concepts::allocator())) { continue; } + + auto it = index().find(allocation); + if (it != index().end()) { + forgotten.insert(index().extract(it)); + } + } + try { + for (auto allocation : ours ) { + if (allocation.linked(concepts::allocates())) { + dealloc_from(allocation); + } + } + for (auto ghost : ours) { + concept * referenced = intellect::level0::referenced(ghost, source); + if (referenced) { + throw still_referenced_by(ghost, referenced); + } + } + } catch(...) { + // NOTE: this doesn't rebuild deallocated subgroups, but that could be done + // by returning them. + index().merge(forgotten); + for (auto allocation : ours) { + source.link(concepts::allocates(), allocation); + allocation.link(concepts::allocator(), source); + } + throw; + } + + // concepts in forgotten will be deallocated when they leave scope + // note: scoped allocation is just a plan to forget (at the end of a { } block) +} + +void dealloc(ref r, ref source) +{ + auto it = index().find(r); + if (it == index().end()) { throw no_such_concept(r); } + + source.unlink(concepts::allocates(), r); + r.unlink(concepts::allocator(), source); + if (r.linked(concepts::allocator())) { return; } + + try { + dealloc_from(r); + concept * referenced = intellect::level0::referenced(r, source); + if (referenced) { + throw still_referenced_by(r, referenced); } + + index().erase(it); + } catch(...) { + source.link(concepts::allocates(), r); + r.link(concepts::allocator(), source); } - throw no_such_concept(r); } std::size_t allocated() { - return concepts().size(); + return index().size(); } } diff --git a/starts/meaning-vm/level-0/memorystore.hpp b/starts/meaning-vm/level-0/memorystore.hpp index 7843513..f4faa13 100644 --- a/starts/meaning-vm/level-0/memorystore.hpp +++ b/starts/meaning-vm/level-0/memorystore.hpp @@ -7,8 +7,45 @@ namespace intellect { namespace level0 { -ref alloc(std::any data = {}); -void dealloc(ref); +// self-reference loops are real. +// +// one person can feel urgent about issue A, and act on this urgency to engage +// another person around B, who acts in a different way to someone else, eventually +// cycling back to stress that stimulates the original person to feel more urgent +// about issue A. +// human behavior can make arbitrary positive or negative feedback loops. +// +// here in memory allocation, i've designed a system intended to reduce such loops +// by encouraging my usage to be a certain way, but it still readily provides for +// them. +// +// in process expansion / simple thought, we also have the issue of recursion. +// if we trust a task to complete, and it ends up triggering itself in a subcontext, +// we could wait forever. +// +// the solution to many of these things is to recognize repetition in systems. +// we also become skeptical as things continue constantly. we expect to develop +// some level of understanding that they will shrink, or we stop them and try +// something else. + +namespace concepts { + +extern ref allocator(); // link shows what is holding something alive +extern ref allocates(); // link shows what is being held alive + +extern ref allocations(); // to use as a basic allocator for simple things +extern ref level0allocations(); // allocator for concepts internal to level0 + +} + +ref basic_alloc(std::any data = {}); +void basic_dealloc(ref allocated); + +ref alloc(ref allocator, std::any data = {}); // new concept +void alloc(ref allocated, ref allocator); // extra ownership for concept +void realloc(ref allocated, ref allocator); // move ownership for concept to allocator +[[deprecated("can make recursion: turn to workable habits")]] +void dealloc(ref allocated, ref allocator); // remove ownership for concept std::size_t allocated(); } diff --git a/starts/meaning-vm/level-0/ref.cpp b/starts/meaning-vm/level-0/ref.cpp index d4758bd..87e911a 100644 --- a/starts/meaning-vm/level-0/ref.cpp +++ b/starts/meaning-vm/level-0/ref.cpp @@ -1,10 +1,12 @@ #include "ref.hpp" #include "concept.hpp" #include "errors.hpp" +#include "memorystore.hpp" #include <ostream> using namespace intellect::level0; +using namespace concepts; std::string ref::dump(ref skipmarkertype, ref skipmarkertarget) { @@ -13,10 +15,12 @@ std::string ref::dump(ref skipmarkertype, ref skipmarkertarget) } std::string ret = std::to_string((unsigned long)ptr()) + ":\n"; for (auto & link : self.links()) { + if (link.first.linked(allocator(), level0allocations())) { continue; } ret += " " + std::to_string((unsigned long)link.first.ptr()) + ": " + std::to_string((unsigned long)link.second.ptr()) + "\n"; } self.link(skipmarkertype, skipmarkertarget); for (auto & link : self.links()) { + if (link.first.linked(allocator(), level0allocations())) { continue; } if (link.first == skipmarkertype && link.second == skipmarkertarget) { continue; } diff --git a/starts/meaning-vm/level-1/baseref.hpp b/starts/meaning-vm/level-1/baseref.hpp index e97db2d..5055d44 100644 --- a/starts/meaning-vm/level-1/baseref.hpp +++ b/starts/meaning-vm/level-1/baseref.hpp @@ -31,7 +31,7 @@ struct baseref : public level0::baseref<ref> ref operator[](ref subref) const { return self.get(subref); } template <typename T> - void vset(ref const & type, T const & v) { self.set(type, level1::alloc(v)); } + void vset(ref const & type, T const & v) { self.set(type, level1::alloc(level0::concepts::allocations(), v)); } template <typename... Ref> std::function<ref(Ref...)> & fun() { return self.template val<std::function<ref(Ref...)>>(); } diff --git a/starts/meaning-vm/level-1/concepts.cpp b/starts/meaning-vm/level-1/concepts.cpp index 51cd693..890d8b2 100644 --- a/starts/meaning-vm/level-1/concepts.cpp +++ b/starts/meaning-vm/level-1/concepts.cpp @@ -9,6 +9,7 @@ ref is("is"); ref anonymous("anonymous"); ref link("link"); ref name("name"); +ref allocation("allocation"), part("part"), group("group"); } } diff --git a/starts/meaning-vm/level-1/concepts.hpp b/starts/meaning-vm/level-1/concepts.hpp index 6dfc64b..b75133e 100644 --- a/starts/meaning-vm/level-1/concepts.hpp +++ b/starts/meaning-vm/level-1/concepts.hpp @@ -12,6 +12,7 @@ extern ref name; // used as the link to value<std::string> naming each concept extern ref is; // a link to define group relationships, links to the more general class extern ref anonymous; // a group given concepts with generated names extern ref link; // TODO: for concepts that are links, link them with is=link +extern ref allocation, part, group; // links structuring allocation groups //extern ref true, false; <-- casting provides as if these were declared } diff --git a/starts/meaning-vm/level-1/funcs.cpp b/starts/meaning-vm/level-1/funcs.cpp index 72d3c27..cfb44b7 100644 --- a/starts/meaning-vm/level-1/funcs.cpp +++ b/starts/meaning-vm/level-1/funcs.cpp @@ -19,9 +19,9 @@ static auto & namestruct() std::unordered_map<std::string,ref,std::hash<std::string>,std::equal_to<std::string>> conceptsByName; ref nameref; name_t() - : nameref(level0::alloc()) + : nameref(level0::alloc(level0::concepts::allocations())) { - level0::ref namestr = alloc((std::string)("name")); + level0::ref namestr = level0::alloc(nameref.ptr(), (std::string)("name")); nameref.set(nameref, namestr); conceptsByName.emplace(namestr.val<std::string>(), nameref); } @@ -29,6 +29,14 @@ static auto & namestruct() return namestruct; } +void givename(concept* con, std::string const & name) +{ + auto & ns = namestruct(); + level0::ref namestr = level0::alloc(con, name); + ns.conceptsByName.emplace(namestr.val<std::string>(), con); + con->set(ns.nameref, namestr); +} + concept* getnamed(std::string const & name) { auto & ns = namestruct(); @@ -36,10 +44,8 @@ concept* getnamed(std::string const & name) if (res != ns.conceptsByName.end()) { return res->second; } else { - level1::ref con = level0::alloc(); - level0::ref namestr = level0::alloc(name); - ns.conceptsByName.emplace(namestr.val<std::string>(), con); - con.set(ns.nameref, namestr); + level1::ref con = level0::alloc(level0::concepts::allocations()); + givename(con, name); return con.ptr(); } } @@ -63,10 +69,9 @@ bool isa(concept* member, concept* group) return false; } -concept* alloc(std::any val) +concept* alloc(concept* allocator, std::any val) { - - ref ret = level0::alloc(val); + ref ret = level0::alloc(allocator, val); std::stringstream ss; ss << val.type().name() << "("; if (false); @@ -80,7 +85,7 @@ concept* alloc(std::any val) #undef t else { ss << "?"; } ss << ")"; - ret.link(concepts::name, level0::alloc(ss.str())); + ret.link(concepts::name, level0::alloc(ret, ss.str())); return ret; } @@ -96,6 +101,7 @@ std::string dump(concept* what, concept* skipmarkertype, concept* skipmarkertarg } std::string ret; for (auto & link : ref(what).links()) { + if (link.first.linked(level0::concepts::allocator(), level0::concepts::level0allocations())) { continue; } if (link.first == concepts::name) { continue; } if (ret.size() == 0) { ret = ref(what).name() + ":\n"; @@ -104,6 +110,7 @@ std::string dump(concept* what, concept* skipmarkertype, concept* skipmarkertarg } what->link(skipmarkertype, skipmarkertarget); for (auto & link : ref(what).links()) { + if (link.first.linked(level0::concepts::allocator(), level0::concepts::level0allocations())) { continue; } if (link.first.ptr() == skipmarkertype && link.second.ptr() == skipmarkertarget) { continue; } diff --git a/starts/meaning-vm/level-1/funcs.hpp b/starts/meaning-vm/level-1/funcs.hpp index 4b53ddd..9361917 100644 --- a/starts/meaning-vm/level-1/funcs.hpp +++ b/starts/meaning-vm/level-1/funcs.hpp @@ -18,7 +18,7 @@ bool isa(concept* member, concept* group); concept* hyphenate(concept* a, concept* b); -concept* alloc(std::any val); +concept* alloc(concept* allocator, std::any val); std::string dump(concept * what, concept * skipmarkertype, concept * skipmarkertarget); diff --git a/starts/meaning-vm/level-1/sugar.cpp b/starts/meaning-vm/level-1/sugar.cpp index 24d59be..21f4001 100644 --- a/starts/meaning-vm/level-1/sugar.cpp +++ b/starts/meaning-vm/level-1/sugar.cpp @@ -49,15 +49,17 @@ ref movetoname(ref anonymous, ref name) // information is not available at this level. bool nonempty = false; for (auto & l : name.links()) { + if (l.first.linked(level0::concepts::allocator(), level0::concepts::level0allocations())) { continue; } if (l.first == concepts::name) { continue; } nonempty = true; } if (nonempty) { for (auto & link : anonymous.links()) { if (link.first == concepts::is && link.second == concepts::anonymous) { continue; } + if (link.first.linked(level0::concepts::allocator(), level0::concepts::level0allocations())) { continue; } if (link.first == concepts::name) { continue; } if (!name.linked(link.first, link.second)) { - throw std::logic_error(name.name() + " already defined otherwise from " + anonymous.get(concepts::is).name()); + throw std::logic_error(name.name() + " already defined otherwise from " + anonymous.getAll(concepts::is).begin()->name()); } } } @@ -66,12 +68,13 @@ ref movetoname(ref anonymous, ref name) anonymous.unlink(concepts::name, nam); if (!nonempty) { for (auto & l : anonymous.links()) { + if (l.first.linked(level0::concepts::allocator(), level0::concepts::level0allocations())) { continue; } name.link(l.first, l.second); } } anonymous.link(concepts::name, nam); - dealloc(anonymous); - dealloc(nam); + dealloc(anonymous, level0::concepts::allocations()); + //dealloc(nam, level0::concepts::allocations()); return name; } diff --git a/starts/meaning-vm/level-2/funcs.cpp b/starts/meaning-vm/level-2/funcs.cpp index ed50c39..a8835f4 100644 --- a/starts/meaning-vm/level-2/funcs.cpp +++ b/starts/meaning-vm/level-2/funcs.cpp @@ -40,7 +40,7 @@ ref dohabit(ref habit, std::initializer_list<ref> args) throw std::invalid_argument("wrong number of arguments to habit"); } posarg = posarg[next-positional-argument]; - // TODO: subcontexts + // TODO: subcontexts or call instances ref::context().set(posarg[argument], arg); } if (posarg.linked(next-positional-argument)) { diff --git a/starts/meaning-vm/level0.cpp b/starts/meaning-vm/level0.cpp index 6ff0102..4ab8b7b 100644 --- a/starts/meaning-vm/level0.cpp +++ b/starts/meaning-vm/level0.cpp @@ -5,17 +5,23 @@ using namespace intellect::level0; +#define out(name) std::cout << " " #name ":" << (long)name.ptr() + int main() { - ref a = alloc(); - ref b = alloc(); - ref c = alloc(); - ref d = alloc(); - ref e = alloc(); - auto numlink = alloc(); - auto codelink = alloc(); - - ref skip = alloc(); + std::cout << allocated() << " allocated" << std::endl; + + ref store = alloc(concepts::allocations()); out(store); + ref a = alloc(store); out(a); + ref b = alloc(store); out(b); + ref c = alloc(store); out(c); + ref d = alloc(store); out(d); + ref e = alloc(store); out(e); + auto numlink = alloc(a); out(numlink); + auto codelink = alloc(a); out(codelink); + + ref skip = alloc(store); out(skip); + std::cout << std::endl; a.link( b, c, @@ -37,18 +43,8 @@ int main() std::cout << allocated() << " allocated" << std::endl; e.unlink(b, a); - auto num = a.get(numlink); - auto code = a.get(codelink); - dealloc(a); - dealloc(num); - dealloc(code); - dealloc(numlink); - dealloc(codelink); - dealloc(c); - dealloc(e); - dealloc(b); - dealloc(d); - dealloc(skip); + //dealloc(a, store); + dealloc(store, concepts::allocations()); std::cout << allocated() << " allocated" << std::endl; diff --git a/starts/meaning-vm/level1.cpp b/starts/meaning-vm/level1.cpp index 9498ddf..3c1a634 100644 --- a/starts/meaning-vm/level1.cpp +++ b/starts/meaning-vm/level1.cpp @@ -7,7 +7,10 @@ using namespace intellect::level1::concepts; int main() { + std::cout << intellect::level0::allocated() << " allocated" << std::endl; + decls(make, linked, habit); + std::cout << intellect::level0::allocated() << " allocated" << std::endl; decls(needs, assumes, makes); decls(not, topic); decls(A, B, C); @@ -61,5 +64,9 @@ int main() std::cout << apple.dump("dumped", true) << std::endl; + std::cout << intellect::level0::allocated() << " allocated" << std::endl; + intellect::level0::dealloc(intellect::level0::concepts::allocations(), intellect::level0::concepts::level0allocations()); + std::cout << intellect::level0::allocated() << " allocated" << std::endl; + return 0; } diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile index 325a07c..637c4fe 100644 --- a/starts/meaning-vm/makefile +++ b/starts/meaning-vm/makefile @@ -1,4 +1,4 @@ -CXXFLAGS=-Wall -Werror -std=gnu++17 -fno-operator-names -ggdb -O0 +CXXFLAGS=-Wall -Werror -Wno-error=deprecated-declarations -std=gnu++17 -fno-operator-names -ggdb -O0 LINK.o=$(LINK.cc) all: level0 level1 habit-starts/rhythm |