From 6e81ffa9f5baabe8d4b16fa927ce423fbe26771e Mon Sep 17 00:00:00 2001 From: olpc user Date: Thu, 21 Nov 2019 13:37:18 -0500 Subject: direct cast concept from string --- starts/meaning-vm/concept.cpp | 45 ++++++++++++++++++++++++ starts/meaning-vm/concept.hpp | 82 ++++++++++++++----------------------------- starts/meaning-vm/helpers.cpp | 28 +++++++++++++++ starts/meaning-vm/helpers.hpp | 50 ++------------------------ starts/meaning-vm/main.cpp | 4 +-- starts/meaning-vm/makefile | 9 +++-- 6 files changed, 110 insertions(+), 108 deletions(-) create mode 100644 starts/meaning-vm/concept.cpp create mode 100644 starts/meaning-vm/helpers.cpp (limited to 'starts/meaning-vm') 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 #include -using cid = struct concept *; +struct concept; +template 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 links; - using array = std::vector; - - 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> links; + using array = std::vector; + + 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 struct value : public concept, public T { - static value& of(cid c) + value(T const & val) : T(val) {} + value(value const & val) = default; + static value& of(ref c) { - return *static_cast*>(c); + return *static_cast*>(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 + +// 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,concept,std::hash> conceptsByName; + +ref::ref(std::string s) +{ + try { + ptr = &conceptsByName.at(value(s)); + } catch (std::out_of_range) { + auto insertion = conceptsByName.emplace(value(s), concept()); + ref con = &insertion.first->second; + ref nam = const_cast((concept const *)&insertion.first->first); + namesByConcept.link(con, nam); + ptr = con; + } +} + +ref::operator std::string() +{ + return value::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 : 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(c); - } -}; - -using str = value; - -cid operator"" _c(const char* str, std::size_t len) -{ - return value({str,len}); -} - -#include +#pragma once -concept namesByConcept; -std::unordered_map,concept,std::hash> conceptsByName; - -value::value(std::string s) -: std::string(s) -{ } - -value::value(cid c) -: std::string(of(namesByConcept.get(c))) -{ } - -value::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((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 -- cgit v1.2.3