diff options
Diffstat (limited to 'starts/meaning-vm')
-rw-r--r-- | starts/meaning-vm/concept.cpp | 2 | ||||
-rw-r--r-- | starts/meaning-vm/concept.hpp | 14 | ||||
-rw-r--r-- | starts/meaning-vm/helpers.cpp | 131 | ||||
-rw-r--r-- | starts/meaning-vm/helpers.hpp | 36 | ||||
-rw-r--r-- | starts/meaning-vm/main.cpp | 13 | ||||
-rw-r--r-- | starts/meaning-vm/makefile | 2 | ||||
-rw-r--r-- | starts/meaning-vm/meaning.cpp | 6 | ||||
-rw-r--r-- | starts/meaning-vm/memorystore.cpp | 2 |
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(); |