From c699a8913c5c1e53e0b701109dabe2b8fc70b644 Mon Sep 17 00:00:00 2001 From: olpc user Date: Fri, 22 Nov 2019 16:56:03 -0800 Subject: while wip, moved concept storage off of helpers --- starts/meaning-vm/concept.cpp | 2 +- starts/meaning-vm/concept.hpp | 22 +++++++++++++++++- starts/meaning-vm/helpers.cpp | 46 +++++++++++++++++++++++++----------- starts/meaning-vm/main.cpp | 14 ++++++++++- starts/meaning-vm/makefile | 4 ++-- starts/meaning-vm/memorystore.cpp | 49 +++++++++++++++++++++++++++++++++++++++ starts/meaning-vm/memorystore.hpp | 9 +++++++ 7 files changed, 128 insertions(+), 18 deletions(-) create mode 100644 starts/meaning-vm/memorystore.cpp create mode 100644 starts/meaning-vm/memorystore.hpp (limited to 'starts/meaning-vm') diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/concept.cpp index 58d1a7c..825ab5a 100644 --- a/starts/meaning-vm/concept.cpp +++ b/starts/meaning-vm/concept.cpp @@ -24,7 +24,7 @@ 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"); + throw std::out_of_range("no such concept link to get: " + type.name()); } return result.first->second; } diff --git a/starts/meaning-vm/concept.hpp b/starts/meaning-vm/concept.hpp index 2b05f44..7c8fd6d 100644 --- a/starts/meaning-vm/concept.hpp +++ b/starts/meaning-vm/concept.hpp @@ -5,12 +5,14 @@ #include #include +template struct vref; struct concept; template struct value; struct ref { - ref(concept *p) : ptr(p) { } + ref(concept *p) : ptr(p) { if (p == 0) throw std::logic_error("null reference"); } + ref(ref const &) = default; concept* operator->() { return ptr; } // for use by containers @@ -33,6 +35,22 @@ struct ref concept * ptr; }; +template +struct vref +{ + vref(value *p) : ptr(p) { } + value* operator->() { return ptr; } + operator T const &() const { return *ptr; } + + vref(ref const & other) : ptr(static_cast*>(other.ptr)) { } + operator ref() { return ptr; } + + // for use by containers + bool operator<(ref const & other) const { return ptr < other.ptr; } + + value * ptr; +}; + struct concept { // a concept is made of concept-typed links to other concepts @@ -43,6 +61,8 @@ struct concept bool linked(ref type); bool linked(ref type, ref target); ref get(ref type); // returns first + template + vref vget(ref type) { return get(type); } array getAll(ref type); void link(ref type, ref target); void unlink(ref type, ref target); diff --git a/starts/meaning-vm/helpers.cpp b/starts/meaning-vm/helpers.cpp index 99c83dd..1d6d498 100644 --- a/starts/meaning-vm/helpers.cpp +++ b/starts/meaning-vm/helpers.cpp @@ -1,5 +1,7 @@ #include "helpers.hpp" +#include "memorystore.hpp" + #include ref operator-(ref a, ref b) @@ -9,7 +11,12 @@ ref operator-(ref a, ref b) concept ref::operator=(ref other) { - // if this is link-type, make new concept + // if this is not anonymous, and other is, then we are naming it + /*declrefs(anonymous); + if (other->linked(anonymous, true) && !ptr->linked(anonymous, true)) { + return; + }*/ + // if this is link-type, make new concept [not checked, might want to assume] concept ret; ret.link(*this, other); return ret; @@ -31,25 +38,38 @@ concept operator,(concept a, concept b) // 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; +std::unordered_map,ref,std::hash,std::equal_to> conceptsByName; + +struct name_t : public ref +{ + name_t(); +} name; +name_t::name_t() +: ref(alloc()) +{ + auto nam = valloc(std::string("name")); + ptr->link(::name, nam); + conceptsByName.emplace(nam, *this); +} ref::ref(std::string const & 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); + value str(s); + auto res = conceptsByName.find(&str); + if (res != conceptsByName.end()) { + ptr = res->second.ptr; + } else { + ref con = alloc(); + auto nam = valloc(s); + conceptsByName.emplace(nam, con); + con->link(::name, nam); ptr = con.ptr; } } value & ref::name() const { - return value::of(namesByConcept.get(*this)); + return *ptr->vget(::name).ptr; } ref::operator const char *() const { @@ -59,8 +79,8 @@ ref::operator const char *() const { ref a(ref what) { static unsigned long long gid = 0; - declrefs(is); - return ref(what.name() + "-" + std::to_string(gid++))[is = what]; + declrefs(is, anonymous); + return ref(what.name() + "-" + std::to_string(gid++))[is = what, anonymous = true]; } ref an(ref what) { diff --git a/starts/meaning-vm/main.cpp b/starts/meaning-vm/main.cpp index f9f8118..b8d0e02 100644 --- a/starts/meaning-vm/main.cpp +++ b/starts/meaning-vm/main.cpp @@ -7,9 +7,12 @@ using namespace std; void dumpconcept(ref r) { - declrefs(dumped); + declrefs(dumped, name); for (auto & l : r->links) { + if (l.first == name) { + continue; + } cout << r << " " << l.first << " " << l.second << endl; } if (!r->linked(dumped)) { @@ -40,6 +43,15 @@ int main() // given A, B, C // and assuming A is not linked by B to C, // makes A be linked by B to C. + + // would like to do A = a(variable); + // solution might be to tag anons as such, and take them with a condition in operator= + // since we want to return a ref, change [is=variable] to use refs. this means learning + // to delete them, which means checking if they are used or not. + // where do we put the deleting? + // right now helpers is doing memory. maybe instead we can have a memory class. + // ideally memory is handled by a concept. + // let's make a pool of concepts? (add-link-unique)[ is = habit, needs = A, needs = B, needs = C, diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile index a562715..29f07e5 100644 --- a/starts/meaning-vm/makefile +++ b/starts/meaning-vm/makefile @@ -1,7 +1,7 @@ -CXXFLAGS=-std=c++14 -fno-operator-names -ggdb +CXXFLAGS=-std=c++17 -fno-operator-names -ggdb LINK.o=$(LINK.cc) -main: main.o concept.o helpers.o +main: main.o concept.o helpers.o memorystore.o *.o: *.hpp clean: -rm *.o main diff --git a/starts/meaning-vm/memorystore.cpp b/starts/meaning-vm/memorystore.cpp new file mode 100644 index 0000000..0d636ee --- /dev/null +++ b/starts/meaning-vm/memorystore.cpp @@ -0,0 +1,49 @@ +#include "memorystore.hpp" + +#include +#include + +using namespace std; + +std::vector concepts; + +ref alloc(concept * moved) { + ref r = moved ? moved : new concept(); + concepts.push_back(r); + return r; +} + +bool referenced(ref r) { + for (auto & r2 : concepts) { + if (r2 == r) { + continue; + } + for (auto & l : r2->links) { + if (l.first == r) { + return true; + } + if (l.second == r) { + return true; + } + } + } + return false; +} + +void dealloc(ref r) { + if (referenced(r)) { + throw std::logic_error("concept is referenced"); + } + for ( + auto it = concepts.begin(); + it != concepts.end(); + ++ it) + { + if (*it == r) { + concepts.erase(it); + delete r; + return; + } + } + throw std::logic_error("concept not held"); +} diff --git a/starts/meaning-vm/memorystore.hpp b/starts/meaning-vm/memorystore.hpp new file mode 100644 index 0000000..d1ca98d --- /dev/null +++ b/starts/meaning-vm/memorystore.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "concept.hpp" + +ref alloc(concept * moved = 0); +template +vref valloc(T const & val) { return alloc(new value(val)); } +void dealloc(ref); +void dealloc_all(ref); // todo? -- cgit v1.2.3