From 5a548e692abcf226d1a21b5b186ede67dca8b0ff Mon Sep 17 00:00:00 2001
From: Karl Semich <fuzzyTew@gmail.com>
Date: Sat, 19 Oct 2019 19:54:15 -0400
Subject: tried making very basic relevence-generators

---
 nascent5.js | 259 +++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 170 insertions(+), 89 deletions(-)

diff --git a/nascent5.js b/nascent5.js
index 55fb7c6..b07afec 100644
--- a/nascent5.js
+++ b/nascent5.js
@@ -1,57 +1,3 @@
-class ActiveMemory {
-	// provides for needs of data
-	constructor() {
-		this.ram = []
-		this.cloned = false
-	}
-	clone() {
-		let ret = new ActiveMemory();
-		ret.ram = this.ram
-		ret.cloned = true
-		return ret
-	}
-	add(...items) {
-		if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
-		for (let item of items)
-			this.ram.push(item)
-	}
-	del(...items) {
-		if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
-		for (let item of items) {
-			let index = this.ram.indexOf(item)
-			this.ram.splice(index, 1)
-		}
-	}
-	contains(...items) {
-		for (let item of items)
-			if (this.ram.indexOf(item) === -1) return false
-		return true
-	}
-	containsWith(...props) {
-		let ret = []
-		outer: for (let a of this.ram) {
-			for (let i = 0; i < props.length; i += 2)
-				if (! a.props.has(props[i], props[i+1]))
-					continue outer
-			return true
-		}
-		return false
-	}
-	getWith(...props) {
-		let ret = []
-		outer: for (let a of this.ram) {
-			//console.log(a.props.props)
-			for (let i = 0; i < props.length; i += 2) {
-				//console.log(props[i] + ': ' + props[i+1] + '?')
-				if (! a.props.has(props[i], props[i+1]))
-					continue outer
-			}
-			ret.push(a)
-		}
-		if (ret.length > 0) return ret
-		return null
-	}
-}
 class Property {
 	constructor(type, dest) {
 		this.type = type
@@ -110,12 +56,79 @@ class ArrayData extends Array {
 		this.props.del('is', 'string')
 	}
 }
-// inhibition: wants lines to line up in top window
+
+// MEMORY
+// the archivist.  Provides for needs of data.  Memory is relevent whenever there is
+// an informational need.
+//
+// 	When remembering steps, likely what is relevent is what is needed to reach the goal
+// 		Here's a possible step memory.
+//
+//		let ret = new StringData('labeled ' + items.length + ' text-string')
+//		ret.props.add('is','step-memory')
+//		ret.props.add('step',genproptextstring)
+//		ret.props.add('ram',ram)
+//		ret.props.add('count',items.length)
+//		for (let a of items)
+//			ret.props.add('item', a)
+
+class ActiveMemory extends ArrayData {
+	// although Memory is eventually a module that provides for stored information needs
+	// this class is just a group of concepts, moved in and out as needed
+	constructor(items, from) {
+		super(items || [], from)
+		this.props.add('is','working-ram')
+	}
+	clone() {
+		return new ActiveMemory(this, this);
+	}
+	add(...items) {
+		//if (this.cloned) { this = this.slice(); this.cloned = false; }
+		for (let item of items)
+			this.push(item)
+	}
+	del(...items) {
+		//if (this.cloned) { this = this.slice(); this.cloned = false; }
+		for (let item of items) {
+			let index = this.indexOf(item)
+			this.splice(index, 1)
+		}
+	}
+	contains(...items) {
+		for (let item of items)
+			if (this.indexOf(item) === -1) return false
+		return true
+	}
+	containsWith(...props) {
+		let ret = []
+		outer: for (let a of this) {
+			for (let i = 0; i < props.length; i += 2)
+				if (! a.props.has(props[i], props[i+1]))
+					continue outer
+			return true
+		}
+		return false
+	}
+	getWith(...props) {
+		let ret = []
+		outer: for (let a of this) {
+			//console.log(a.props.props)
+			for (let i = 0; i < props.length; i += 2) {
+				//console.log(props[i] + ': ' + props[i+1] + '?')
+				if (! a.props.has(props[i], props[i+1]))
+					continue outer
+			}
+			ret.push(a)
+		}
+		if (ret.length > 0) return ret
+		return null
+	}
+}
+// note: for now we produce only data; state-changes are data-changes
 class FunctionData {
 	constructor(name, // name of function
 	            func, // function taking ordered needs
 	                  // ordered array of made objects is returned
-	            relevence, // TEMPORARY; MOVE TO HABIT. function that generates the needs, takes ram
 	            needs, // array of 1-property-per-object this function requires
 	            makes // array of 1-property-per-object this function produces
 	) {
@@ -123,7 +136,9 @@ class FunctionData {
 		this.props = new Properties('function')
 		this.props.add('name', name)
 		this.call = func
-		this.relevence = relevence
+		// If needed, make atomspace-like pattern structures for needs/makes.
+		// 	- represent multiple properties on 1 needed object
+		// 	- represent input objects present in output
 		this.needs = needs
 		this.makes = makes
 	}
@@ -161,35 +176,61 @@ line2words = new FunctionData(
 	(line) => { // call
 		let res = new ArrayData(line.split(' '), line)
 		res.props.add('is','words')
+		res.props.del('is','text-string')
 		return res
 	},
-	(ram) => { // relevence
-		return ram.getWith('is','text', 'is','string')
-	},
 	['is','text-string'], // needs
 	['is','word-array'] // makes
 )
 
+// makes text-string used by line2words.  example of small relevence habit
+genproptextstring = new FunctionData(
+	'genproptextstring',
+	/*call*/(text) => {
+		if (text.props.has('is','string')) {
+			if (!text.props.has('is','text-string')) {
+				text.props.add('is','text-string')
+			}
+			return text
+		}
+		return null
+	},
+	/*needs*/['is','text'],
+	/*makes*/['is','text-string']
+)
+
 respondhello = new FunctionData(
 	'respondhello',
 	(words) => { // call
-		console.log(words[0] + ", user!")
+		console.log(words[0] + " world!")
 		let res = new StringData("said " + words[0])
 		res.props.add('is','output')
 		res.props.add('is','text')
 		return res
 	},
-	(ram) => { // relevence
-		let res = ram.getWith('is','words', 'is','input')
-		if (res) {
-			res = res.filter(x => { x = x[0].toLowerCase(); return x == 'hello' || x == 'hi'})
+	['is','hello-input'], // needs
+	['is','output'] // makes
+)
+
+genprophelloinput = new FunctionData(
+	'genprophelloinput',
+	/*call*/(input) => {
+		if (!input.props.has('is','words'))
+			return null
+		if (!input.props.has('is','hello-input')) {
+			let x = input[0].toLowerCase()
+			let c = x[x.length-1]
+			if (c == ',' || c == '!' || c == '.') x = x.slice(0,x.length-1)
+			if (x != 'hello' && x != 'hi') return null
+			input.props.add('is','hello-input')
 		}
-		return res
+		return input
 	},
-	['is','input-words'], // needs
-	['is','output'] // makes
+	/*needs*/['is','input'],
+	/*makes*/['is','hello-input']
 )
 
+/* old, this isn't relevent to needed structure
 // nodejs is missing a succinct read-line-from-stdin function.  make our own.
 userinput = (() => {
 	const readline = require('readline')
@@ -198,9 +239,9 @@ userinput = (() => {
 		lines.push(line)
 	})
 
-	return new FunctionData(
+	let ret = new FunctionData(
 		'userinput',
-		() => { // call
+		(self) => { // call
 			let res = new StringData(lines.shift())
 			res.props.add('is','text')
 			res.props.add('is','input')
@@ -209,21 +250,55 @@ userinput = (() => {
 		() => { // relevence
 			return lines.length > 0
 		},
-		['userinput-has','lines'] // needs
+		['has','userinput-lines'] // needs
 		['is','string','is','text','is','input'] // makes
 	)
+	ret.lines = lines
 })()
-// => switching from 'relevence' to 'needs'. <= relevence is the module that processes needs
-// TODO: we need to make active memory a Data so that we can pass sets of data to relevence
-// TODO: want to move the relevence funcs out of the func defs that use them
-// TODO: we have 'is input-words'; can make as makeinputwords from respondhello.relevence
-// TODO: we have 'is word-array' instead of 'is words' and 'is array'
+genprophaslines = new FunctionData(
+	'genprophaslines',
+	(userinput) => { // call
+	}
+)
+*/
+
+// PATTERN REQUEST: we want to be able to store needed-steps.
+// 	needed-steps are parallel needs that are needed for a helpful step
+// 	any one may be met, and others are ignored once one is, but all are generated at once
+// 	habits that meet needs expect them not to be inside an array and have no way of referring to that.
+// 	[AND needs can be collapsed, but OR needs need patterns]
+// 		[how do we pull a need out of the list?]
+
+// make a habit that plans core behavior
+findstepsfor = new FunctionData(
+	'findstepsfor',
+	/*call*/(need, depth) => {
+		// find a habit that does the final goal.
+		// TODO: for now we assume all needs are 'is' and store just what-it-is in the need string.  when doesn't work anymore, make type-getters on Properties to retrieve the need details
+		let ret = new ArrayData([])
+		for (let habit of all_parts) {
+			if (habit.makes.indexOf(need) !== -1) {
+				// found a workable habit
+				ret.push(habit.needs)
+			}
+		}
+		ret.props.add('is','alternate-needs-array')
+		return ret
+	},
+	// TODO: likely need more structure here
+	/*needs*/['is','desired-need'],
+	/*makes*/['is','alternate-needs-array']
+)
+
+// TODO: add structure enough to build findstepsfor
+// TODO: build findstepsfor
 // TODO 2: add to surrounding process: remove source needs when there is no longer a reason for their presence
 
 
-all_parts = [ line2words, respondhello ]
+all_parts = [ line2words, genproptextstring, respondhello, genprophelloinput ]
 
 ram = new ActiveMemory()
+//ram.add(ram)
 optstried = new Set()
 steps = []
 
@@ -241,21 +316,23 @@ readline.createInterface({
 		cont = false
 		for (let part of all_parts) {
 			//console.log('for-loop-of-parts ' + part.name)
-			let rel = part.relevence(ram)
+			// TODO: >1 parameter,must redo next line
+			let rel = ram.getWith(...part.needs)
 			if (rel) {
 				for (let a of rel) {
 					//console.log('for-loop-of-rel ' + part.name + ' ' + a)
 					if (optstried.has(part.name + ' ' + a)) continue; 
 					//console.log('call-part ' + part.name + ' ' + a)
 					res = part.call(a)
+					optstried.add(part.name + ' ' + a)
+					if (res == null) continue
+					// TODO: res==null is considered failure now
 					ram.add(res)
 					//console.log('part-called')
 					step = [a, part.name, res]
 					steps.push(step)
 					console.log('made ' + step)
 					cont = true
-					optstried.add(part.name + ' ' + a)
-
 				}
 			}
 		}
@@ -269,20 +346,24 @@ readline.createInterface({
 // using an item should link it to what it is used by, so that it may be found easier again when needed
 
 // Please grow to understand your own structure.  What is needed to make an intellect?
+// 	^-- we want it to learn the basic needs of life, eventually, on its own.
+// 	    notably those to do with care for others.
 
-// MEMORY: the archivist.  Provides for needs of data.  Memory is relevent whenever there is
-// an informational need.
+// MEMORY: see MEMORY above
 
 // RELEVENCE: the gofer.  Provides the link between needs, etc, and the behavior that
 // finds them.  Is relevent for meeting needs in active ways and likely much else.
 
 // BEHAVIOR: the core.  combines interdependent habits from memory to meet needs.
-//
-// 1 way to make behavior:
-// 	find a habit that does the final goal
-// 	find with this process, information that meets its needs
+// The two below go on simultaneously.  only 1 is needed.
+// A way to plan behavior:
+// 	find habits that do the final goal, discern their needs
+// 	pick needs to treat as a new final goal and repeat until needs are met
+// A way to make behavior:
+// 	find a habit that does a goal
+// 	find with this process, information that meets its needs <spawns more>
 // 	run it
+// 		TODO: for subprocesses spawning,
+//		consider labelling things that are very quick and side-effect-free
+//		these can probably be immediately run.
 //
-// specifying the needs is an interesting problem
-// but i think our norm is just property specs
-// other habits can generate the property specs
-- 
cgit v1.2.3