summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--starts/meaning-vm/concept.cpp9
-rw-r--r--starts/meaning-vm/concept.hpp23
-rw-r--r--starts/meaning-vm/helpers.cpp68
-rw-r--r--starts/meaning-vm/helpers.hpp16
-rw-r--r--starts/meaning-vm/main.cpp30
-rw-r--r--starts/meaning-vm/makefile4
-rw-r--r--starts/meaning-vm/meaning.cpp27
-rw-r--r--starts/meaning-vm/meaning.hpp36
-rw-r--r--starts/meaning-vm/memorystore.cpp13
9 files changed, 176 insertions, 50 deletions
diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/concept.cpp
index c064ed4..03c784f 100644
--- a/starts/meaning-vm/concept.cpp
+++ b/starts/meaning-vm/concept.cpp
@@ -20,11 +20,16 @@ bool concept::linked(ref type, ref target)
return false;
}
-ref concept::get(ref type)
+ref concept::get(ref type, bool quick)
{
+ // this is called by name(), so it passes quick=true
auto result = links.equal_range(type.ptr);
if (result.first == result.second) {
- throw std::out_of_range("no such concept link to get: " + type.name());
+ if (quick) {
+ throw std::out_of_range("no such concept link to get");
+ } else {
+ 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 e5cddec..c69ff10 100644
--- a/starts/meaning-vm/concept.hpp
+++ b/starts/meaning-vm/concept.hpp
@@ -15,19 +15,22 @@ struct ref
ref(ref const &) = default;
concept* operator->() { return ptr; }
bool operator==(ref const & that) const { return this->ptr == that.ptr; }
+ bool operator!=(ref const & that) const { return this->ptr != that.ptr; }
bool operator<(ref const &) const { throw std::logic_error("ref has redefined syntax sugar: do not use in containers"); }
- // for helpers
+ // for helpers, mostly names
ref(std::string const &);
ref(char const * str) : ref(std::string(str)) { }
ref(bool b) : ref(b ? "true" : "false") { }
ref() : ref("nothing") { }
- value<std::string> & name() const;
+ value<std::string> & name() const; // this is a reference so that its char pointer lasts
operator const char *() const;
- ref operator=(ref other); // helper constructs new concept with this as link
- ref operator[](ref links); // helper sets all links from passed concept
+ // helper linking syntax sugar
+ ref operator=(ref that);
+ ref operator<<(ref target);
+ ref operator[](ref links);
bool isa(ref what) const;
bool isan(ref what) const;
@@ -42,11 +45,13 @@ struct vref
value<T>* operator->() { return ptr; }
operator T const &() const { return *ptr; }
- vref(ref const & other) : ptr(static_cast<value<T>*>(other.ptr)) { }
+ vref(T const & val);
+
+ vref(ref const & that) : ptr(static_cast<value<T>*>(that.ptr)) { }
operator ref() { return ptr; }
// for use by containers
- //bool operator<(ref const & other) const { return ptr < other.ptr; }
+ //bool operator<(ref const & that) const { return ptr < that.ptr; }
value<T> * ptr;
};
@@ -60,9 +65,9 @@ struct concept
ref id();
bool linked(ref type);
bool linked(ref type, ref target);
- ref get(ref type); // returns first
+ ref get(ref type, bool quick = false); // returns first
template <typename T>
- vref<T> vget(ref type) { return get(type); }
+ vref<T> vget(ref type, bool quick = false) { return get(type, quick); }
array getAll(ref type);
void link(ref type, ref target);
void unlink(ref type, ref target);
@@ -72,7 +77,7 @@ struct concept
template <typename T>
struct value : public concept, public T
{
- value(T const & val) : T(val) {}
+ value(T const & val) : T(val) { }
value(value<T> const & val) = default;
static value<T>& of(ref c)
{
diff --git a/starts/meaning-vm/helpers.cpp b/starts/meaning-vm/helpers.cpp
index dae149f..810d30c 100644
--- a/starts/meaning-vm/helpers.cpp
+++ b/starts/meaning-vm/helpers.cpp
@@ -1,5 +1,6 @@
#include "helpers.hpp"
+#include "meaning.hpp"
#include "memorystore.hpp"
#include <unordered_map>
@@ -11,9 +12,25 @@ ref operator-(ref a, ref b)
ref ref::operator=(ref that)
{
- // if this is not anonymous, and that is, then we are naming it
- declrefs(anonymous, name, is);
- if (that->linked(anonymous, true) && !ptr->linked(anonymous, true)) {
+ decllnks(anonymous, is, name);
+ declrefs(link, source, type, target, unknown);
+ lnks(link-target, link-source, link-target);
+ if (this->isa(link) && ptr->get(link-target) == unknown) {
+ // we are a link missing a target: our assignment is making the link happen
+ ptr->unlink(link-target, unknown);
+ ptr->link(link-target, that);
+ ref src = ptr->get(link-source);
+ if (ptr->get(link-type) != unknown && src != unknown) {
+ src->link(ptr->get(link-type), ptr->get(link-target));
+ dealloc(ptr);
+ return src;
+ } else {
+ throw std::logic_error("not sure what to do with incomplete link assignment");
+ }
+ } else if (isa(link-type)) {
+ // assignment to a link-type is likely inside a [type1=target1,type2=target2] expression
+ return (*this) << that;
+ } else if (that->linked(anonymous, true) && !ptr->linked(anonymous, true)) {
// this is assignment of anonymous content to empty named concept
bool donealready = false;
if (ptr->links.size() != 1) {
@@ -30,24 +47,34 @@ ref ref::operator=(ref that)
that->unlink(anonymous, true);
auto nam = that->get(name);
that->unlink(name, nam);
- dealloc(nam);
if (!donealready) {
ptr->links.insert(that->links.begin(), that->links.end());
}
+ that->link(name, nam);
dealloc(that);
+ dealloc(nam);
return *this;
}
+ throw std::logic_error("unexpected use of assignment");
+}
- // if this is link-type, make new concept [not checked, might want to assume]
+ref ref::operator<<(ref target)
+{
+ // prep a link
ref ret = alloc();
- ret->link(*this, that);
+ ret->link(*this, target);
return ret;
}
-ref ref::operator[](ref links) {
- ptr->links.insert(links->links.begin(), links->links.end());
- dealloc(links);
- return *this;
+ref ref::operator[](ref that) {
+ declrefs(link, type, unknown);
+ if (that.isa(link-type)) {
+ return ::link(*this, that, unknown);
+ } else {
+ ptr->links.insert(that->links.begin(), that->links.end());
+ dealloc(that);
+ return *this;
+ }
}
ref operator,(ref a, ref b)
@@ -66,10 +93,17 @@ struct name_t : public ref
{
name_t();
} name;
+
+template <>
+vref<std::string>::vref(std::string const & s)
+: ptr(valloc(s).ptr)
+{
+ ptr->link(::name, ptr);
+}
name_t::name_t()
: ref(alloc())
{
- auto nam = valloc(std::string("name"));
+ vref nam(std::string("name"));
ptr->link(::name, nam);
conceptsByName.emplace(nam, ptr);
}
@@ -81,7 +115,7 @@ ref::ref(std::string const & s)
ptr = res->second;
} else {
ref con = alloc();
- auto nam = valloc<std::string>(s);
+ vref<std::string> nam(s);
conceptsByName.emplace(nam, con.ptr);
con->link(::name, nam);
ptr = con.ptr;
@@ -90,7 +124,12 @@ ref::ref(std::string const & s)
value<std::string> & ref::name() const
{
- return *ptr->vget<std::string>(::name).ptr;
+ try {
+ return *ptr->vget<std::string>(::name, true).ptr;
+ } catch (std::out_of_range) {
+ declrefs(UNNAMED);
+ return UNNAMED.name();
+ }
}
ref::operator const char *() const {
@@ -100,7 +139,7 @@ ref::operator const char *() const {
ref a(ref what)
{
static unsigned long long gid = 0;
- declrefs(is, anonymous);
+ decllnks(is, anonymous);
return ref(what.name() + "-" + std::to_string(gid++))[is = what, anonymous = true];
}
ref a(ref what, ref name)
@@ -121,6 +160,7 @@ bool ref::isa(ref what) const
declrefs(is);
for (auto group : ptr->getAll(is)) {
if (group == what) return true;
+ if (group == *this) continue;
if (group.isa(what)) return true;
}
return false;
diff --git a/starts/meaning-vm/helpers.hpp b/starts/meaning-vm/helpers.hpp
index eca2479..8c7e307 100644
--- a/starts/meaning-vm/helpers.hpp
+++ b/starts/meaning-vm/helpers.hpp
@@ -48,6 +48,22 @@ void __helper_init_ref_names(std::string names, T &... refrefs)
ref __VA_ARGS__; \
__helper_init_ref_names(#__VA_ARGS__, __VA_ARGS__)
+template <typename... T>
+void lnks(T ... passedrefs)
+{
+ std::initializer_list<ref> refs = { passedrefs... };
+ declrefs(link, type, is);
+ for (ref r : refs) {
+ if (!r->linked(is, link-type)) {
+ r->link(is, link-type);
+ }
+ }
+}
+
+#define decllnks(...) \
+ declrefs(__VA_ARGS__); \
+ lnks(__VA_ARGS__)
+
ref operator,(ref a, ref b);
ref operator-(ref a, ref b);
diff --git a/starts/meaning-vm/main.cpp b/starts/meaning-vm/main.cpp
index c4207cb..6919791 100644
--- a/starts/meaning-vm/main.cpp
+++ b/starts/meaning-vm/main.cpp
@@ -1,5 +1,6 @@
#include "concept.hpp"
#include "helpers.hpp"
+#include "meaning.hpp"
using namespace std;
@@ -7,7 +8,7 @@ using namespace std;
void dumpconcept(ref r)
{
- declrefs(dumped, name);
+ decllnks(dumped, name);
for (auto & l : r->links) {
if (ref(l.first) == name) {
@@ -27,27 +28,22 @@ void dumpconcept(ref r)
int main()
{
- declrefs(is, link, type);
- is->link(is, link-type);
-
- declrefs(source, target);
- declrefs(linked, A, B, C, abc, variable);
- declrefs(trueness, truth, what, not);
-
- declrefs(add, unique, habit, needs, assumes, makes);
- A = a(variable);
- B = a(variable);
- C = a(variable);
+ declrefs(make, linked, habit);
+ declrefs(A, B, C);
+ decllnks(needs, assumes, makes);
// add a new unique link to a concept
// given A, B, C
// and assuming A is not linked by B to C,
// makes A be linked by B to C.
- add-link-unique = a(habit)[
- needs = a(variable, A), needs = a(variable, B), needs = a(variable, C),
- makes = a(link, abc-linked)[link-source = A, link-type = B, link-target = C],
- assumes = a(trueness, abc-not-linked)[what = abc-linked, truth = false]
+ // NEXT? make code for make-linked that takes a ref
+ // change the needs structure to use a model for the ref,
+ // with needed values specified as 'provided'
+ make-linked = a(habit)[
+ needs = and(avariable(A), avariable(B), avariable(C)),
+ assumes = not(A-B-C-linked = link(A, B, C)),
+ makes = A-B-C-linked
];
- dumpconcept(add-link-unique);
+ dumpconcept(make-linked);
}
diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile
index 29f07e5..c037661 100644
--- a/starts/meaning-vm/makefile
+++ b/starts/meaning-vm/makefile
@@ -1,7 +1,7 @@
-CXXFLAGS=-std=c++17 -fno-operator-names -ggdb
+CXXFLAGS=-std=c++17 -fno-operator-names -ggdb -O0
LINK.o=$(LINK.cc)
-main: main.o concept.o helpers.o memorystore.o
+main: main.o concept.o helpers.o memorystore.o meaning.o
*.o: *.hpp
clean:
-rm *.o main
diff --git a/starts/meaning-vm/meaning.cpp b/starts/meaning-vm/meaning.cpp
new file mode 100644
index 0000000..a47a0ce
--- /dev/null
+++ b/starts/meaning-vm/meaning.cpp
@@ -0,0 +1,27 @@
+#include "meaning.hpp"
+
+#include "helpers.hpp"
+
+ref avariable(ref name)
+{
+ declrefs(variable);
+ return a(variable, name);
+}
+
+ref link(ref sourceref, ref typeref, ref targetref)
+{
+ declrefs(link, source, type, target);
+ lnks(link-source, link-type, link-target);
+ return a(link)[
+ link-source = sourceref,
+ link-type = typeref,
+ link-target = targetref
+ ];
+}
+
+ref not(ref whatref)
+{
+ declrefs(not);
+ decllnks(what);
+ return a(not, not-whatref)[what] = whatref;
+}
diff --git a/starts/meaning-vm/meaning.hpp b/starts/meaning-vm/meaning.hpp
new file mode 100644
index 0000000..c358d69
--- /dev/null
+++ b/starts/meaning-vm/meaning.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "concept.hpp"
+#include "helpers.hpp"
+
+// get a named variable
+ref avariable(ref name);
+
+template <typename... T>
+ref and(T... refs)
+{
+ std::initializer_list<ref> rs = { refs... };
+ declrefs(and);
+ decllnks(what);
+ ref ret = a(and);
+ ref name; int count = 0;
+ for (auto r : rs) {
+ ret[what] = r;
+ if (count == 0) {
+ name.ptr = r.ptr;
+ } else {
+ name.ptr = (name-and-r).ptr;
+ }
+ ++ count;
+ }
+ if (count == 1) {
+ throw std::logic_error("and needs at least two subjects");
+ }
+ return name = ret;
+}
+
+// make a reference to a link
+ref link(ref sourceref, ref typeref, ref targetref);
+
+// invert a meaning
+ref not(ref whatref);
diff --git a/starts/meaning-vm/memorystore.cpp b/starts/meaning-vm/memorystore.cpp
index c759051..19e40db 100644
--- a/starts/meaning-vm/memorystore.cpp
+++ b/starts/meaning-vm/memorystore.cpp
@@ -16,26 +16,27 @@ ref alloc(concept * moved) {
return r;
}
-bool referenced(ref r) {
+concept* referenced(ref r) {
for (ref r2 : concepts()) {
if (r2 == r) {
continue;
}
for (auto & l : r2->links) {
if (ref(l.first) == r) {
- return true;
+ return r2.ptr;
}
if (ref(l.second) == r) {
- return true;
+ return r2.ptr;
}
}
}
- return false;
+ return 0;
}
void dealloc(ref r) {
- if (referenced(r)) {
- throw std::logic_error("concept is referenced");
+ concept * referenced = ::referenced(r);
+ if (referenced) {
+ throw std::logic_error("concept '" + r.name() + "' is referenced by '" + ref(referenced).name() + '"');
}
for (
auto it = concepts().begin();