aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Burwell <ben.burwell@trifecta.com>2016-09-14 12:30:04 -0400
committerBen Burwell <ben.burwell@trifecta.com>2016-09-14 12:30:04 -0400
commitfd5817a6bb3185314540825e3d665e94ffe188c0 (patch)
tree9b35138a18122ebfcb5cfa41ac0eadd27cb2c002 /lib
Initial commit
Diffstat (limited to 'lib')
-rw-r--r--lib/binops.js33
-rw-r--r--lib/readability.js38
-rw-r--r--lib/run.js20
-rw-r--r--lib/statements.js74
-rw-r--r--lib/style.css125
-rw-r--r--lib/types.js22
-rw-r--r--lib/util.js13
7 files changed, 325 insertions, 0 deletions
diff --git a/lib/binops.js b/lib/binops.js
new file mode 100644
index 0000000..a709097
--- /dev/null
+++ b/lib/binops.js
@@ -0,0 +1,33 @@
+var binaryOperators = {
+ '!=': function(a, b) {
+ return a != b;
+ },
+
+ '<': function(a, b) {
+ return a < b;
+ },
+
+ '>': function(a, b) {
+ return a > b;
+ },
+
+ '-': function(a, b) {
+ return a - b;
+ },
+
+ '+': function(a, b) {
+ return a + b;
+ },
+
+ '==': function(a, b) {
+ return a == b;
+ },
+
+ '<=': function(a, b) {
+ return a <= b;
+ },
+
+ '>=': function(a, b) {
+ return a >= b;
+ }
+};
diff --git a/lib/readability.js b/lib/readability.js
new file mode 100644
index 0000000..06eb4ad
--- /dev/null
+++ b/lib/readability.js
@@ -0,0 +1,38 @@
+var appendText = function(node, text) {
+ var n = document.createElement('var');
+ n.innerText = text;
+ node.appendChild(n);
+};
+
+var readability = {
+ 'assign': function(e) {
+ return e.dataset.name;
+ },
+
+ 'variable': function(e) {
+ return e.dataset.name;
+ },
+
+ 'constant': function(e) {
+ return e.dataset.type + '(' + e.dataset.val + ')';
+ },
+
+ 'compare': function(e) {
+ return e.dataset.op;
+ },
+
+ 'bin-op': function(e) {
+ return e.dataset.op;
+ }
+};
+
+var makeReadable = function(root) {
+ var classes = Object.keys(readability);
+ for (var idx = 0; idx < classes.length; idx++) {
+ var klass = classes[idx];
+ var els = root.getElementsByClassName(klass);
+ els.forEach(function(el) {
+ appendText(el, readability[klass](el));
+ });
+ }
+};
diff --git a/lib/run.js b/lib/run.js
new file mode 100644
index 0000000..92441a2
--- /dev/null
+++ b/lib/run.js
@@ -0,0 +1,20 @@
+(function() {
+ var evaluate = function(node, context) {
+ if (typeof context === 'undefined') {
+ context = {};
+ }
+ return statementEvaluators[node.className](node.dataset, node.children, context);
+ };
+
+ var statementEvaluators = getStatementEvaluators(evaluate);
+
+ document.addEventListener('DOMContentLoaded', function() {
+ var t0 = performance.now();
+ evaluate(document.body.children[0]);
+ var t1 = performance.now();
+ makeReadable(document.body);
+ var t2 = performance.now();
+ console.debug('Evaluated in ' + (t1 - t0) + 'ms');
+ console.debug('Rendered in ' + (t2 - t1) + 'ms');
+ });
+})();
diff --git a/lib/statements.js b/lib/statements.js
new file mode 100644
index 0000000..b59c08f
--- /dev/null
+++ b/lib/statements.js
@@ -0,0 +1,74 @@
+var getStatementEvaluators = function(evaluate) {
+ return {
+ 'statement-sequence': function(dataset, children, context) {
+ var retval = null;
+ children.forEach(function(child) {
+ retval = evaluate(child, context);
+ });
+ return retval;
+ },
+
+ 'while': function(dataset, children, context) {
+ var condition = children[0];
+ var body = children[1];
+ while (evaluate(condition, context)) {
+ evaluate(body, context);
+ }
+ },
+
+ 'compare': function(dataset, children, context) {
+ var operator = binaryOperators[dataset.op];
+ var lhs = evaluate(children[0], context);
+ var rhs = evaluate(children[1], context);
+ var result = operator(lhs, rhs);
+ return result;
+ },
+
+ 'variable': function(dataset, children, context) {
+ return context[dataset.name];
+ },
+
+ 'constant': function(dataset, children, context) {
+ return stringToType(dataset.val, dataset.type);
+ },
+
+ 'branch': function(dataset, children, context) {
+ var condition = children[0];
+ var ifBody = children[1];
+
+ // else is optional
+ if (children.length > 2) {
+ var elseBody = children[2];
+ }
+
+ if (evaluate(condition, context)) {
+ return evaluate(ifBody, context);
+ } else if (elseBody) {
+ return evaluate(elseBody, context);
+ }
+ },
+
+ 'assign': function(dataset, children, context) {
+ context[dataset.name] = evaluate(children[0], context);
+ return context[dataset.name];
+ },
+
+ 'bin-op': function(dataset, children, context) {
+ var operator = binaryOperators[dataset.op];
+ var lhs = evaluate(children[0], context);
+ var rhs = evaluate(children[1], context);
+ return operator(lhs, rhs);
+ },
+
+ 'return': function(dataset, children, context) {
+ return evaluate(children[0], context);
+ },
+
+ 'print': function(dataset, children, context) {
+ var args = children.map(function(child) {
+ return evaluate(child, context);
+ });
+ console.log.apply(this, args);
+ }
+ };
+};
diff --git a/lib/style.css b/lib/style.css
new file mode 100644
index 0000000..6b7d25f
--- /dev/null
+++ b/lib/style.css
@@ -0,0 +1,125 @@
+body {
+ font-family: monospace;
+}
+
+span {
+ display: flex;
+ padding-left: 3px;
+ padding-right: 3px;
+}
+
+var {
+ font-style: normal;
+ padding-left: 3px;
+ padding-right: 3px;
+}
+
+.statement-sequence {
+ display: block;
+ border: 2px solid #666;
+}
+
+.statement-sequence > span {
+ background-color: yellow;
+ padding: 3px;
+ margin: 3px;
+ border: 1px dotted #666;
+}
+
+.assign {
+ color: blue;
+}
+
+.assign::before {
+ content: 'Variable Assignment';
+ color: darkmagenta;
+ order: 1;
+}
+
+.assign::after {
+ content: '=';
+ color: black;
+ order: 3;
+}
+
+.assign > *:nth-child(1) {
+ order: 4;
+}
+
+.assign > *:nth-child(2) {
+ order: 2;
+}
+
+.variable {
+ color: blue;
+}
+
+.constant {
+ color: red;
+}
+
+.while {
+ flex-direction: column;
+}
+
+.while > span {
+ margin-left: 20px;
+}
+
+.while::before {
+ content: 'While';
+ color: darkmagenta;
+}
+
+.return > span {
+ order: 2;
+}
+
+.return::after {
+ content: 'Return';
+ color: darkmagenta;
+ order: 1;
+}
+
+.compare::before {
+ content: 'Comparison';
+ color: darkmagenta;
+ order: 1;
+}
+
+.compare > *:nth-child(1) {
+ order: 2;
+}
+
+.compare > *:nth-child(3) {
+ order: 3;
+}
+
+.compare > *:nth-child(2) {
+ order: 4;
+}
+
+.branch {
+ flex-direction: column;
+}
+
+.branch::before {
+ content: 'Logical Branch';
+ color: darkmagenta;
+}
+
+.branch > span {
+ margin-left: 20px;
+}
+
+.bin-op > span:nth-child(1) {
+ order: 1;
+}
+
+.bin-op > span:nth-child(2) {
+ order: 3;
+}
+
+.bin-op > var {
+ order: 2;
+}
diff --git a/lib/types.js b/lib/types.js
new file mode 100644
index 0000000..38e2b60
--- /dev/null
+++ b/lib/types.js
@@ -0,0 +1,22 @@
+var stringToType = function(str, type) {
+ switch (type) {
+ case 'number':
+ if (str.indexOf('.')) {
+ return parseFloat(str);
+ } else {
+ return parseInt(str, 10);
+ }
+ case 'string':
+ return str;
+ case 'boolean':
+ if (str === 'true') {
+ return true;
+ } else if (str === 'false') {
+ return false;
+ } else {
+ throw new Error('Invalid boolean value ' + str);
+ }
+ default:
+ throw new Error('type', type, 'is not defined');
+ }
+};
diff --git a/lib/util.js b/lib/util.js
new file mode 100644
index 0000000..3c6857c
--- /dev/null
+++ b/lib/util.js
@@ -0,0 +1,13 @@
+HTMLCollection.prototype.map = function(fn) {
+ var results = [];
+ for (var idx = 0; idx < this.length; idx++) {
+ results.push(fn(this.item(idx)));
+ }
+ return results;
+};
+
+HTMLCollection.prototype.forEach = function(fn) {
+ for (var idx = 0; idx < this.length; idx++) {
+ fn(this.item(idx));
+ }
+};