summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorolpc user <olpc@xo-5d-f7-86.localdomain>2019-11-24 13:22:55 -0800
committerolpc user <olpc@xo-5d-f7-86.localdomain>2019-11-24 13:22:55 -0800
commit9a14918abec434d8463e07635daef380ad630649 (patch)
treefa1a5200da88ad6065092b05dc063a8a80df8faa
parent50be8bb8697b23ff469de142eaebe9666c2a9537 (diff)
downloadstandingwithresilience-9a14918abec434d8463e07635daef380ad630649.tar.gz
standingwithresilience-9a14918abec434d8463e07635daef380ad630649.zip
breaking into levels
-rw-r--r--starts/meaning-vm/DESIGN.txt10
-rw-r--r--starts/meaning-vm/concept.hpp100
-rw-r--r--starts/meaning-vm/level-0/common.hpp14
-rw-r--r--starts/meaning-vm/level-0/concept.cpp (renamed from starts/meaning-vm/concept.cpp)91
-rw-r--r--starts/meaning-vm/level-0/concept.hpp38
-rw-r--r--starts/meaning-vm/level-0/errors.hpp77
-rw-r--r--starts/meaning-vm/level-0/level-0.hpp9
-rw-r--r--starts/meaning-vm/level-0/memorystore.cpp (renamed from starts/meaning-vm/memorystore.cpp)22
-rw-r--r--starts/meaning-vm/level-0/memorystore.hpp13
-rw-r--r--starts/meaning-vm/level-0/ref.cpp34
-rw-r--r--starts/meaning-vm/level-0/ref.hpp26
-rw-r--r--starts/meaning-vm/level-0/value.hpp25
-rw-r--r--starts/meaning-vm/level-0/vref.hpp31
-rw-r--r--starts/meaning-vm/level0.cpp25
-rw-r--r--starts/meaning-vm/makefile10
-rw-r--r--starts/meaning-vm/memorystore.hpp9
16 files changed, 377 insertions, 157 deletions
diff --git a/starts/meaning-vm/DESIGN.txt b/starts/meaning-vm/DESIGN.txt
new file mode 100644
index 0000000..299acb2
--- /dev/null
+++ b/starts/meaning-vm/DESIGN.txt
@@ -0,0 +1,10 @@
+The codebase is made in levels.
+Ideally each level defines a complete API to the underworkings.
+Higher levels include greater degrees of meaning.
+
+# LEVEL 0
+Level 0 defines an interconnected network of concept references in memory.
+Each concept has a unique address, and a list of concept pairs it links to.
+The first of the pair represents the type of the link, and the second the target.
+Concepts may not be deallocated unless nothing links to them.
+A special kind of concept is the value, which holds arbitrary data alongside itself.
diff --git a/starts/meaning-vm/concept.hpp b/starts/meaning-vm/concept.hpp
deleted file mode 100644
index 3308e10..0000000
--- a/starts/meaning-vm/concept.hpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#pragma once
-
-#include <map>
-#include <stdexcept>
-#include <string>
-#include <vector>
-
-template <typename T> struct vref;
-struct concept;
-template <typename T> struct value;
-struct statementcallref;
-
-struct ref
-{
- ref(concept *p) : ptr(p) { if (p == 0) throw std::logic_error("null reference"); }
- concept* operator->() { return ptr; }
- concept const * operator->() const { return ptr; }
- bool operator==(ref const & that) const { return this->ptr == that.ptr; }
- bool operator!=(ref const & that) const { return this->ptr != that.ptr; }
-
- bool operator<(ref const &) const { throw std::logic_error("ref has redefined syntax sugar: do not use in containers"); }
-
- // for helpers, mostly names
- ref(std::string const &);
- ref(char const * str) : ref(std::string(str)) { }
- ref(bool b) : ref(b ? "true" : "false") { }
- ref() : ref("nothing") { }
- vref<std::string> name() const;
- operator const char *() const;
-
- // helper linking syntax sugar
- statementcallref operator=(ref that);
- //ref operator<<(ref target);
- ref operator[](ref links);
-
- bool isa(ref what) const;
- bool isan(ref what) const;
-
- concept * ptr;
-
- /*
- // destructor handles evaluating refs as statements
- ~ref() noexcept;
- ref(ref & that);
- ref(ref && that) noexcept;
- void destatement();
- */
-};
-
-template <typename T>
-struct vref
-{
- vref(value<T> *p) : ptr(p) { }
- value<T>* operator->() { return ptr; }
- operator T const &() const { return *ptr; }
-
- vref(T const & val);
-
- vref(ref const & that) : ptr(static_cast<value<T>*>(that.ptr)) { }
- operator ref() { return ptr; }
-
- // for use by containers
- //bool operator<(ref const & that) const { return ptr < that.ptr; }
-
- value<T> * ptr;
-};
-
-struct concept
-{
- // a concept is made of concept-typed links to other concepts
- std::multimap<concept*,concept*> links;
- using array = std::vector<ref>;
-
- ref id();
- bool linked(ref const & type) const;
- bool linked(ref const & type, ref const & target) const;
- ref get(ref const & type, bool quick = false) const; // returns first
- template <typename T>
- vref<T> vget(ref const & type, bool quick = false) const { return get(type, quick); }
- array getAll(ref const & type) const;
- void link(ref const & type, ref const & target);
- void unlink(ref const & type, ref const & target);
- void unlink(ref const & type);
-};
-
-template <typename T>
-struct value : public concept
-{
- value(T const & val) : data(val) { }
- value(value<T> const & val) = default;
- static value<T>& of(ref c)
- {
- return *static_cast<value<T>*>(c.ptr);
- }
-
- operator T&() { return data; }
- operator T const &() const { return data; }
-
- T data;
-};
diff --git a/starts/meaning-vm/level-0/common.hpp b/starts/meaning-vm/level-0/common.hpp
new file mode 100644
index 0000000..4c36a04
--- /dev/null
+++ b/starts/meaning-vm/level-0/common.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#define self (*this)
+
+namespace intellect {
+namespace level0 {
+
+struct concept;
+struct ref;
+template <typename T> struct value;
+template <typename T> struct vref;
+
+}
+}
diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/level-0/concept.cpp
index 993ac62..579cca8 100644
--- a/starts/meaning-vm/concept.cpp
+++ b/starts/meaning-vm/level-0/concept.cpp
@@ -1,10 +1,46 @@
#include "concept.hpp"
+#include "errors.hpp"
+
+using namespace intellect::level0;
+
+#define selfref const_cast<concept*>(&self)
ref concept::id()
{
return this;
}
+void concept::link(ref const & type, ref const & target)
+{
+ links.insert({type.ptr, target.ptr});
+}
+
+void concept::unlink(ref const & type, ref const & target)
+{
+ auto ls = links.equal_range(type);
+ for (auto l = ls.first; l != ls.second; ++ l) {
+ if (l->second == target) {
+ links.erase(l);
+ return;
+ }
+ }
+ throw no_such_link_type_target(selfref, type, target);
+}
+
+void concept::unlink(ref const & 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);
+ }
+ links.erase(ls.first);
+}
+
bool concept::linked(ref const & type) const
{
return links.count(type.ptr) > 0;
@@ -20,25 +56,11 @@ bool concept::linked(ref const & type, ref const & target) const
return false;
}
-ref concept::get(ref const & type, bool quick) const
-{
- // this is called by name(), so it passes quick=true
- auto result = links.equal_range(type.ptr);
- if (result.first == result.second) {
- if (quick) {
- throw std::out_of_range("no such concept link to get");
- } else {
- throw std::out_of_range("no such concept link to get: " + (std::string)type.name());
- }
- }
- return result.first->second;
-}
-
concept::array concept::getAll(ref const & type) const
{
array ret;
for (
- auto range = links.equal_range(type.ptr);
+ auto range = links.equal_range(type);
range.first != range.second;
++ range.first
) {
@@ -47,33 +69,26 @@ concept::array concept::getAll(ref const & type) const
return ret;
}
-void concept::link(ref const & type, ref const & target)
+ref concept::get(ref const & type) const
{
- links.insert({type.ptr, target.ptr});
-}
-
-void concept::unlink(ref const & type, ref const & target)
-{
- auto ls = links.equal_range(type.ptr);
- for (auto l = ls.first; l != ls.second; ++ l) {
- if (l->second == target.ptr) {
- links.erase(l);
- return;
- }
+ auto result = links.equal_range(type.ptr);
+ 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);
}
- throw std::out_of_range("no such concept link to erase");
+ return result.first->second;
}
-void concept::unlink(ref const & type)
+void concept::set(ref const & type, ref const & target)
{
- auto ls = links.equal_range(type.ptr);
- if (ls.first == ls.second) {
- throw std::out_of_range("no such concept link to erase");
+ if (linked(type)) {
+ throw link_type_not_unique(selfref, type);
}
- auto mid = ls.first;
- ++ mid;
- if (mid != ls.second) {
- throw std::out_of_range("more than one link of type to erase");
- }
- links.erase(ls.first);
+ link(type, target);
}
+
+
diff --git a/starts/meaning-vm/level-0/concept.hpp b/starts/meaning-vm/level-0/concept.hpp
new file mode 100644
index 0000000..dc3221b
--- /dev/null
+++ b/starts/meaning-vm/level-0/concept.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "common.hpp"
+#include "ref.hpp"
+
+#include <map>
+#include <vector>
+
+namespace intellect {
+namespace level0 {
+
+struct concept
+{
+ // a concept is made of concept-typed links to other concepts
+ std::multimap<ref,ref> links;
+ using array = std::vector<ref>;
+
+ ref id();
+
+ void link(ref const & type, ref const & target);
+ void unlink(ref const & type, ref const & target);
+ void unlink(ref const & type);
+
+ bool linked(ref const & type) const;
+ bool linked(ref const & type, ref const & target) const;
+
+ array getAll(ref const & type) const;
+
+ // get and set enforce that only 1 link of a given type is present
+ ref get(ref const & type) const;
+ void set(ref const & type, ref const & target);
+
+ template <typename T>
+ vref<T> vget(ref const & type) const { return get(type); }
+};
+
+}
+}
diff --git a/starts/meaning-vm/level-0/errors.hpp b/starts/meaning-vm/level-0/errors.hpp
new file mode 100644
index 0000000..c052c69
--- /dev/null
+++ b/starts/meaning-vm/level-0/errors.hpp
@@ -0,0 +1,77 @@
+#pragma once
+#include "ref.hpp"
+
+#include <stdexcept>
+
+namespace intellect {
+namespace level0 {
+
+struct no_such_link_type : public std::out_of_range
+{
+ no_such_link_type(ref source, ref type)
+ : std::out_of_range("no such concept link type"),
+ source(source),
+ type(type)
+ { }
+
+ ref const source;
+ ref const type;
+};
+
+struct no_such_link_type_target : public std::out_of_range
+{
+ no_such_link_type_target(ref source, ref type, ref target)
+ : std::out_of_range("no such concept link type and target"),
+ source(source),
+ type(type),
+ target(type)
+ { }
+
+ ref const source;
+ ref const type;
+ ref const target;
+};
+
+struct link_type_not_unique : public std::invalid_argument
+{
+ link_type_not_unique(ref source, ref type)
+ : std::invalid_argument("more than one such concept link type"),
+ source(source),
+ type(type)
+ { }
+
+ ref const source;
+ ref const type;
+};
+
+struct still_referenced_by : public std::invalid_argument
+{
+ still_referenced_by(ref topic, ref referrer)
+ : std::invalid_argument("concept is still referenced"),
+ topic(topic),
+ referrer(referrer)
+ { }
+
+ ref const topic;
+ ref const referrer;
+};
+
+struct no_such_concept : public std::invalid_argument
+{
+ no_such_concept(ref topic)
+ : std::invalid_argument("no such concept reference"),
+ topic(topic)
+ { }
+
+ ref const topic;
+};
+
+struct null_reference : public std::invalid_argument
+{
+ null_reference()
+ : std::invalid_argument("null reference")
+ { }
+};
+
+}
+}
diff --git a/starts/meaning-vm/level-0/level-0.hpp b/starts/meaning-vm/level-0/level-0.hpp
new file mode 100644
index 0000000..b44b6e0
--- /dev/null
+++ b/starts/meaning-vm/level-0/level-0.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "common.hpp"
+#include "concept.hpp"
+#include "errors.hpp"
+#include "memorystore.hpp"
+#include "ref.hpp"
+#include "value.hpp"
+#include "vref.hpp"
diff --git a/starts/meaning-vm/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp
index 9be7ba5..6cf71df 100644
--- a/starts/meaning-vm/memorystore.cpp
+++ b/starts/meaning-vm/level-0/memorystore.cpp
@@ -1,22 +1,25 @@
#include "memorystore.hpp"
+#include "concept.hpp"
+#include "errors.hpp"
#include <unordered_set>
-using namespace std;
+namespace intellect {
+namespace level0 {
-auto & concepts()
+static auto & concepts()
{
- static std::unordered_set<concept*> concepts;
+ static std::unordered_set<ref, std::hash<concept*>> concepts;
return concepts;
}
ref alloc(concept * moved) {
ref r = moved ? moved : new concept();
- concepts().insert(r.ptr);
+ concepts().insert(r);
return r;
}
-concept* referenced(ref r) {
+static concept* referenced(ref r) {
for (ref r2 : concepts()) {
if (r2 == r) {
continue;
@@ -34,9 +37,9 @@ concept* referenced(ref r) {
}
void dealloc(ref r) {
- concept * referenced = ::referenced(r);
+ concept * referenced = intellect::level0::referenced(r);
if (referenced) {
- throw std::logic_error("concept '" + r.name()->data + "' is referenced by '" + ref(referenced).name()->data + '"');
+ throw still_referenced_by(r, referenced);
}
for (
auto it = concepts().begin();
@@ -49,5 +52,8 @@ void dealloc(ref r) {
return;
}
}
- throw std::logic_error("concept not held");
+ throw no_such_concept(r);
+}
+
+}
}
diff --git a/starts/meaning-vm/level-0/memorystore.hpp b/starts/meaning-vm/level-0/memorystore.hpp
new file mode 100644
index 0000000..4e0a2bd
--- /dev/null
+++ b/starts/meaning-vm/level-0/memorystore.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "common.hpp"
+#include "ref.hpp"
+
+namespace intellect {
+namespace level0 {
+
+ref alloc(concept * moved = 0);
+void dealloc(ref);
+
+}
+}
diff --git a/starts/meaning-vm/level-0/ref.cpp b/starts/meaning-vm/level-0/ref.cpp
new file mode 100644
index 0000000..7e10528
--- /dev/null
+++ b/starts/meaning-vm/level-0/ref.cpp
@@ -0,0 +1,34 @@
+#include "ref.hpp"
+#include "concept.hpp"
+#include "errors.hpp"
+
+#include <ostream>
+
+using namespace intellect::level0;
+
+ref::ref(concept *p)
+: ptr(p)
+{
+ if (p == 0) {
+ throw null_reference();
+ }
+}
+
+std::string ref::dump(ref skipmarkertype, ref skipmarkertarget) const
+{
+ if (self->linked(skipmarkertype, skipmarkertarget)) {
+ return {};
+ }
+ std::string ret = std::to_string((unsigned long)ptr) + ":\n";
+ for (auto & link : self->links) {
+ 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 == skipmarkertype && link.second == skipmarkertype) {
+ continue;
+ }
+ ret += link.second.dump(skipmarkertype, skipmarkertarget);
+ }
+ return ret;
+}
diff --git a/starts/meaning-vm/level-0/ref.hpp b/starts/meaning-vm/level-0/ref.hpp
new file mode 100644
index 0000000..951676b
--- /dev/null
+++ b/starts/meaning-vm/level-0/ref.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "common.hpp"
+
+#include <string>
+
+namespace intellect {
+namespace level0 {
+
+struct ref
+{
+ ref(concept *p);
+ operator concept*() const { return ptr; }
+ concept* operator->() const { return ptr; }
+ bool operator==(ref const & other) const { return self.ptr == other.ptr; }
+ bool operator!=(ref const & other) const { return self.ptr != other.ptr; }
+ bool operator<(ref const & other) const { return self.ptr < other.ptr; }
+ concept & deref() { return *ptr; }
+
+ std::string dump(ref skipmarkertype, ref skipmarkertarget) const;
+
+ concept * const ptr;
+};
+
+}
+}
diff --git a/starts/meaning-vm/level-0/value.hpp b/starts/meaning-vm/level-0/value.hpp
new file mode 100644
index 0000000..ff704bf
--- /dev/null
+++ b/starts/meaning-vm/level-0/value.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "common.hpp"
+
+#include "concept.hpp"
+
+namespace intellect {
+namespace level0 {
+
+template <typename T>
+struct value : public concept
+{
+ value(T const & val) : data(val) { }
+
+ value(value<T> const & val) = default;
+
+ operator T&() { return data; }
+ operator T const &() const { return data; }
+
+ T data;
+};
+
+
+}
+}
diff --git a/starts/meaning-vm/level-0/vref.hpp b/starts/meaning-vm/level-0/vref.hpp
new file mode 100644
index 0000000..7fe2045
--- /dev/null
+++ b/starts/meaning-vm/level-0/vref.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "common.hpp"
+#include "memorystore.hpp"
+#include "ref.hpp"
+#include "value.hpp"
+
+namespace intellect {
+namespace level0 {
+
+template <typename T>
+struct vref
+{
+ vref(value<T> *p) : ptr(p) { }
+ value<T>* operator->() { return ptr; }
+ operator T const &() const { return *ptr; }
+
+ vref(T const & val) : ptr(alloc(new value<T>(val))) { }
+
+ vref(ref const & other) : ptr(static_cast<value<T>*>(other.ptr)) { }
+ operator ref() { return ptr; }
+
+ // for use by containers
+ bool operator<(vref<T> const & other) const { return self.ptr < other.ptr; }
+
+ value<T> * const ptr;
+};
+
+
+}
+}
diff --git a/starts/meaning-vm/level0.cpp b/starts/meaning-vm/level0.cpp
new file mode 100644
index 0000000..71c18b7
--- /dev/null
+++ b/starts/meaning-vm/level0.cpp
@@ -0,0 +1,25 @@
+#include "level-0/level-0.hpp"
+
+#include <iostream>
+
+using namespace intellect::level0;
+
+int main()
+{
+ ref a = alloc();
+ ref b = alloc();
+ ref c = alloc();
+ ref d = alloc();
+ ref e = alloc();
+
+ ref skip = alloc();
+
+ a->link(b, c);
+ a->link(d, e);
+ e->link(b, a);
+ c->link(b, e);
+
+ std::cout << a.dump(skip, skip) << std::endl;
+
+ return 0;
+}
diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile
index 7c39de3..748cca2 100644
--- a/starts/meaning-vm/makefile
+++ b/starts/meaning-vm/makefile
@@ -1,7 +1,13 @@
CXXFLAGS=-Wall -Werror -std=c++17 -fno-operator-names -ggdb -O0
LINK.o=$(LINK.cc)
+level0: level0.o liblevel0.a
+liblevel0.a: level-0/memorystore.o level-0/concept.o level-0/ref.o
+%.a:
+ ar ru $@ $^
+ ranlib $@
+
main: main.o concept.o helpers.o memorystore.o meaning.o
-*.o: *.hpp
+*.o: *.hpp */*.hpp
clean:
- -rm *.o main
+ -rm *.o main level0 *.a */*.o
diff --git a/starts/meaning-vm/memorystore.hpp b/starts/meaning-vm/memorystore.hpp
deleted file mode 100644
index d1ca98d..0000000
--- a/starts/meaning-vm/memorystore.hpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-#include "concept.hpp"
-
-ref alloc(concept * moved = 0);
-template <typename T>
-vref<T> valloc(T const & val) { return alloc(new value<T>(val)); }
-void dealloc(ref);
-void dealloc_all(ref); // todo?