Skip to content

Commit

Permalink
First working updater.
Browse files Browse the repository at this point in the history
  • Loading branch information
Anton Medvedev committed Oct 18, 2015
1 parent 90b1028 commit fb75f43
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 24 deletions.
5 changes: 5 additions & 0 deletions lib/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ var _compilerExpression = require('./compiler/expression');

var _compilerExpression2 = _interopRequireDefault(_compilerExpression);

var _compilerExpressionVisitor = require('./compiler/expression/visitor');

var _compilerExpressionVisitor2 = _interopRequireDefault(_compilerExpressionVisitor);

var _compilerDocument = require('./compiler/document');

var _compilerDocument2 = _interopRequireDefault(_compilerDocument);
Expand All @@ -46,6 +50,7 @@ var Compiler = (function () {
(0, _compilerDocument2['default'])(_parser.parser.ast);
(0, _compilerElement2['default'])(_parser.parser.ast);
(0, _compilerExpression2['default'])(_parser.parser.ast);
(0, _compilerExpressionVisitor2['default'])(_parser.parser.ast);
(0, _compilerText2['default'])(_parser.parser.ast);
}

Expand Down
2 changes: 2 additions & 0 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { parser } from '../parser';
import { Figure } from './figure';
import { sourceNode } from './compiler/sourceNode';
import expression from './compiler/expression';
import visitor from './compiler/expression/visitor';
import document from './compiler/document';
import element from './compiler/element';
import text from './compiler/text';
Expand All @@ -15,6 +16,7 @@ export default class Compiler {
document(parser.ast);
element(parser.ast);
expression(parser.ast);
visitor(parser.ast);
text(parser.ast);
}

Expand Down
14 changes: 4 additions & 10 deletions src/compiler/expression.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { sourceNode } from './sourceNode';
import { collectVariables } from './expression/variable';

export default function (ast) {
ast.ExpressionStatementNode.prototype.compile = function (figure) {
Expand All @@ -8,18 +9,11 @@ export default function (ast) {
sourceNode(this.loc, [this.nodeName, " = document.createTextNode('')"])
);

var variables = [];

this.ast.visit(function (node) {
if (node.type == 'Identifier') {
if (variables.indexOf(node.name) == -1) {
variables.push(node.name);
}
}
var variables = collectVariables(this.expression);
figure.addUpdater(variables, () => {
return sourceNode(this.loc, [this.nodeName, '.textContent = ', this.expression.compile()]);
});

sourceNode(this.loc, this.expression.compile());

return this.nodeName;
};

Expand Down
17 changes: 17 additions & 0 deletions src/compiler/expression/variable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export function collectVariables(expr) {
var variables = [];

if (!expr.visit) {
throw new Error(`Can not collect variables for node "${expr.type}" type.`);
}

expr.visit((node) => {
if (node.type == 'Identifier') {
if (variables.indexOf(node.name) == -1) {
variables.push(node.name);
}
}
});

return variables;
}
147 changes: 147 additions & 0 deletions src/compiler/expression/visitor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
export default function visitor(ast) {
ast.FilterExpressionNode.prototype.visit = function (callback) {
callback(this);

this.callee.visit(callback);
var args = this.arguments;

for (var i = 0, len = args.length; i < len; i++) {
args[i].visit(callback);
}
};

ast.ArrayExpressionNode.prototype.visit = function (callback) {
callback(this);

var elements = this.elements;

for (var i = 0, len = elements.length; i < len; i++) {
elements[i].visit(callback);
}
};

ast.ObjectExpressionNode.prototype.visit = function (callback) {
callback(this);

var i, j, properties = this.properties;

for (i = 0, len = properties.length; i < len; i++) {
var prop = properties[i];
var kind = prop.kind;
var key = prop.key;
var value = prop.value;

if (kind === "init") {
key.visit(callback);
value.visit(callback);
} else {
var params = value.params;
var body = value.body;

key.visit(callback);

for (j = 0, plen = params.length; j < plen; j++) {
params[j].visit(callback);
}

for (j = 0, blen = body.length; j < blen; j++) {
body[j].visit(callback);
}
}
}
};

ast.SequenceExpressionNode.prototype.visit = function (callback) {
callback(this);

var expressions = this.expressions;

for (var i = 0, len = expressions.length; i < len; i++) {
expressions[i].visit(callback);
}
};

ast.UnaryExpressionNode.prototype.visit = function (callback) {
callback(this);

this.argument.visit(callback);
};

ast.BinaryExpressionNode.prototype.visit = function (callback) {
callback(this);

this.left.visit(callback);
this.right.visit(callback);
};

ast.AssignmentExpressionNode.prototype.visit = function (callback) {
callback(this);

this.left.visit(callback);
this.right.visit(callback);
};

ast.UpdateExpressionNode.prototype.visit = function (callback) {
callback(this);

this.argument.visit(callback);
this.argument.visit(callback);
};

ast.LogicalExpressionNode.prototype.visit = function (callback) {
callback(this);

this.left.visit(callback);
this.right.visit(callback);
};

ast.ConditionalExpressionNode.prototype.visit = function (callback) {
callback(this);

this.test.visit(callback);
this.consequent.visit(callback);
this.alternate.visit(callback);
};

ast.NewExpressionNode.prototype.visit = function (callback) {
callback(this);

this.callee.visit(callback);
var args = this.arguments;

if (args !== null) {
for (var i = 0, len = args.length; i < len; i++) {
args[i].visit(callback);
}
}
};

ast.CallExpressionNode.prototype.visit = function (callback) {
callback(this);

this.callee.visit(callback);
var args = this.arguments;

for (var i = 0, len = args.length; i < len; i++) {
args[i].visit(callback);
}
};

ast.MemberExpressionNode.prototype.visit = function (callback) {
callback(this);
this.object.visit(callback);
this.property.visit(callback);
};

ast.IdentifierNode.prototype.visit = function (callback) {
callback(this);
};

ast.AccessorNode.prototype.visit = function (callback) {
callback(this);
};

ast.LiteralNode.prototype.visit = function (callback) {
callback(this);
};
}
4 changes: 2 additions & 2 deletions src/compiler/updater.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { sourceNode } from './sourceNode';
import { size, uniqueName } from '../utils';

export default class Updater {
export class Updater {
constructor(variables) {
this.variables = variables.sort();
this.name = uniqueName(this.variables);
Expand Down Expand Up @@ -77,7 +77,7 @@ export default class Updater {
}
}

makeDataDependent = function () {
makeDataDependent() {
this.isDataDependent = true;
};
}
Expand Down
33 changes: 21 additions & 12 deletions src/figure.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { sourceNode } from './compiler/sourceNode';
import { Updater } from './compiler/updater';
import { size } from './utils';

export class Figure {
Expand Down Expand Up @@ -97,26 +98,34 @@ export class Figure {
return sourceNode(null, parts).join(',\n');
}

compileExpression(expression, callback, dataDependent) {
dataDependent = dataDependent || false;
addUpdater(variables, callback, dataDependent = false) {
if (variables.length == 1) {

if (expression.variables.length == 1) {
this.onSetter(expression.variables[0]).add(callback(expression.toCode()));
} else if (expression.variables.length > 1) {
var complexSetter = this.onComplexSetter(expression.variables);
complexSetter.add(callback(expression.toCode()));
this.onUpdater(variables[0]).add(callback());

} else if (variables.length > 1) {

var complexUpdater = this.onComplexUpdater(variables);
complexUpdater.add(callback());

if (dataDependent) {
complexSetter.dataDependent();
complexUpdater.dataDependent();
}

for (variable of expression.variables) {
this.onSetter(variable).cache();
this.onSetter(variable).addComplex(expression.variables, complexSetter.name);
for (let variable of variables) {
this.onUpdater(variable).cache();
this.onUpdater(variable).addComplex(variables, complexUpdater.name);
}
}
}

onUpdater(variableName) {
return variableName in this.updaters ? this.updaters[variableName] : this.updaters[variableName] = new Updater([variableName]);
}

return expression;
onComplexUpdater(variables) {
var name = uniqueName(variables);
return name in this.complexUpdaters ? this.complexUpdaters[name] : this.complexUpdaters[name] = new Updater(variables);
}

uniqid(name = 'default') {
Expand Down

0 comments on commit fb75f43

Please sign in to comment.