summaryrefslogtreecommitdiff
path: root/starts/meaning-vm
diff options
context:
space:
mode:
Diffstat (limited to 'starts/meaning-vm')
-rw-r--r--starts/meaning-vm/concept.cpp2
-rw-r--r--starts/meaning-vm/concept.hpp14
-rw-r--r--starts/meaning-vm/helpers.cpp131
-rw-r--r--starts/meaning-vm/helpers.hpp36
-rw-r--r--starts/meaning-vm/main.cpp13
-rw-r--r--starts/meaning-vm/makefile2
-rw-r--r--starts/meaning-vm/meaning.cpp6
-rw-r--r--starts/meaning-vm/memorystore.cpp2
8 files changed, 153 insertions, 53 deletions
diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/concept.cpp
index 03c784f..e9fd8e5 100644
--- a/starts/meaning-vm/concept.cpp
+++ b/starts/meaning-vm/concept.cpp
@@ -28,7 +28,7 @@ ref concept::get(ref type, bool quick)
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());
+ throw std::out_of_range("no such concept link to get: " + (std::string)type.name());
}
}
return result.first->second;
diff --git a/starts/meaning-vm/concept.hpp b/starts/meaning-vm/concept.hpp
index c69ff10..eca2fa5 100644
--- a/starts/meaning-vm/concept.hpp
+++ b/starts/meaning-vm/concept.hpp
@@ -8,6 +8,7 @@
template <typename T> struct vref;
struct concept;
template <typename T> struct value;
+class statementevaluable;
struct ref
{
@@ -24,11 +25,11 @@ struct ref
ref(char const * str) : ref(std::string(str)) { }
ref(bool b) : ref(b ? "true" : "false") { }
ref() : ref("nothing") { }
- value<std::string> & name() const; // this is a reference so that its char pointer lasts
+ vref<std::string> name() const;
operator const char *() const;
// helper linking syntax sugar
- ref operator=(ref that);
+ statementevaluable operator=(ref that);
ref operator<<(ref target);
ref operator[](ref links);
@@ -75,12 +76,17 @@ struct concept
};
template <typename T>
-struct value : public concept, public T
+struct value : public concept
{
- value(T const & val) : T(val) { }
+ value(T const & val) : data(val) { }
value(value<T> const & val) = default;
static value<T>& of(ref c)
{
return *static_cast<value<T>*>(c.ptr);
}
+
+ operator T&() { return data; }
+ operator T const &() const { return data; }
+
+ T data;
};
diff --git a/starts/meaning-vm/helpers.cpp b/starts/meaning-vm/helpers.cpp
index 810d30c..e29962b 100644
--- a/starts/meaning-vm/helpers.cpp
+++ b/starts/meaning-vm/helpers.cpp
@@ -10,52 +10,89 @@ ref operator-(ref a, ref b)
return ref(a.name() + "-" + b.name());
}
-ref ref::operator=(ref that)
+statementevaluable ref::operator=(ref that)
{
+ // for single-line evaluation, we'll need to return a special object
+ declrefs(assign, expression);
+ decllnks(value, to);
+ return {
+ a(assign-expression)[
+ to = *this,
+ value = that
+ ],
+ [](ref expr) {
+ declrefs(link, target, unknown, source, type);
+ decllnks(value, to);
+ lnks(link-target, link-type, link-source);
+ decllnks(name, is);
+ ref lhs = expr.get(to);
+ ref rhs = expr.get(value);
+ if (lhs.isa(link) && lhs->get(link-target) == unknown) {
+ // we are a link missing a target: our assignment is making the link happen
+ lhs->unlink(link-target, unknown);
+ lhs->link(link-target, rhs);
+ ref src = lhs->get(link-source);
+ if (lhs->get(link-type) != unknown && src != unknown) {
+ src->link(lhs->get(link-type), rhs);
+ dealloc(lhs);
+ dealloc(expr);
+ } else {
+ throw std::logic_error("not sure what to do with incomplete link assignment");
+ }
+ } else if (rhs->linked(anonymous, true) && !lhs->linked(anonymous, true)) {
+ // this is assignment of anonymous content to empty named concept
+ bool donealready = false;
+ for (auto & l : lhs->links) {
+ if (ref(l.first) == name) { continue; }
+ if (ref(l.first) == is && ref(l.second) == link-type) { continue; }
+ donealready = true;
+ }
+ if (donealready) {
+ // if we have links, and that has links we do not have, an error has been made
+ for (auto & link : rhs->links) {
+ if (ref(link.first) == anonymous) { continue; }
+ if (ref(link.first) == name) { continue; }
+ if (!lhs->linked(ref(link.first), ref(link.second))) {
+ throw std::logic_error(lhs.name() + " already defined otherwise from " + rhs->get(is).name());
+ }
+ }
+ donealready = true;
+ }
+ rhs->unlink(anonymous, true);
+ auto nam = rhs->get(name);
+ rhs->unlink(name, nam);
+ if (!donealready) {
+ ptr->links.insert(rhs->links.begin(), rhs->links.end());
+ }
+ rhs->link(name, nam);
+ dealloc(rhs);
+ dealloc(nam);
+ } else {
+ throw std::logic_error("unexpected bare assignment");
+ }
+ }
+ }
+/*
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 (that->linked(anonymous, true) && !ptr->linked(anonymous, true)) {
+ // TODO TODO: when left hand side is a link, and right hand side is anonymous,
+ // especially when left hand side is link without other content,
+ // there is no way to determine if user is providing content for link,
+ // or is making a link on another ref[a = b].
+ // instead, return just assignment information, and process in outer context.
+ // will want to make a ref subclass and assign in destructor unless has been used elsewhere.
+
} else if (isa(link-type)) {
// assignment to a link-type is likely inside a [type1=target1,type2=target2] expression
+ // this happens after checking for name assignment because when name assignment
+ // is redundant, the left-hand value could be a link
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) {
- // if we have links, and that has links we do not have, an error has been made
- for (auto & link : that->links) {
- if (ref(link.first) == anonymous) { continue; }
- if (ref(link.first) == name) { continue; }
- if (!ptr->linked(ref(link.first), ref(link.second))) {
- throw std::logic_error(this->name() + " already defined otherwise from " + that->get(is).name());
- }
- }
- donealready = true;
- }
- that->unlink(anonymous, true);
- auto nam = that->get(name);
- that->unlink(name, 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");
+*/
}
ref ref::operator<<(ref target)
@@ -66,8 +103,16 @@ ref ref::operator<<(ref target)
return ret;
}
-ref ref::operator[](ref that) {
+ref ref::operator[](ref expr) {
+ declrefs(assign, expression);
+ decllnks(value, to);
declrefs(link, type, unknown);
+
+ if (expr.isa(assign-expression)) {
+ }
+ expr.take();
+ ref lhs = expr.get(to);
+ ref rhs = expr.get(value);
if (that.isa(link-type)) {
return ::link(*this, that, unknown);
} else {
@@ -122,10 +167,10 @@ ref::ref(std::string const & s)
}
}
-value<std::string> & ref::name() const
+vref<std::string> ref::name() const
{
try {
- return *ptr->vget<std::string>(::name, true).ptr;
+ return ptr->vget<std::string>(::name, true);
} catch (std::out_of_range) {
declrefs(UNNAMED);
return UNNAMED.name();
@@ -133,7 +178,7 @@ value<std::string> & ref::name() const
}
ref::operator const char *() const {
- return name().c_str();
+ return name()->data.c_str();
}
ref a(ref what)
@@ -144,7 +189,11 @@ ref a(ref what)
}
ref a(ref what, ref name)
{
- return name = a(what);
+ if (!name.isa(what)) {
+ decllnks(is);
+ name[is = what];
+ }
+ return name;
}
ref an(ref what)
{
diff --git a/starts/meaning-vm/helpers.hpp b/starts/meaning-vm/helpers.hpp
index 8c7e307..12d1e9c 100644
--- a/starts/meaning-vm/helpers.hpp
+++ b/starts/meaning-vm/helpers.hpp
@@ -27,8 +27,44 @@
// if there is an "is" link to the passed ref.
#include "concept.hpp"
+#include "memorystore.hpp"
#include <sstream>
+inline std::string operator+(vref<std::string> a, char const * b) { return std::string(a) + b; }
+inline std::string operator+(vref<std::string> a, std::string b) { return std::string(a) + b; }
+inline std::string operator+(char const * a, vref<std::string> b) { return a + std::string(b); }
+inline std::string operator+(std::string a, vref<std::string> b) { return a + std::string(b); }
+
+// TODO TODO
+// actually, get rid of this, and set the function as a value on a normal ref.
+// then use ref destructor.
+// have to delete ref copy constructor. use move constructor instead.
+// could also alter ref copy constructor to tell copied ref is okay.
+class statementevaluable : public ref
+{
+public:
+ statementevaluable(ref r, std::function<void(ref)> evaluation)
+ : ref(r.ptr),
+ evaluation(evaluation)
+ { }
+ statementevaluable(statementevaluable const &) = delete;
+ ~statementevaluable() { if (evaluate) { evaluation(*this); } }
+private:
+ std::function<void(ref)> evaluation;
+};
+
+template <>
+vref<std::string>::vref(std::string const &);
+
+template <typename T>
+vref<T>::vref(T const & v)
+: ptr(valloc(v).ptr)
+#include "memorystore.hpp"
+{
+ ptr->link(ref("name"), vref(std::to_string(v)));
+}
+
+
template <typename... T>
void __helper_init_ref_names(std::string names, T &... refrefs)
{
diff --git a/starts/meaning-vm/main.cpp b/starts/meaning-vm/main.cpp
index 6919791..1d25975 100644
--- a/starts/meaning-vm/main.cpp
+++ b/starts/meaning-vm/main.cpp
@@ -29,8 +29,11 @@ void dumpconcept(ref r)
int main()
{
declrefs(make, linked, habit);
- declrefs(A, B, C);
+ declrefs(structure, function, argument, position, provide);
decllnks(needs, assumes, makes);
+ decllnks(A, B, C);
+ decllnks(is);
+ lnks(argument-position);
// add a new unique link to a concept
// given A, B, C
@@ -40,7 +43,13 @@ int main()
// 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)),
+ needs = a(structure)[
+ is = function-argument,
+ argument-position = vref<int>(1),
+ avariable(A) = provide,
+ avariable(B) = provide,
+ avariable(C) = provide
+ ],
assumes = not(A-B-C-linked = link(A, B, C)),
makes = A-B-C-linked
];
diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile
index c037661..7c39de3 100644
--- a/starts/meaning-vm/makefile
+++ b/starts/meaning-vm/makefile
@@ -1,4 +1,4 @@
-CXXFLAGS=-std=c++17 -fno-operator-names -ggdb -O0
+CXXFLAGS=-Wall -Werror -std=c++17 -fno-operator-names -ggdb -O0
LINK.o=$(LINK.cc)
main: main.o concept.o helpers.o memorystore.o meaning.o
diff --git a/starts/meaning-vm/meaning.cpp b/starts/meaning-vm/meaning.cpp
index a47a0ce..a6156bf 100644
--- a/starts/meaning-vm/meaning.cpp
+++ b/starts/meaning-vm/meaning.cpp
@@ -13,9 +13,9 @@ 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
+ link-source << sourceref,
+ link-type << typeref,
+ link-target << targetref
];
}
diff --git a/starts/meaning-vm/memorystore.cpp b/starts/meaning-vm/memorystore.cpp
index 19e40db..9be7ba5 100644
--- a/starts/meaning-vm/memorystore.cpp
+++ b/starts/meaning-vm/memorystore.cpp
@@ -36,7 +36,7 @@ concept* referenced(ref r) {
void dealloc(ref r) {
concept * referenced = ::referenced(r);
if (referenced) {
- throw std::logic_error("concept '" + r.name() + "' is referenced by '" + ref(referenced).name() + '"');
+ throw std::logic_error("concept '" + r.name()->data + "' is referenced by '" + ref(referenced).name()->data + '"');
}
for (
auto it = concepts().begin();