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/common.hpp14
-rw-r--r--starts/meaning-vm/level-0/concept.cpp94
-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.cpp59
-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
11 files changed, 420 insertions, 0 deletions
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/level-0/concept.cpp b/starts/meaning-vm/level-0/concept.cpp
new file mode 100644
index 0000000..579cca8
--- /dev/null
+++ b/starts/meaning-vm/level-0/concept.cpp
@@ -0,0 +1,94 @@
+#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;
+}
+
+bool concept::linked(ref const & type, ref const & target) const
+{
+ for (ref const & t : getAll(type)) {
+ if (t == target) {
+ return true;
+ }
+ }
+ return false;
+}
+
+concept::array concept::getAll(ref const & type) const
+{
+ array ret;
+ for (
+ auto range = links.equal_range(type);
+ range.first != range.second;
+ ++ range.first
+ ) {
+ ret.emplace_back(range.first->second);
+ }
+ return ret;
+}
+
+ref concept::get(ref const & type) const
+{
+ 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);
+ }
+ return result.first->second;
+}
+
+void concept::set(ref const & type, ref const & target)
+{
+ if (linked(type)) {
+ throw link_type_not_unique(selfref, type);
+ }
+ 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/level-0/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp
new file mode 100644
index 0000000..6cf71df
--- /dev/null
+++ b/starts/meaning-vm/level-0/memorystore.cpp
@@ -0,0 +1,59 @@
+#include "memorystore.hpp"
+#include "concept.hpp"
+#include "errors.hpp"
+
+#include <unordered_set>
+
+namespace intellect {
+namespace level0 {
+
+static auto & 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);
+ return r;
+}
+
+static concept* referenced(ref r) {
+ for (ref r2 : concepts()) {
+ if (r2 == r) {
+ continue;
+ }
+ for (auto & l : r2->links) {
+ if (ref(l.first) == r) {
+ return r2.ptr;
+ }
+ if (ref(l.second) == r) {
+ return r2.ptr;
+ }
+ }
+ }
+ return 0;
+}
+
+void dealloc(ref 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 (ref(*it) == r) {
+ concepts().erase(it);
+ delete r.ptr;
+ return;
+ }
+ }
+ 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;
+};
+
+
+}
+}