From dd35e6f5cf4bda4ae17d7611fbc138fdbdf60c8b Mon Sep 17 00:00:00 2001
From: olpc user <olpc@xo-5d-f7-86.localdomain>
Date: Fri, 22 Nov 2019 18:30:17 -0800
Subject: syntax sugar for assigning anonymous to name

---
 starts/meaning-vm/concept.cpp | 14 ++++++++++++++
 starts/meaning-vm/concept.hpp |  1 +
 starts/meaning-vm/helpers.cpp | 44 ++++++++++++++++++++++++++++++++++++-------
 starts/meaning-vm/helpers.hpp |  2 ++
 starts/meaning-vm/main.cpp    | 24 +++++++----------------
 5 files changed, 61 insertions(+), 24 deletions(-)

(limited to 'starts')

diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/concept.cpp
index c46b058..c064ed4 100644
--- a/starts/meaning-vm/concept.cpp
+++ b/starts/meaning-vm/concept.cpp
@@ -58,3 +58,17 @@ void concept::unlink(ref type, ref target)
 	}
 	throw std::out_of_range("no such concept link to erase");
 }
+
+void concept::unlink(ref type)
+{
+	auto ls = links.equal_range(type.ptr);
+	if (ls.first == ls.second) {
+		throw std::out_of_range("no such concept link to erase");
+	}
+	auto mid = ls.first;
+	++ mid;
+	if (mid != ls.second) {
+		throw std::out_of_range("more than one link of type to erase");
+	}
+	links.erase(ls.first);
+}
diff --git a/starts/meaning-vm/concept.hpp b/starts/meaning-vm/concept.hpp
index 4d73770..e5cddec 100644
--- a/starts/meaning-vm/concept.hpp
+++ b/starts/meaning-vm/concept.hpp
@@ -66,6 +66,7 @@ struct concept
 	array getAll(ref type);
 	void link(ref type, ref target);
 	void unlink(ref type, ref target);
+	void unlink(ref type);
 };
 
 template <typename T>
diff --git a/starts/meaning-vm/helpers.cpp b/starts/meaning-vm/helpers.cpp
index 8c8618d..dae149f 100644
--- a/starts/meaning-vm/helpers.cpp
+++ b/starts/meaning-vm/helpers.cpp
@@ -9,16 +9,38 @@ ref operator-(ref a, ref b)
 	return ref(a.name() + "-" + b.name());
 }
 
-ref ref::operator=(ref other)
+ref ref::operator=(ref that)
 {
-	// if this is not anonymous, and other is, then we are naming it
-	/*declrefs(anonymous);
-	if (other->linked(anonymous, true) && !ptr->linked(anonymous, true)) {
-		return;
-	}*/
+	// if this is not anonymous, and that is, then we are naming it
+	declrefs(anonymous, name, is);
+	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);
+		dealloc(nam);
+		if (!donealready) {
+			ptr->links.insert(that->links.begin(), that->links.end());
+		}
+		dealloc(that);
+		return *this;
+	}
+
 	// if this is link-type, make new concept [not checked, might want to assume]
 	ref ret = alloc();
-	ret->link(*this, other);
+	ret->link(*this, that);
 	return ret;
 }
 
@@ -81,10 +103,18 @@ ref a(ref what)
 	declrefs(is, anonymous);
 	return ref(what.name() + "-" + std::to_string(gid++))[is = what, anonymous = true];
 }
+ref a(ref what, ref name)
+{
+	return name = a(what);
+}
 ref an(ref what)
 {
 	return a(what);
 }
+ref an(ref what, ref name)
+{
+	return a(what, name);
+}
 
 bool ref::isa(ref what) const
 {
diff --git a/starts/meaning-vm/helpers.hpp b/starts/meaning-vm/helpers.hpp
index 103e826..eca2479 100644
--- a/starts/meaning-vm/helpers.hpp
+++ b/starts/meaning-vm/helpers.hpp
@@ -53,3 +53,5 @@ ref operator-(ref a, ref b);
 
 ref a(ref what);
 ref an(ref what);
+ref a(ref what, ref name);
+ref an(ref what, ref name);
diff --git a/starts/meaning-vm/main.cpp b/starts/meaning-vm/main.cpp
index f8e4ec0..c4207cb 100644
--- a/starts/meaning-vm/main.cpp
+++ b/starts/meaning-vm/main.cpp
@@ -35,28 +35,18 @@ int main()
 	declrefs(trueness, truth, what, not);
 
 	declrefs(add, unique, habit, needs, assumes, makes);
-	A[is = variable];
-	B[is = variable];
-	C[is = variable];
+	A = a(variable);
+	B = a(variable);
+	C = a(variable);
 
 	// add a new unique link to a concept
 	// given A, B, C
 	// and assuming A is not linked by B to C,
 	// makes A be linked by B to C.
-	
-	// would like to do A = a(variable);
-	// 	solution might be to tag anons as such, and take them with a condition in operator=
-	// since we want to return a ref, change [is=variable] to use refs.  this means learning
-	// to delete them, which means checking if they are used or not.
-	// 	where do we put the deleting?
-	// 	right now helpers is doing memory.  maybe instead we can have a memory class.
-	// 	ideally memory is handled by a concept.
-	// 	let's make a pool of concepts?
-	(add-link-unique)[
-		is = habit,
-		needs = A, needs = B, needs = C,
-		makes = (abc-linked)[is = link, link-source = A, link-type = B, link-target = C],
-		assumes = (abc-not-linked)[is = trueness, what = abc-linked, truth = false]
+	add-link-unique = a(habit)[
+		needs = a(variable, A), needs = a(variable, B), needs = a(variable, C),
+		makes = a(link, abc-linked)[link-source = A, link-type = B, link-target = C],
+		assumes = a(trueness, abc-not-linked)[what = abc-linked, truth = false]
 	];
 
 	dumpconcept(add-link-unique);
-- 
cgit v1.2.3