diff --git a/src/css/styles.css b/src/css/styles.css
index 4416e83..2694168 100644
--- a/src/css/styles.css
+++ b/src/css/styles.css
@@ -16,6 +16,7 @@ code { font-size: 1.2em; font-weight: bold; }
.expression .result td { border-top: dotted 1px gray; }
.expression { font-size: 1.5em; font-family: monospace }
.expression .prefix { font-weight: normal; display: none; font-size: 0.9em }
+.expression .other { font-size: 0.9em}
.hex .prefix { display: inline; }
@@ -36,6 +37,7 @@ code { font-size: 1.2em; font-weight: bold; }
.light .indicator { color: #ddd; }
.light .on { color: #121212; }
.light .prefix { color: #888}
+.light .other { font-size: 0.9em}
/* Dark */
.dark { background: #121212; color: white;}
@@ -45,5 +47,6 @@ code { font-size: 1.2em; font-weight: bold; }
.dark .on { color: white; }
.dark .zero { color: #999;}
.dark .prefix { color: #999}
+.dark .other { color: #444;}
diff --git a/src/index.html b/src/index.html
index ea64e91..5646263 100644
--- a/src/index.html
+++ b/src/index.html
@@ -115,40 +115,40 @@
-
-
@@ -170,6 +170,7 @@
else {
cmd.execute('1|2');
+ cmd.execute('1<<0x2a');
cmd.execute('2 4 8 16 32');
}
diff --git a/src/js/app/bitwise/expression.js b/src/js/app/bitwise/expression.js
index 5276338..79be83c 100644
--- a/src/js/app/bitwise/expression.js
+++ b/src/js/app/bitwise/expression.js
@@ -1,51 +1,48 @@
app.set('expression', function() {
"use strict";
- var decNumber = "\d+";
- var hexNumber = "(?:\d|a|b|c|d|e|f)";
- var modes = {
- 'dec': {
- expr: /^(\d+)\s*(<<|>>|\||\&|\^)\s*(\d+)$/,
- list: /^((\d*)+\s?)+$/
- },
- 'hex': {
- expr: /^([\d,a-f]+)\s*(<<|>>|\||\&|\^)\s*([\d,a-f]+)$/,
- list: /^(([\d,a-f]*)+\s?)+$/
- }
- };
+ var exprRegex = /^(\d+|0x[\d,a-f]+)\s*(<<|>>|\||\&|\^)\s*(\d+|0x[\d,a-f]+)$/;
+ var listRegex = /^((\d+|0x[\d,a-f]+)\s?)+$/
return {
canParse: function(string, mode) {
- var regex = modes[mode || 'dec'];
- return regex.expr.test(string) || regex.list.test(string);
+ return exprRegex.test(string) || listRegex.test(string);
},
parse: function(string, mode) {
mode = (mode || 'dec');
var trimmed = string.replace(/^\s+|\s+$/, '');
- var regex = modes[mode];
var base = getBase(mode);
- var matches = regex.expr.exec(trimmed);
+ var matches = exprRegex.exec(trimmed);
if(matches != null) {
return createCalculableExpression(matches, base);
}
- matches = regex.list.exec(string);
+ matches = listRegex.exec(string);
if(matches != null) {
return createListOfNumbersExpression(string, base)
}
+ },
+ parseOperand: function(input) {
+ return new Operand(input);
+ },
+ createOperand: function(number, kind) {
+ var str = number.toString(getBase(kind));
+ if(kind == 'hex') {
+ str = "0x" + str;
+ }
+
+ return new Operand(str);
}
+
};
function createCalculableExpression(matches, base) {
- var o1 = parseInt(matches[1], base);
- var o2 = parseInt(matches[3], base);
-
var m = new app.models.BitwiseOperation();
- m.operand1 = new Operand(o1);
- m.operand2 = new Operand(o2);
+ m.operand1 = new Operand(matches[1]);
+ m.operand2 = new Operand(matches[3]);
m.sign = matches[2];
m.string = matches.input;
//m.result = eval(matches.input);
@@ -54,15 +51,15 @@ app.set('expression', function() {
}
function createListOfNumbersExpression(input, base) {
- var numbers = [];
+ var operands = [];
input.split(' ').forEach(function(n){
if(n.trim().length > 0) {
- numbers.push(parseInt(n, base));
+ operands.push(new Operand(n.trim()));
}
});
- return new app.models.BitwiseNumbers(numbers);
+ return new app.models.BitwiseNumbers(operands);
}
function getBase(mode) {
@@ -73,11 +70,16 @@ app.set('expression', function() {
}
}
- function Operand(n) {
- this.value = n;
- this.hex = n.toString(16);
- this.dec = n.toString(10);
- this.bin = n.toString(2);
+ function Operand(input) {
+ // console.log('input: ' + input);
+ this.input = input;
+ this.value = parseInt(input);
+ // console.log('value: ' + this.value);
+ this.hex = '0x' + this.value.toString(16);
+ this.dec = this.value.toString(10);
+ this.bin = this.value.toString(2);
+ this.kind = this.input.indexOf('0x') == 0 ? 'hex' : 'dec';
+ this.other = this.kind == 'dec' ? this.hex : this.dec;
}
Operand.prototype.valueOf = function () {
diff --git a/src/js/app/modelViews.js b/src/js/app/modelViews.js
index 1767aff..799d795 100644
--- a/src/js/app/modelViews.js
+++ b/src/js/app/modelViews.js
@@ -6,32 +6,18 @@ app.compose(function () {
var calc = app.get('calc');
var html = app.get('html');
var cmdConfig = app.get('cmdConfig');
+ var expression = app.get('expression');
app.modelView(app.models.BitwiseOperation, {
renderView: function(expr) {
- var result = calc.calcExpression(expr);
- var maxLen = getBinaryLength([expr.operand1.value, expr.operand2.value, result]);
+ var result = expression.createOperand(calc.calcExpression(expr), getResultMode([expr.operand1, expr.operand2]));
+ var maxLen = getBinaryLength([expr.operand1.value, expr.operand2.value, result.value]);
var model = Object.create(expr);
-
- var otherMode = cmdConfig.mode == 'dec' ? 'hex' : 'dec';
-
- model.mode = cmdConfig.mode;
- model.otherMode = otherMode;
-
- model.operand1Str = expr.operand1[cmdConfig.mode];
+ model.result = result;
model.operand1Binary = formatter.padLeft(expr.operand1.bin, maxLen);
- model.operand1Other = formatter.padLeft(expr.operand1[otherMode]);
-
- model.operand2Str = expr.operand2[cmdConfig.mode];
model.operand2Binary = formatter.padLeft(expr.operand2.bin, maxLen);
- model.operand2Other = expr.operand2[otherMode];
-
- model.resultStr = formatter.formatString(result, cmdConfig.mode);
- model.resultBinary = formatter.padLeft(formatter.formatString(result, cmdConfig.mode), maxLen);
- model.resultOther = formatter.formatString(result, otherMode);
-
- console.log(model);
+ model.resultBinary = formatter.padLeft(model.result.bin, maxLen);
var templateId = /<<|>>/.test(model.sign) ? 'shiftExpressionView' : 'binaryExpressionView';
var template = app.template(templateId);
@@ -48,7 +34,7 @@ app.compose(function () {
var table = html.element('
');
var otherMode = cmdConfig.mode == 'dec' ? 'hex' : 'dec';
- model.numbers.forEach(function(n){
+ model.operands.forEach(function(n){
var row = table.insertRow();
var decCell = row.insertCell();
@@ -59,12 +45,12 @@ app.compose(function () {
var binCell = row.insertCell();
binCell.className = 'bin';
- decCell.innerHTML = html.template('0x{n}', { n: formatter.formatString(n, cmdConfig.mode) });
- binCell.textContent = formatter.padLeft(formatter.formatString(n), maxLen);
+ decCell.textContent = n.input;
+ binCell.textContent = formatter.padLeft(n.bin, maxLen);
var otherCell = row.insertCell();
- otherCell.className = 'other ' + otherMode;
- otherCell.innerHTML = html.template('0x{n}', { n: formatter.formatString(n, otherMode) });
+ otherCell.className = 'other';
+ otherCell.textContent = n.other;
});
colorizeBits(table);
@@ -118,5 +104,15 @@ app.compose(function () {
.replace(/1/g, '1');
});
}
+
+ function getResultMode(operands) {
+ for(var i=0; i index) {
- sb.push("\t\thtml.push('" + normalize(template.substr(index, m.index - index)) + "');");
- }
- sb.push('\t\thtml.push(' + m[1] + ');');
- index = m.index + m[0].length;
- }
-
- if(index < template.length - 1) {
- sb.push("\t\thtml.push('" + normalize(template.substr(index, template.length - index)) + "');");
- }
- sb.push('\t}');
- sb.push("\treturn html.join('');");
- sb.push('}');
- sb.push('})()')
- console.log(sb.join('\r\n'));
- return eval(sb.join('\r\n'));
- }
- };
-
- function normalize(str) {
- return str.replace(/(\r|\n)+/g, '').replace("'", "\\\'");
- }
- */
})(window.app, window.core);
\ No newline at end of file
diff --git a/src/js/components/templatesFeature.js b/src/js/components/templatesFeature.js
index bccf5c5..e2f0405 100644
--- a/src/js/components/templatesFeature.js
+++ b/src/js/components/templatesFeature.js
@@ -1,11 +1,16 @@
(function(app) {
"use strict";
- function Template(html) {
+ function Template(html, isCompiled) {
this.html = html;
+ this.isCompiled = isCompiled === true;
}
Template.prototype.render = function (model) {
+ if(this.isCompiled) {
+ return app.get('html').element(this.process(model));
+ }
+
return app.get('html').element(this.html, model);
};
@@ -16,11 +21,11 @@
throw new Error(key + ' template is not found');
}
return tpl;
- }
+ };
app.run(function() {
readTemplates(app.get('rootView'));
- })
+ });
function readTemplates(containerEl) {
var els = containerEl.querySelectorAll('[data-template]');
@@ -34,9 +39,49 @@
return;
}
- store[key] = new Template(element.innerHTML);
+
+ var template = new Template(element.innerHTML);
+ store[key] = template;
+
+ if(element.hasAttribute('data-compiled')) {
+ template.process = compile(template.html);
+ template.isCompiled = true;
+ }
});
- }
+
+
+ function compile (template) {
+ var regex = /(?:{([^}]+)})/g;
+
+ var sb = [];
+
+ sb.push('(function() {')
+ sb.push('return function (m) { ')
+ sb.push('\tvar html = [];')
+ sb.push('console.log(m)');
+ var m, index = 0;
+ while ((m = regex.exec(template)) !== null) {
+ if(m.index > index) {
+ sb.push("\t\thtml.push('" + normalize(template.substr(index, m.index - index)) + "');");
+ }
+ sb.push('\t\thtml.push(' + m[1] + ');');
+ index = m.index + m[0].length;
+ }
+
+ if(index < template.length - 1) {
+ sb.push("\t\thtml.push('" + normalize(template.substr(index, template.length - index)) + "');");
+ }
+ sb.push("\treturn html.join('');");
+ sb.push('}');
+ sb.push('})()');
+ console.log(sb.join('\r\n'));
+ return eval(sb.join('\r\n'));
+ }
+ };
+
+ function normalize(str) {
+ return str.replace(/(\r|\n)+/g, '').replace("'", "\\\'");
+ }
})(window.app);
diff --git a/tests/domain/expressionSpec.js b/tests/domain/expressionSpec.js
index f119430..ef42fef 100644
--- a/tests/domain/expressionSpec.js
+++ b/tests/domain/expressionSpec.js
@@ -1,38 +1,86 @@
+var app = window.app;
+var expression = app.get('expression');
+
describe("expression parse", function() {
- var app = window.app;
- var expression = app.get('expression');
- var decCases = {
- "1 2 3": { numbers: [1,2,3] },
- "1": { numbers: [1] },
- "2>>1": { operand1: 2, operand2:1, "sign":">>", string:"2>>1" },
+ var shouldParse = ['0x2>>1', '1 2 3', '0x1 1 2 3 5', '0x1>>0x2', '1|2'];
+
+ it("should be able to parse", function() {
+ shouldParse.forEach(function(expr) {
+ console.log(expr);
+ expect(expression.canParse(expr)).toBe(true);
+ })
+ });
+
+ var expressionCases = {
+ "0x2>>1": { operand1: 2, operand2:1, "sign":">>", string:"0x2>>1" },
"123|111": { operand1: 123, operand2:111, "sign":"|", string: "123|111" },
- "23^1": { operand1: 23, operand2:1, "sign":"^", string: "23^1" }
+ "23^0x1": { operand1: 23, operand2:1, "sign":"^", string: "23^0x1" },
+ "0xf>>0xa": { operand1: 15, operand2:10, "sign":">>", string:"0xf>>0xa" },
+ "0x10&0x11": { operand1: 0x10, operand2:0x11, "sign":"&", string:"0x10&0x11" },
+ "0x1a^11": { operand1: 0x1a, operand2:11, "sign":"^", string:"0x1a^11" }
};
- var hexCases = {
- "1 10 f" : { numbers: [1, 16, 15] },
- "f>>a": { operand1: 15, operand2:10, "sign":">>", string:"f>>a" },
- "10&11": { operand1: 16, operand2:17, "sign":"&", string:"10&11" },
- "10^11": { operand1: 16, operand2:17, "sign":"^", string:"10^11" }
- };
-
- it("should parse decimal expressions", function() {
+ it("should parse expressions", function() {
var input, expr;
- for(input in decCases) {
- expect(expression.canParse(input)).toBe(true);
- expr = expression.parse(input);
- expect(JSON.stringify(expr)).toEqual(JSON.stringify(decCases[input]));
+ for(input in expressionCases) {
+ var actual = expression.parse(input);
+ var expected = expressionCases[input];
+ expect(actual).toBeDefined();
+ expect(actual).not.toBe(null);
+ expect(actual.sign).toBe(expected.sign);
+ expect(actual.operand1.value).toBe(expected.operand1);
+ expect(actual.operand2.value).toBe(expected.operand2);
+ expect(actual.string).toBe(expected.string);
}
});
+ var listCases = {
+ '1 2 3': [1, 2, 3],
+ '0x1 2 0xa6b': [0x1, 2, 0xa6b],
+ '0x11a': [0x11a]
+ };
+
it("should parse hexadecimal expressions", function() {
- var input, expr;
- for(input in hexCases) {
- console.log('input: ' + input)
- expect(expression.canParse(input, 'hex')).toBe(true);
- expr = expression.parse(input, 'hex');
- expect(JSON.stringify(expr)).toEqual(JSON.stringify(hexCases[input]));
+ var input, expr, i;
+ for(input in listCases) {
+ var actual = expression.parse(input);
+ var expected = listCases[input];
+
+ for(i =0; i