summaryrefslogtreecommitdiff
path: root/starts/meaning-vm
diff options
context:
space:
mode:
Diffstat (limited to 'starts/meaning-vm')
-rw-r--r--starts/meaning-vm/level-0/baseref.hpp4
-rw-r--r--starts/meaning-vm/level-0/concept.cpp1
-rw-r--r--starts/meaning-vm/level-0/memorystore.cpp152
-rw-r--r--starts/meaning-vm/level-0/memorystore.hpp41
-rw-r--r--starts/meaning-vm/level-0/ref.cpp4
-rw-r--r--starts/meaning-vm/level-1/baseref.hpp2
-rw-r--r--starts/meaning-vm/level-1/concepts.cpp1
-rw-r--r--starts/meaning-vm/level-1/concepts.hpp1
-rw-r--r--starts/meaning-vm/level-1/funcs.cpp27
-rw-r--r--starts/meaning-vm/level-1/funcs.hpp2
-rw-r--r--starts/meaning-vm/level-1/sugar.cpp9
-rw-r--r--starts/meaning-vm/level-2/funcs.cpp2
-rw-r--r--starts/meaning-vm/level0.cpp38
-rw-r--r--starts/meaning-vm/level1.cpp7
-rw-r--r--starts/meaning-vm/makefile2
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