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.cpp131
1 files changed, 90 insertions, 41 deletions
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)
{