summaryrefslogtreecommitdiff
path: root/starts/meaning-vm
diff options
context:
space:
mode:
Diffstat (limited to 'starts/meaning-vm')
-rw-r--r--starts/meaning-vm/concept.hpp74
-rw-r--r--starts/meaning-vm/helpers.hpp49
-rw-r--r--starts/meaning-vm/main.cpp12
-rw-r--r--starts/meaning-vm/makefile4
4 files changed, 139 insertions, 0 deletions
diff --git a/starts/meaning-vm/concept.hpp b/starts/meaning-vm/concept.hpp
new file mode 100644
index 0000000..981835f
--- /dev/null
+++ b/starts/meaning-vm/concept.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+using cid = struct concept *;
+
+struct concept
+{
+ // a concept is made of concept-typed links to other concepts
+ std::multimap<cid,cid> links;
+ using array = std::vector<cid>;
+
+ cid id();
+ cid get(cid type); // returns first
+ array getAll(cid type);
+ void link(cid type, cid target);
+ void unlink(cid type, cid target);
+};
+
+template <typename T>
+struct value : public concept, public T
+{
+ static value<T>& of(cid c)
+ {
+ return *static_cast<value<T>*>(c);
+ }
+};
+
+cid concept::id()
+{
+ return this;
+}
+
+cid concept::get(cid type)
+{
+ auto result = links.equal_range(type);
+ if (result.first == result.second) {
+ throw std::out_of_range("no such concept link to get");
+ }
+ return result.first->second;
+}
+
+concept::array concept::getAll(cid type)
+{
+ array ret;
+ for (
+ auto range = links.equal_range(type);
+ range.first != range.second;
+ ++ range.first
+ ) {
+ ret.push_back(range.first->second);
+ }
+ return ret;
+}
+
+void concept::link(cid type, cid target)
+{
+ links.insert({type, target});
+}
+
+void concept::unlink(cid type, cid 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 std::out_of_range("no such concept link to erase");
+}
diff --git a/starts/meaning-vm/helpers.hpp b/starts/meaning-vm/helpers.hpp
new file mode 100644
index 0000000..f21952a
--- /dev/null
+++ b/starts/meaning-vm/helpers.hpp
@@ -0,0 +1,49 @@
+#include "concept.hpp"
+
+// Makes string values interchangeable with the concepts
+// they name.
+template<>
+struct value<std::string> : public concept, public std::string
+{
+ //using std::string::basic_string;
+ value(std::string);
+ value(cid);
+ operator cid();
+ static value& of(cid c)
+ {
+ return *static_cast<value*>(c);
+ }
+};
+
+using str = value<std::string>;
+
+cid operator"" _c(const char* str, std::size_t len)
+{
+ return value<std::string>({str,len});
+}
+
+#include <unordered_map>
+
+concept namesByConcept;
+std::unordered_map<value<std::string>,concept,std::hash<std::string>> conceptsByName;
+
+value<std::string>::value(std::string s)
+: std::string(s)
+{ }
+
+value<std::string>::value(cid c)
+: std::string(of(namesByConcept.get(c)))
+{ }
+
+value<std::string>::operator cid()
+{
+ try {
+ return &conceptsByName.at(*this);
+ } catch (std::out_of_range) {
+ auto insertion = conceptsByName.emplace(*this, concept());
+ cid con = &insertion.first->second;
+ cid nam = const_cast<cid>((const cid)&insertion.first->first);
+ namesByConcept.link(con, nam);
+ return con;
+ }
+}
diff --git a/starts/meaning-vm/main.cpp b/starts/meaning-vm/main.cpp
new file mode 100644
index 0000000..8fb4c64
--- /dev/null
+++ b/starts/meaning-vm/main.cpp
@@ -0,0 +1,12 @@
+#include "concept.hpp"
+#include "helpers.hpp"
+
+using namespace std;
+
+#include <iostream>
+
+int main()
+{
+ cid concept = "concept"_c;
+ cout << str(concept) << endl;
+}
diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile
new file mode 100644
index 0000000..eb47570
--- /dev/null
+++ b/starts/meaning-vm/makefile
@@ -0,0 +1,4 @@
+CXXFLAGS=-std=c++11 -ggdb
+
+main: main.cpp
+aain.cpp: *.hpp