diff options
Diffstat (limited to 'starts/meaning-vm/helpers.cpp')
-rw-r--r-- | starts/meaning-vm/helpers.cpp | 131 |
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) { |