summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--starts/meaning-vm/concept.cpp45
-rw-r--r--starts/meaning-vm/concept.hpp82
-rw-r--r--starts/meaning-vm/helpers.cpp28
-rw-r--r--starts/meaning-vm/helpers.hpp50
-rw-r--r--starts/meaning-vm/main.cpp4
-rw-r--r--starts/meaning-vm/makefile9
6 files changed, 110 insertions, 108 deletions
diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/concept.cpp
new file mode 100644
index 0000000..dc9ecca
--- /dev/null
+++ b/starts/meaning-vm/concept.cpp
@@ -0,0 +1,45 @@
+#include "concept.hpp"
+
+ref concept::id()
+{
+ return this;
+}
+
+ref concept::get(ref 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(ref 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(ref type, ref target)
+{
+ links.insert({type, target});
+}
+
+void concept::unlink(ref type, ref 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/concept.hpp b/starts/meaning-vm/concept.hpp
index 981835f..ce76f5d 100644
--- a/starts/meaning-vm/concept.hpp
+++ b/starts/meaning-vm/concept.hpp
@@ -5,70 +5,42 @@
#include <string>
#include <vector>
-using cid = struct concept *;
+struct concept;
+template <typename T> struct value;
+
+struct ref
+{
+ ref(concept *p) : ptr(p) { }
+ operator concept*() const { return ptr; }
+
+ // helper names
+ ref(std::string);
+ operator std::string();
+ ref(char const * str) : ref(std::string(str)) { }
+
+ concept * ptr;
+};
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);
+ std::multimap<ref,ref,std::less<concept*>> links;
+ using array = std::vector<ref>;
+
+ ref id();
+ ref get(ref type); // returns first
+ array getAll(ref type);
+ void link(ref type, ref target);
+ void unlink(ref type, ref target);
};
template <typename T>
struct value : public concept, public T
{
- static value<T>& of(cid c)
+ value(T const & val) : T(val) {}
+ value(value<T> const & val) = default;
+ static value<T>& of(ref c)
{
- return *static_cast<value<T>*>(c);
+ return *static_cast<value<T>*>(c.ptr);
}
};
-
-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.cpp b/starts/meaning-vm/helpers.cpp
new file mode 100644
index 0000000..e4a7689
--- /dev/null
+++ b/starts/meaning-vm/helpers.cpp
@@ -0,0 +1,28 @@
+#include "helpers.hpp"
+
+#include <unordered_map>
+
+// these concept names are for bootstrapping convenience,
+// to make hardcoding structures easier.
+// hence there is just one single list of them
+
+concept namesByConcept;
+std::unordered_map<value<std::string>,concept,std::hash<std::string>> conceptsByName;
+
+ref::ref(std::string s)
+{
+ try {
+ ptr = &conceptsByName.at(value<std::string>(s));
+ } catch (std::out_of_range) {
+ auto insertion = conceptsByName.emplace(value<std::string>(s), concept());
+ ref con = &insertion.first->second;
+ ref nam = const_cast<concept *>((concept const *)&insertion.first->first);
+ namesByConcept.link(con, nam);
+ ptr = con;
+ }
+}
+
+ref::operator std::string()
+{
+ return value<std::string>::of(namesByConcept.get(*this));
+}
diff --git a/starts/meaning-vm/helpers.hpp b/starts/meaning-vm/helpers.hpp
index f21952a..6659019 100644
--- a/starts/meaning-vm/helpers.hpp
+++ b/starts/meaning-vm/helpers.hpp
@@ -1,49 +1,3 @@
-#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>
+#pragma once
-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;
- }
-}
+#include "concept.hpp"
diff --git a/starts/meaning-vm/main.cpp b/starts/meaning-vm/main.cpp
index 8fb4c64..7381da2 100644
--- a/starts/meaning-vm/main.cpp
+++ b/starts/meaning-vm/main.cpp
@@ -7,6 +7,6 @@ using namespace std;
int main()
{
- cid concept = "concept"_c;
- cout << str(concept) << endl;
+ ref concept = "concept";
+ cout << string(concept) << endl;
}
diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile
index eb47570..9796f88 100644
--- a/starts/meaning-vm/makefile
+++ b/starts/meaning-vm/makefile
@@ -1,4 +1,7 @@
-CXXFLAGS=-std=c++11 -ggdb
+CXXFLAGS=-std=c++14 -ggdb
+LINK.o=$(LINK.cc)
-main: main.cpp
-aain.cpp: *.hpp
+main: main.o concept.o helpers.o
+%.o: *.hpp
+clean:
+ -rm *.o main