From 94ed7bbaa739995a9815b5f1c916d9e24575368c Mon Sep 17 00:00:00 2001
From: olpc user <olpc@xo-5d-f7-86.localdomain>
Date: Thu, 26 Dec 2019 16:34:28 -0800
Subject: level2 compiles, nothing visible yet

---
 starts/meaning-vm/habit-starts/rhythm.cpp |   2 +-
 starts/meaning-vm/level-2/habits.cpp      |  70 +++++++++----
 starts/meaning-vm/level-2/habits.hpp      | 159 ++++++++++++++++++++++++++++++
 starts/meaning-vm/level-2/sugar.cpp       |  32 ++++++
 starts/meaning-vm/level-2/sugar.hpp       |  26 ++---
 starts/meaning-vm/level2.cpp              |  45 +++++++++
 starts/meaning-vm/makefile                |   4 +-
 7 files changed, 301 insertions(+), 37 deletions(-)
 create mode 100644 starts/meaning-vm/level-2/sugar.cpp

(limited to 'starts')

diff --git a/starts/meaning-vm/habit-starts/rhythm.cpp b/starts/meaning-vm/habit-starts/rhythm.cpp
index 72626d6..01a42d9 100644
--- a/starts/meaning-vm/habit-starts/rhythm.cpp
+++ b/starts/meaning-vm/habit-starts/rhythm.cpp
@@ -119,7 +119,7 @@ int main()
 #endif
 	ahabit(wait-habit, (),
 	{
-		usleep(micros);
+		sugar::usleep(micros);
 	});
 
 	(keep-doing-habit)(start-beat);
diff --git a/starts/meaning-vm/level-2/habits.cpp b/starts/meaning-vm/level-2/habits.cpp
index 4900daf..266d412 100644
--- a/starts/meaning-vm/level-2/habits.cpp
+++ b/starts/meaning-vm/level-2/habits.cpp
@@ -13,6 +13,16 @@ int createhabits()
 		s.link(t, dst);
 	});
 
+	ahabit(link-crucial, ((souce, s), (type, t), (target, dst)),
+	{
+		result = s.crucial(t, dst);
+	});
+
+	ahabit(link-set-crucial, ((source, s), (type, t), (target, dst)),
+	{
+		s.setcrucial(t, dst);
+	});
+
 	decls(linked, anything);
 	ahabit(linked, ((source, s), (type, t), (target, dst, anything)),
 	{
@@ -66,6 +76,14 @@ int createhabits()
 	{
 		intellect::level0::basic_dealloc(c);
 	});
+	ahabit(concept-crucial, ((concept, c)),
+	{
+		result = c.crucial();
+	});
+	ahabit(concept-set-crucial, ((concept, c)),
+	{
+		c.setcrucial();
+	});
 
 	decls(habit, context);
 	ahabit(know-is, ((concept, c), (group, g)),
@@ -138,6 +156,20 @@ int createhabits()
 	{
 		return lea.val<links_it>() == leb.val<links_it>();
 	});
+	ahabit(link-entry-unlink, ((link-entry, le)),
+	{
+		le.get(source).unlink(le.val<links_it>()++);
+		(populate-link-entry)(le);
+		result = le;
+	});
+	ahabit(link-entry-crucial, ((link-entry, le)),
+	{
+		result = le.get(source).crucial(le.val<links_it>());
+	});
+	ahabit(link-entry-set-crucial, ((link-entry, le)),
+	{
+		le.get(source).setcrucial(le.val<links_it>());
+	});
 
 	// a simple list primitive to aid in dev
 	decls(list, nothing, next, previous, first, last, act);
@@ -185,6 +217,8 @@ int createhabits()
 			l.set(last-item, le);
 			prev.set(next, le);
 		}
+
+		result = list;
 	});
 	ahabit(list-entry-unmake, ((list-entry, le)),
 	{
@@ -197,15 +231,19 @@ int createhabits()
 			set(n, previous, prev);
 		}
 		(concept-unmake)(le);
+		result = n;
 	});
 
-	ahabit(list-each-entry, ((list, l), (context, c), (action, act)),
-	{
-		ref cur = (list-first-entry)(l);
-		while (cur != nothing && result == nothing) {
-			result = act(cur, c);
-			cur = (list-next-entry)(cur);
+	ahabit(list-each-entry, ((list, l), (context, c), (action, a)),
+	{
+		ref subctx = (make-concept());
+		subctx.set(context, c);
+		subctx.set(list-entry, (list-first-entry)(l));
+		while (subctx.get(list-entry) != nothing && result == nothing) {
+			result = act(a, subctx);
+			subctx.set(list-entry, (list-entry-next)(subctx.get(list-entry)));
 		}
+		(unmake-concept)(subctx);
 	});
 	ahabit(list-has-item, ((list, l), (item, i)),
 	{
@@ -260,6 +298,7 @@ int createhabits()
 	{
 		if (linked(act, is, habit) && !linked(act, habit)) {
 			act.fun<ref>()(subctx);
+			result = subctx.get("result");
 		} else if (linked(act, habit) && linked(get(act, habit), is, habit)) {
 			ref h = get(act, habit);
 			if (linked(h, habit)) {
@@ -275,9 +314,10 @@ int createhabits()
 					"action", act
 				);
 				self(h, subctx2);
+				result = subctx2.get("result");
 				(unmake-concept)(subctx2);
 			} else {
-				h({{context, subctx}, {action, act}});
+				result = h({{context, subctx}, {action, act}});
 			}
 		} else {
 			throw (make-concept)().link(
@@ -297,7 +337,7 @@ int createhabits()
 				made-information-map, out,
 				action, act);
 	});
-	ahabit(context-action, ((outer-context, outerctx), (context-action, ca)),
+	ahabit(context-action, ((context, outerctx), (action, ca)),
 	{
 
 		ref action = ca["action"];
@@ -339,24 +379,12 @@ int createhabits()
 			(action-list-item)(list-entry-item(le), subctx);
 		});
 
-	// maybe condition and list could be merged better by factoring out the concept
-	// of translating?
-	// 	we're going to want to provide lists of subactions to condition
-	// 	the irritation around not having the condition be a function is the
-	// 	creation of anonymous variable names to hold the values.  is likely fine.
-	// 	note: the name "outer-context" is being treated specially.  we'll just use that.
-	// 		this name could make a quoting requirement.  could be worked around.
-	//
-	// 		if we remove outer-context, we'll probably need to recognize condition-
-	// 		action in action-list-item, and pass the outer-context to it.
-	// 		either way, we can implement condition-action with outer-context as
-	// 		a passed value.
-	
 	ahabit(nothing, (), {});
 	link(nothing, habit, nothing);
 
 	// does acts[cond] in outer-context.
 	// uses acts[anything] if there is no acts[cond].
+	
 	ahabit(condition-action, ((condition, cond), (actions, acts)),
 	{
 		ref outerctx = linked(ctx, "outer-context") ? ctx["outer-context"] : ctx;
diff --git a/starts/meaning-vm/level-2/habits.hpp b/starts/meaning-vm/level-2/habits.hpp
index 0bff7f7..b416ee0 100644
--- a/starts/meaning-vm/level-2/habits.hpp
+++ b/starts/meaning-vm/level-2/habits.hpp
@@ -1,10 +1,169 @@
+#pragma once
+
 #include "common.hpp"
+#include "ref.hpp"
+#include "concepts.hpp"
 
 namespace intellect {
 namespace level2 {
 
 void ensurehabitscreated(); // for running from static code, for construction order
 
+namespace concepts {
+
+	// make a link
+	// link(source, type, target)
+	static ref link("link");
+
+	// get if a link is permanent
+	// result = (link-crucial)(source, type, target)
+	static ref crucial("crucial");
+	
+	// set a link to be permanent
+	// (link-set-crucial)(source, type, target)
+	static ref set("set");
+
+	// get if a link exists
+	// result = linked(source, type, target? = anything)
+	static ref linked("linked");
+
+	// remove a link
+	// unlink(source, type, target)
+	static ref unlink("unlink");
+
+	// get a link target by type
+	// result = get(source, type)
+	static ref get("get");
+
+	// set a link target, replacing an existing type if needed
+	// set(source, type, target)
+
+	// produce a totally new, empty concept, with no links to or from
+	// result = (make-concept)()
+	static ref make("make"), concept("concept");
+
+	// produce a new concept by copying links and data from an old concept.
+	// nothing will link to new concept.
+	// result = (make-copy)(concept)
+	static ref copy("copy");
+
+	// destroy a concept forever, for handling temporary data.
+	// this will fail if the concept is set to be crucial, or is in use.
+	// (concept-unmake)(concept)
+	static ref unmake("unmake");
+
+	// get if a concept is set to be crucial
+	// result = (concept-crucial)(concept)
+	
+	// set a concept to be crucial
+	// r(concept-set-crucial)(concept)
+	
+	// place a concept in a new group.
+	// forms a new link of type 'is', fails if one aleady exists
+	// concept = (know-is)(concept, group)
+	static ref know("know"), is("is")  ;
+
+	// fill any concept with information about the first link entry in a concept
+	// if there is a link in the entry, then [type] and [target] will be present
+	// link-entry = (know-is-first-link-entry)(link-entry, concept)
+	static ref first("first"), entry("entry");
+
+	// fill any concept with information about the last link entry in a concept
+	// link-entry = (know-is-last-link-entry)(link-entry, concept)
+	static ref last("last");
+
+	// change a link entry concept to be about the next link in the concept
+	// link-entry = (next-link-entry)(link-entry)
+
+	// change a link entry concept to be about the previous link in the concept
+	// link-entry = (previous-link-entry)(link-entry)
+	static ref previous("previous");
+
+	// get if two link entry concepts refer to the same link entry
+	// result = (same-link-entry)(link-entry-A, link-entry-B)
+	static ref same("same");
+
+	// remove a link entry from a concept
+	// the entry will be about the next one, after the action
+	// link-entry = (link-entry-unlink)(link-entry)
+	
+	// get if a link entry is set to be crucial
+	// result = (link-entry-crucial)(link-entry)
+	
+	// set a link entry to be crucial & permanent
+	// (link-entry-set-crucial)(link-entry)
+	
+	// add links to a concept facilitating use as a list
+	// list = (know-is-list)(list)
+	static ref list("list");
+
+	// get the first list-entry of a list
+	// result = (list-first-entry)(list)
+	
+	// get the last list-entry of a list
+	// result = (list-last-entry)(list)
+	
+	// get a subsequent list-entry
+	// result = (list-entry-next)(list-entry)
+	
+	// get a preceding list-entry
+	// result = (list-entry-previous)(list-entry)
+	
+	// get the item associated with a list-entry
+	// result = (list-entry-item)(list-entry)
+	static ref item("item");
+
+	// make a new entry in a list, holding an item concept
+	// list = (make-next-list-entry)(list, item)
+	
+	// destroy forever an entry in a list.  for lists of temporaries.
+	// the result is the next entry.
+	// result = (list-entry-unmake)(list-entry, le)
+	
+	// action(list-entry, context) for every entry in a list until result made
+	// result = (list-each-entry)(list, context, action)
+	static ref each("each");
+
+	// get if a list has an item in it
+	// result = (list-has-item)(list, item)
+	static ref has("has");
+
+	// destroy forever an entry in its list, by the item it contains
+	// for lists of temporaries
+	// true = (list-item-entry-unmake)(list, item)
+	
+	// the .act level-2 member function can ease list creation.
+	// it passes itself as the first argument to a habit
+	// (make-concept)().act(know-is-list)
+	// 	.act(make-next-list-entry, i1)
+	// 	.act(make-next-list-entry, i2)
+	// 	...;
+	
+	// make a concept holding an item in a translation map
+	// result = (make-map-item)(source, target)
+	static ref map("map");
+
+	// make a contextual subcontext for an action
+	// the maps are lists of translation map items
+	// result = (make-context-action)(needed-information-map, made-information-map, action)
+	static ref action("action");
+
+	// condition do one of multiple possible actions
+	// looks up actions[condition] and does that.
+	// does actions[anything] if nothing matches.
+	// result = (condition-action)(condition, actions)
+	static ref condition("condition");
+
+	// action handlers
+	// calls anything with a 'habit' handler: act(action, context)
+	// 	for action is habit: provides context as full context
+	// 	for action has habit: calls habit with unordered (context, action)
+	// 		recursively handles if habit itself has habit to handle it.
+	// the habit of habits, calls a habit: habit(context, action)
+	// the habit of context-actions, calls a subcontextual action: (context-action)(context, action)
+	// the habit of action lists, calls a list of actions: (action-list)(context, action)
+	// the habit of 'nothing', does nothing: (nothing)()
+}
 
 }
 }
diff --git a/starts/meaning-vm/level-2/sugar.cpp b/starts/meaning-vm/level-2/sugar.cpp
new file mode 100644
index 0000000..2a86cca
--- /dev/null
+++ b/starts/meaning-vm/level-2/sugar.cpp
@@ -0,0 +1,32 @@
+#include "sugar.hpp"
+
+#include <stdlib.h> // int rand(); void srand(int seed);
+#include <time.h> // int time(0); int clock_gettime(CLOCK_REALTIME, struct timespec *tp{tv_sec,tv_nsec})
+#include <unistd.h> // usleep(unsigned int usecs)
+
+namespace intellect {
+namespace level2 {
+namespace sugar {
+
+double rand(double min, double max)
+{
+	// seed random number generator statically, for habit delay
+	static struct timespec tp;
+	static int seed = (
+			clock_gettime(CLOCK_REALTIME, &tp),
+			srand(tp.tv_nsec),
+			tp.tv_nsec
+	);
+	(void)(seed);
+
+	return double(::rand()) / RAND_MAX * (max - min) + min;
+}
+
+void usleep(unsigned int usecs)
+{
+	::usleep(usecs);
+}
+
+}
+}
+}
diff --git a/starts/meaning-vm/level-2/sugar.hpp b/starts/meaning-vm/level-2/sugar.hpp
index adedaa9..04393a1 100644
--- a/starts/meaning-vm/level-2/sugar.hpp
+++ b/starts/meaning-vm/level-2/sugar.hpp
@@ -1,11 +1,15 @@
 #pragma once
 
-#include <stdlib.h> // int rand(); void srand(int seed);
-#include <time.h> // int time(0); int clock_gettime(CLOCK_REALTIME, struct timespec *tp{tv_sec,tv_nsec})
-#include <unistd.h> // usleep(unsigned int usecs)
-
 #undef self
 
+namespace intellect {
+namespace level2 {
+
+namespace sugar {
+	void usleep(unsigned int usecs);
+	double rand(double min, double max);
+}
+
 // habits have a structure such that they contain information about their positional
 // arguments.  they are made with a macro that turns the args into local variables.
 // the function to call them takes any number of arguments, and these are placed in the
@@ -28,8 +32,8 @@
 	[&](ref ctx) \
 	{ \
 		{ \
-			static int delay = (double(rand()) / RAND_MAX * 400000 + 200000); \
-			usleep(delay); \
+			static int delay = sugar::rand(200000, 400000); \
+			sugar::usleep(delay); \
 		} \
 		ref self = ref(#name); (void)self; \
 		ref result("nothing"); (void)result; \
@@ -55,10 +59,6 @@
 		ref tok = ctx.linked(ref(#name)) ? ctx[ref(#name)] : ref(#__VA_ARGS__);
 	#define _macro_habit_assume(info, tok, ...) \
 		if ((#__VA_ARGS__)[0] != 0) { intellect::level2::habitassume(_macro_habit_name, ref(#info), ref(#__VA_ARGS__)); }
-	
-	// seed random number generator statically, for habit delay
-	namespace _macro_habit {
-	static struct timespec tp;
-	static int timeres = clock_gettime(CLOCK_REALTIME, &tp);
-	static int seed = (srand(tp.tv_nsec), tp.tv_nsec);
-	}
+
+}
+}
diff --git a/starts/meaning-vm/level2.cpp b/starts/meaning-vm/level2.cpp
index c04a5cc..ebdf121 100644
--- a/starts/meaning-vm/level2.cpp
+++ b/starts/meaning-vm/level2.cpp
@@ -1,9 +1,54 @@
 #include "level-2/level-2.hpp"
+#include "level-1/level-1.hpp"
 
 #include <iostream>
+#include <set>
 
 using namespace intellect::level2;
+using namespace intellect::level2::concepts;
 
 int main()
 {
+	decls(dump, name, of, is, nothing);
+	ahabit(name-of, ((concept, c)),
+	{
+		if (linked(c, name)) {
+			result = get(c, name);
+		} else {
+			for (auto & group : c.getAll(is)) {
+				result = (name-of)(group);
+				if (result != nothing) { break; }
+			}
+			std::stringstream ss;
+			if (result != nothing) {
+				ss << result.val<std::string>();
+			} else {
+				ss << "unnamed";
+			}
+			ss << "-" << std::hex << (size_t)(c.ptr());
+			intellect::level1::givename(c, ss.str());
+			result = get(c, name);
+		}
+	});
+	// I guess I'd better code dump as a behavior.
+	ahabit(dump, ((concept, c)),
+	{
+		decls(type, target);
+		static std::set<ref> dumped;
+		if (dumped.count(c) == 0) {
+			std::cout << (name-of)(c).val<std::string>() << ":" << std::endl;
+			dumped.insert(c);
+			ref le = (make-concept)().act(know-is-first-link-entry, c);
+			while (le.linked(target)) {
+				std::cout << "  " << (name-of)(le.get(type)).val<std::string>() << ": " << (name-of)(le.get(target)).val<std::string>() << std::endl;
+				(next-link-entry)(le);
+			}
+			(know-is-first-link-entry)(le, c);
+			while (le.linked(target)) {
+				(dump)(le.get(target));
+				(next-link-entry)(le);
+			}
+			(unmake-concept)(le);
+		}
+	});
 }
diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile
index 0a9738c..b2df672 100644
--- a/starts/meaning-vm/makefile
+++ b/starts/meaning-vm/makefile
@@ -3,12 +3,12 @@
 CXXFLAGS=-pedantic -Wall -Werror -Wno-error=deprecated-declarations -Wno-gnu-zero-variadic-macro-arguments -std=gnu++17 -fno-operator-names -ggdb -O0
 LINK.o=$(LINK.cc)
 
-all: level0 level1 habit-starts/rhythm
+all: level0 level1 habit-starts/rhythm level2
 level0: level0.o liblevel0.a
 liblevel0.a: $(patsubst %.cpp,%.o,$(wildcard level-0/*.cpp))
 level1: level1.o liblevel1.a
 liblevel1.a: $(patsubst %.cpp,%.o,$(wildcard level-0/*.cpp)) $(patsubst %.cpp,%.o,$(wildcard level-1/*.cpp))
-level2: liblevel2.a
+level2: level2.o liblevel2.a
 liblevel2.a: $(patsubst %.cpp,%.o,$(wildcard level-0/*.cpp)) $(patsubst %.cpp,%.o,$(wildcard level-1/*.cpp)) $(patsubst %.cpp,%.o,$(wildcard level-2/*.cpp))
 
 habit-starts/rhythm: habit-starts/rhythm.o liblevel2.a
-- 
cgit v1.2.3