diff options
author | Ben Burwell <ben.burwell@trifecta.com> | 2016-09-14 12:30:04 -0400 |
---|---|---|
committer | Ben Burwell <ben.burwell@trifecta.com> | 2016-09-14 12:30:04 -0400 |
commit | fd5817a6bb3185314540825e3d665e94ffe188c0 (patch) | |
tree | 9b35138a18122ebfcb5cfa41ac0eadd27cb2c002 /lib |
Initial commit
Diffstat (limited to 'lib')
-rw-r--r-- | lib/binops.js | 33 | ||||
-rw-r--r-- | lib/readability.js | 38 | ||||
-rw-r--r-- | lib/run.js | 20 | ||||
-rw-r--r-- | lib/statements.js | 74 | ||||
-rw-r--r-- | lib/style.css | 125 | ||||
-rw-r--r-- | lib/types.js | 22 | ||||
-rw-r--r-- | lib/util.js | 13 |
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)); + } +}; |