diff options
-rw-r--r-- | starts/meaning-vm/concept.cpp | 45 | ||||
-rw-r--r-- | starts/meaning-vm/concept.hpp | 82 | ||||
-rw-r--r-- | starts/meaning-vm/helpers.cpp | 28 | ||||
-rw-r--r-- | starts/meaning-vm/helpers.hpp | 50 | ||||
-rw-r--r-- | starts/meaning-vm/main.cpp | 4 | ||||
-rw-r--r-- | starts/meaning-vm/makefile | 9 |
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 |