summaryrefslogtreecommitdiff
path: root/starts
diff options
context:
space:
mode:
Diffstat (limited to 'starts')
-rw-r--r--starts/meaning-vm/concept.cpp2
-rw-r--r--starts/meaning-vm/concept.hpp22
-rw-r--r--starts/meaning-vm/helpers.cpp46
-rw-r--r--starts/meaning-vm/main.cpp14
-rw-r--r--starts/meaning-vm/makefile4
-rw-r--r--starts/meaning-vm/memorystore.cpp49
-rw-r--r--starts/meaning-vm/memorystore.hpp9
7 files changed, 128 insertions, 18 deletions
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 <string>
#include <vector>
+template <typename T> struct vref;
struct concept;
template <typename T> 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 <typename T>
+struct vref
+{
+ vref(value<T> *p) : ptr(p) { }
+ value<T>* operator->() { return ptr; }
+ operator T const &() const { return *ptr; }
+
+ vref(ref const & other) : ptr(static_cast<value<T>*>(other.ptr)) { }
+ operator ref() { return ptr; }
+
+ // for use by containers
+ bool operator<(ref const & other) const { return ptr < other.ptr; }
+
+ value<T> * 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 <typename T>
+ vref<T> 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 <unordered_map>
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<value<std::string>,concept,std::hash<std::string>> conceptsByName;
+std::unordered_map<vref<std::string>,ref,std::hash<std::string>,std::equal_to<std::string>> 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<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);
+ value<std::string> str(s);
+ auto res = conceptsByName.find(&str);
+ if (res != conceptsByName.end()) {
+ ptr = res->second.ptr;
+ } else {
+ ref con = alloc();
+ auto nam = valloc<std::string>(s);
+ conceptsByName.emplace(nam, con);
+ con->link(::name, nam);
ptr = con.ptr;
}
}
value<std::string> & ref::name() const
{
- return value<std::string>::of(namesByConcept.get(*this));
+ return *ptr->vget<std::string>(::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 <list>
+#include <vector>
+
+using namespace std;
+
+std::vector<ref> 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 <typename T>
+vref<T> valloc(T const & val) { return alloc(new value<T>(val)); }
+void dealloc(ref);
+void dealloc_all(ref); // todo?