aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-08-26 22:52:02 -0700
committeralon@honor <none@none>2010-08-26 22:52:02 -0700
commitc96ca4ad280e3d9704b8f127311e5b48b707e3bd (patch)
treeb63e654f7df8a9c18f4477edfdec4b26a428424c
parenta9256705ada4ae335870cdb60ae7f9c8373038e3 (diff)
cleanup + prep for enzymatic2
-rw-r--r--src/enzymatic2.js163
-rw-r--r--src/parser.js14
-rw-r--r--src/utility.js33
3 files changed, 200 insertions, 10 deletions
diff --git a/src/enzymatic2.js b/src/enzymatic2.js
new file mode 100644
index 00000000..bdab72bd
--- /dev/null
+++ b/src/enzymatic2.js
@@ -0,0 +1,163 @@
+/**
+ * A 2nd implementation of an 'enzymatic programming' paradigm.
+ */
+
+Zyme2 = function(reqs) {
+ //! List of items that we want. Each element in this list is
+ //! a list of features, we want elements that have them all.
+ //! We will only call this Zyme if we find *all* of the elements
+ //! it wants.
+ this.reqs = reqs;
+};
+
+Substrate2 = function(name_) {
+ this.name_ = name_;
+ this.elems = {};
+ this.currUid = 1;
+};
+
+Substrate2.prototype = {
+ _addElement: function(elem) {
+ if (!elem.__uid__) {
+ elem.__uid__ = this.currUid;
+ this.currUid ++;
+ } else {
+ assertTrue(!this.elems[elem.__uid__]);
+ }
+ this.elems[elem.__uid__] = elem;
+ },
+
+ _removeElement: function(elem) {
+ this.elems[elem.__uid__] = null;
+ delete elem.__uid__;
+ },
+
+ _getElement: function(uid) { return this.elems[uid]; },
+
+ getItems: function() {
+ return values(this.elems).filter(function(elem) { return elem.isItem });
+ },
+
+ getZymes: function() {
+ return values(this.elems).filter(function(elem) { return elem.isZyme });
+ },
+
+ addItem: function(item) {
+ this._addElement(item);
+ item.isItem = true;
+
+ this.getZymes().forEach(function(zyme) { this.noticeItem(zyme, item) });
+ },
+
+ addZyme: function(zyme) {
+ this._addElement(zyme);
+ zyme.isZyme = true;
+ zyme.potentials = zyme.reqs.map(function() { return [] });
+
+ this.getItems().forEach(function(item) { this.noticeItem(zyme, item); });
+ },
+
+ removeItem: function(item) {
+ this._removeElement(item);
+ delete item.__result__;
+ delete item.__finalResult__;
+
+ this.getZymes().forEach(function(zyme) { this.forgetItem(zyme, item) });
+ },
+
+ removeZyme: function(zyme) {
+ this._removeElement(zyme);
+ },
+
+ _getFits: function(zyme, item) {
+ return fits = zyme.reqs.map(function(req) {
+ return req.filter(function(feat) { return !item[feat] }).length == 0;
+ });
+ },
+
+ noticeItem: function(zyme, item) {
+ loopOn(this._getFits(zyme, item), function(i, fit) {
+ if (fit) {
+ zyme.potentials[i].push(item);
+ }
+ });
+ },
+
+ forgetItem: function(zyme, item) {
+ loopOn(this._getFits(zyme, item), function(i, fit) {
+ if (fit) {
+ zyme.potentials = zyme.potentials.filter(function(item2) { return item2 !== item });
+ }
+ });
+ },
+
+ processItem: function(zyme, items) {
+ items.forEach(this.removeItem, this);
+ var splat = splitter(zyme.process(items), function(item) {
+ return item.__result__ || item.__finalResult__;
+ });
+ splat.leftIn.forEach(this.addItem, this);
+ return splat.splitOut;
+ },
+
+// if (sumTruthy(combo) == zyme.reqs.length) { // good to go
+
+// XXX
+
+ solve: function() {
+ var startTime = Date.now();
+ var midTime = startTime;
+ var that = this;
+ function midComment() {
+ var curr = Date.now();
+ if (curr - midTime > 1000) {
+ print('// Working on ' + that.name_ + ', so far ' + ((curr-startTime)/1000).toString().substr(0,10) + ' seconds. Have ' + that.items.length + ' items.');
+ midTime = curr;
+ }
+ }
+ function finalComment() {
+ print('// Completed ' + that.name_ + ' in ' + ((Date.now() - startTime)/1000).toString().substr(0,10) + ' seconds.');
+ }
+
+ var results = [];
+ var done = false;
+ while (!done) {
+ var hadProcessing = false;
+ this.getZymes().forEach(function(zyme) {
+ while (!done) {
+ var selected = zyme.potentials.map(function(potential) { return potential[0] });
+ if (sumTruthy(selected) == zyme.reqs.length) {
+ var outputs = this.processItem(zyme, selected);
+ hadProcessing = true;
+ if (outputs.length === 1 && outputs[0].__finalResult__) {
+ results = outputs;
+ done = true;
+ } else {
+ results = results.concat(outputs);
+ }
+ } else {
+ break;
+ }
+ }
+ }, this);
+ if (this.items.length === 0) {
+ finalComment();
+ done = true;
+ }
+ if (!hadProcessing) {
+ print("Reached a dead end.");
+ this.getItems().forEach(function(item) {
+ print("remaining item:" + dump(item));
+ });
+ throw "failure";
+ }
+ midComment();
+ }
+ if (results[0].__finalResult__) {
+ return results[0];
+ } else {
+ return results;
+ }
+ },
+};
+
diff --git a/src/parser.js b/src/parser.js
index ba0a36e4..390daf9b 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -24,6 +24,7 @@ if (!this['read']) {
load('utility.js');
load('enzymatic.js');
+load('enzymatic2.js');
// Tools
@@ -89,13 +90,6 @@ function addIdent(token) {
return token;
}
-// Splits out items that pass filter. Returns also the original sans the filtered
-function splitter(array, filter) {
- var splitOut = array.filter(filter);
- var original = array.filter(function(x) { return !filter(x) });
- return { original: original, splitOut: splitOut };
-}
-
function combineTokens(tokens) {
var ret = {
lineNum: tokens[0].lineNum,
@@ -822,7 +816,7 @@ function analyzer(data) {
['globalConstant', 'globalVariable', 'functionStub', 'type'].forEach(function(intertype) {
var temp = splitter(item.items, function(item) { return item.intertype == intertype });
item[intertype + 's'] = temp.splitOut;
- item.items = temp.original;
+ item.items = temp.leftIn;
});
// Functions & labels
item.functions = []
@@ -1307,7 +1301,7 @@ print("\n\n// XXX MAKEBLOCK " + entry + ' : ' + labels.length + ' : ' + getLabel
print("//no first line");
return;
}
- var others = split.original;
+ var others = split.leftIn;
var lastLine = first.lines.slice(-1)[0];
print("// makeBlock " + entry + ' : ' + getLabelIds(labels) + ' IN: ' + first.inLabels + ' OUT: ' + first.outLabels);
// If we have one outgoing, and none incoming - make this a block of 1,
@@ -1332,7 +1326,7 @@ print('// loop ? b');
// outside the loop. Insiders are those that can get back to the entry
var split2 = splitter(others, function(label) { return label.allOutLabels.indexOf(entry) == -1 });
var outsiders = split2.splitOut;
- var insiders = split2.original;
+ var insiders = split2.leftIn;
print('// potential loop : in/out : ' + getLabelIds(insiders) + ' to ' + getLabelIds(outsiders));
// Hopefully exactly one of the outsiders is a 'pivot' - a label to which all those leaving
// the loop must go. Then even some |if (falala) { ... break; }| will get ...
diff --git a/src/utility.js b/src/utility.js
index 447c52a6..f95e81f1 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -80,3 +80,36 @@ function walkJSON(item, func) {
}
}
+function keys(x) {
+ var ret = [];
+ for (a in x) ret.push(a);
+ return ret;
+}
+
+function values(x) {
+ var ret = [];
+ for (a in x) ret.push(x[a]);
+ return ret;
+}
+
+function sum(x) {
+ return x.reduce(function(a,b) { return a+b }, 0);
+}
+
+function sumTruthy(x) {
+ return x.reduce(function(a,b) { return (!!a)+(!!b) }, 0);
+}
+
+function loopOn(array, func) {
+ for (var i = 0; i < array.length; i++) {
+ func(i, array[i]);
+ }
+}
+
+// Splits out items that pass filter. Returns also the original sans the filtered
+function splitter(array, filter) {
+ var splitOut = array.filter(filter);
+ var leftIn = array.filter(function(x) { return !filter(x) });
+ return { leftIn: leftIn, splitOut: splitOut };
+}
+