summaryrefslogtreecommitdiff
path: root/starts/meaning-vm/helpers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'starts/meaning-vm/helpers.cpp')
-rw-r--r--starts/meaning-vm/helpers.cpp284
1 files changed, 201 insertions, 83 deletions
diff --git a/starts/meaning-vm/helpers.cpp b/starts/meaning-vm/helpers.cpp
index e29962b..da1a974 100644
--- a/starts/meaning-vm/helpers.cpp
+++ b/starts/meaning-vm/helpers.cpp
@@ -4,74 +4,111 @@
#include "memorystore.hpp"
#include <unordered_map>
+#include <functional>
+
+// sometimes we use an assignment as an expression.
+// is there any reason not to support this?
+// well, we would evaluate the assignment when it is converted to a ref
+// and currently that is used for something else
+// what is it used for?
+// I don't remember ... the assignment is destroyed and unevaluated, so it's likely
+// throughout the internal implemntation
+// it's used for the comma operator, which doesn't want evaluation.
+// okay, hmm.
+// well, if we wanted to support this, we could change the comma operator to not do the
+// conversion. use some other trick.
+// [ ] change comma operator to not do conversion: instead take statementcallref object
+// [ ] change statementcallref::operator ref() to evaluate and return the statement
+// since we're accumulating more possible bugs, let's think about design.
+// really, ref should be different from syntax sugar. we should have a special syntax sugar
+// object, and it should not use its own functions at all. that means not using meaning functions
+// that use them eiher.
+// work also brings to light how the product will be made in layers, with each layer using more interdependence and automatic meaning, etc, than the lower one.
+// layer0 is raw references and allocations
+// layer1 is very core meaning
+// layer2 is very core syntax sugar
+// each layer can only use layers below it.
+
+// concept names are for bootstrapping convenience,
+// to make hardcoding structures easier.
+// hence there is just one single list of them
+std::unordered_map<std::string,concept*,std::hash<std::string>,std::equal_to<std::string>> conceptsByName;
+
+struct name_t : public ref
+{
+ name_t();
+} name;
+
+static ref statement_function("statement-function");
+static ref statement_evaluated("statement-evaluated");
+static ref true_ref("true");
+static ref false_ref("false");
ref operator-(ref a, ref b)
{
return ref(a.name() + "-" + b.name());
}
-statementevaluable ref::operator=(ref that)
+statementcallref 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());
- }
+ statementcallref ret(assign-expression, [](ref expr){
+ declrefs(link, target, unknown, source, type);
+ decllnks(value, to);
+ lnks(link-target, link-type, link-source);
+ decllnks(name, is, anonymous);
+ 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);
+ expr->unlink(to, lhs);
+ dealloc(lhs);
+ } 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");
+ donealready = true;
+ }
+ rhs->unlink(anonymous, true);
+ auto nam = rhs->get(name);
+ rhs->unlink(name, nam);
+ if (!donealready) {
+ lhs->links.insert(rhs->links.begin(), rhs->links.end());
}
+ rhs->link(name, nam);
+ expr->unlink(value, rhs);
+ dealloc(rhs);
+ dealloc(nam);
+ } else {
+ throw std::logic_error("unexpected bare assignment");
}
- }
+ });
+ ret.r->link(to, *this);
+ ret.r->link(value, that);
+ return ret;
/*
decllnks(anonymous, is, name);
declrefs(link, source, type, target, unknown);
@@ -95,49 +132,127 @@ statementevaluable ref::operator=(ref that)
*/
}
-ref ref::operator<<(ref target)
+/*ref ref::operator<<(ref target)
{
// prep a link
ref ret = alloc();
ret->link(*this, target);
return ret;
+}*/
+
+void statementcallref::destatement()
+{
+ auto func = r->get(statement_function);
+ r->unlink(statement_function);
+ dealloc(func);
}
-ref ref::operator[](ref expr) {
- declrefs(assign, expression);
- decllnks(value, to);
- declrefs(link, type, unknown);
+statementcallref::statementcallref(ref type, std::function<void(ref)> func)
+: r(a(type).ptr)
+{
+ r->link(statement_function, valloc<std::function<void(ref)>>(func));
+}
- if (expr.isa(assign-expression)) {
+statementcallref::statementcallref(ref const & that)
+: r(that.ptr)
+{
+ if (!that->linked(statement_function)) {
+ throw std::logic_error(std::string(that) + " has no statement-function");
}
- expr.take();
- ref lhs = expr.get(to);
- ref rhs = expr.get(value);
- if (that.isa(link-type)) {
- return ::link(*this, that, unknown);
- } else {
- ptr->links.insert(that->links.begin(), that->links.end());
- dealloc(that);
- return *this;
+}
+
+statementcallref::operator ref()
+{
+ ref ret(r);
+ destatement();
+ r.ptr = 0;
+ return ret;
+}
+
+#include <iostream>
+statementcallref::~statementcallref() noexcept
+{
+ if (r.ptr == 0) { return; }
+ if (r->linked(statement_evaluated, true_ref)) {
+ std::cerr << "statement already evaluated: " << r << std::endl;
+ return;
}
+ try {
+ auto func = r->vget<std::function<void(ref)>>(statement_function, true);
+ func->data(r);
+ destatement();
+ r->link(statement_evaluated, true_ref);
+ dealloc(r);
+ r.ptr = 0;
+ } catch (std::out_of_range &) { }
}
-ref operator,(ref a, ref b)
+statementcallref::statementcallref(statementcallref && that) noexcept
+: r(that.r.ptr)
{
- a->links.insert(b->links.begin(), b->links.end());
- dealloc(b);
- return a;
+ that.r.ptr = 0;
}
-// concept names are for bootstrapping convenience,
-// to make hardcoding structures easier.
-// hence there is just one single list of them
-std::unordered_map<std::string,concept*,std::hash<std::string>,std::equal_to<std::string>> conceptsByName;
+statementcallref::statementcallref(statementcallref & that)
+: r(that.r.ptr)
+{
+ if (that.r.ptr == 0) { throw std::logic_error("empty ref"); }
+ if (that.r->linked(statement_function)) {
+ // statements are moved, for evaluation
+ that.r.ptr = 0;
+ }
+}
-struct name_t : public ref
+ref ref::operator[](ref expr) {
+ declrefs(assign, comma, expression);
+ decllnks(value, to, what);
+ declrefs(link, type, unknown);
+
+ if (expr.isa(assign-expression)) {
+ ref lhs = expr->get(to);
+ ref rhs = expr->get(value);
+ ptr->link(lhs, rhs);
+ dealloc(expr);
+ return *this;
+ } else if (expr.isa(comma-expression)) {
+ auto parts = expr->getAll(what);
+ dealloc(expr);
+ for (ref part : parts) {
+ if (!part.isa(assign-expression)) {
+ throw std::logic_error("[,] argument is not an assignment");
+ }
+ operator[](part);
+ }
+ return *this;
+ } else if (expr.isa(link-type)) {
+ return ::link(*this, expr, unknown);
+ } else {
+ throw std::logic_error("[] argument is neither a link nor an assignment");
+ }
+}
+
+statementcallref operator,(statementcallref a, statementcallref b)
{
- name_t();
-} name;
+ declrefs(comma, expression);
+ decllnks(what);
+ if (a.r.isa(comma-expression)) {
+ if (b.r.isa(comma-expression)) {
+ a.r->links.insert(b.r->links.begin(), b.r->links.end());
+ dealloc(b); b.r.ptr = 0;
+ } else {
+ a.r->link(what, b.r); b.r.ptr = 0;
+ }
+ return a;
+ } else if (b.r.isa(comma-expression)) {
+ b.r->link(what, a.r); a.r.ptr = 0;
+ return b;
+ } else {
+ statementcallref ret(comma-expression, [](ref) { throw std::logic_error("bare comma-expression"); });
+ ret.r->link(what, a.r); a.r.ptr = 0;
+ ret.r->link(what, b.r); b.r.ptr = 0;
+ return ret;
+ }
+}
template <>
vref<std::string>::vref(std::string const & s)
@@ -146,7 +261,7 @@ vref<std::string>::vref(std::string const & s)
ptr->link(::name, ptr);
}
name_t::name_t()
-: ref(alloc())
+: ref(alloc().ptr)
{
vref nam(std::string("name"));
ptr->link(::name, nam);
@@ -171,7 +286,7 @@ vref<std::string> ref::name() const
{
try {
return ptr->vget<std::string>(::name, true);
- } catch (std::out_of_range) {
+ } catch (std::out_of_range &) {
declrefs(UNNAMED);
return UNNAMED.name();
}
@@ -185,7 +300,10 @@ ref a(ref what)
{
static unsigned long long gid = 0;
decllnks(is, anonymous);
- return ref(what.name() + "-" + std::to_string(gid++))[is = what, anonymous = true];
+ ref ret(what.name() + "-" + std::to_string(gid++));
+ ret->link(is, what);
+ ret->link(anonymous, true);
+ return ret;
}
ref a(ref what, ref name)
{