marko/compiler/Builder.js
2015-12-28 10:17:22 -07:00

298 lines
8.2 KiB
JavaScript

'use strict';
var isArray = Array.isArray;
var Node = require('./ast/Node');
var Program = require('./ast/Program');
var TemplateRoot = require('./ast/TemplateRoot');
var FunctionDeclaration = require('./ast/FunctionDeclaration');
var FunctionCall = require('./ast/FunctionCall');
var Literal = require('./ast/Literal');
var Identifier = require('./ast/Identifier');
var If = require('./ast/If');
var ElseIf = require('./ast/ElseIf');
var Else = require('./ast/Else');
var Assignment = require('./ast/Assignment');
var BinaryExpression = require('./ast/BinaryExpression');
var Vars = require('./ast/Vars');
var Return = require('./ast/Return');
var HtmlElement = require('./ast/HtmlElement');
var Html = require('./ast/Html');
var Text = require('./ast/Text');
var ForEach = require('./ast/ForEach');
var ForEachProp = require('./ast/ForEachProp');
var ForRange = require('./ast/ForRange');
var Slot = require('./ast/Slot');
var HtmlComment = require('./ast/HtmlComment');
var SelfInvokingFunction = require('./ast/SelfInvokingFunction');
var ForStatement = require('./ast/ForStatement');
var BinaryExpression = require('./ast/BinaryExpression');
var UpdateExpression = require('./ast/UpdateExpression');
var UnaryExpression = require('./ast/UnaryExpression');
var MemberExpression = require('./ast/MemberExpression');
var parseExpression = require('./util/parseExpression');
function makeNode(arg) {
if (typeof arg === 'string') {
return parseExpression(arg);
} else if (arg instanceof Node) {
return arg;
} else {
return undefined;
}
}
class Builder {
assignment(left, right, operator) {
if (operator == null) {
operator = '=';
}
left = makeNode(left);
right = makeNode(right);
return new Assignment({left, right, operator});
}
binaryExpression(left, operator, right) {
left = makeNode(left);
right = makeNode(right);
return new BinaryExpression({left, operator, right});
}
elseStatement(body) {
return new Else({body});
}
elseIfStatement(test, body, elseStatement) {
test = makeNode(test);
return new ElseIf({
if: new If({test, body, else: elseStatement})
});
}
expression(value) {
return makeNode(value);
}
forEach(varName, inExpression, body) {
if (arguments.length === 1) {
var def = arguments[0];
return new ForEach(def);
} else {
varName = makeNode(varName);
inExpression = makeNode(inExpression);
return new ForEach({varName, in: inExpression, body});
}
}
forEachProp(nameVarName, valueVarName, inExpression, body) {
if (arguments.length === 1) {
var def = arguments[0];
return new ForEachProp(def);
} else {
nameVarName = makeNode(nameVarName);
valueVarName = makeNode(valueVarName);
inExpression = makeNode(inExpression);
return new ForEachProp({nameVarName, valueVarName, in: inExpression, body});
}
}
forRange(varName, from, to, step, body) {
if (arguments.length === 1) {
var def = arguments[0];
return new ForRange(def);
} else {
varName = makeNode(varName);
from = makeNode(from);
to = makeNode(to);
step = makeNode(step);
body = makeNode(body);
return new ForRange({varName, from, to, step, body});
}
}
forStatement(init, test, update, body) {
if (arguments.length === 1) {
var def = arguments[0];
return new ForStatement(def);
} else {
init = makeNode(init);
test = makeNode(test);
update = makeNode(update);
return new ForStatement({init, test, update, body});
}
}
functionCall(callee, args) {
callee = makeNode(callee);
if (args) {
if (!isArray(args)) {
args = [args];
}
for (var i=0; i<args.length; i++) {
args[i] = makeNode(args[i]);
}
} else {
args = [];
}
return new FunctionCall({callee, args});
}
functionDeclaration(name, params, body) {
return new FunctionDeclaration({name, params, body});
}
html(argument) {
argument = makeNode(argument);
return new Html({argument});
}
htmlComment(comment) {
return new HtmlComment({comment});
}
htmlElement(tagName, attributes, body, argument) {
if (typeof tagName === 'object' && !(tagName instanceof Node)) {
let def = arguments[0];
return new HtmlElement(def);
} else {
return new HtmlElement({tagName, attributes, body, argument});
}
}
identifier(name) {
return new Identifier({name});
}
ifStatement(test, body, elseStatement) {
return new If({test, body, else: elseStatement});
}
literal(value) {
return new Literal({value});
}
memberExpression(object, property, computed) {
object = makeNode(object);
property = makeNode(property);
return new MemberExpression({object, property, computed});
}
negate(argument) {
argument = makeNode(argument);
var operator = '!';
var prefix = true;
return new UnaryExpression({argument, operator, prefix});
}
node(type, generateCode) {
if (typeof type === 'function') {
generateCode = arguments[0];
type = 'Node';
}
var node = new Node(type);
if (generateCode) {
node.setCodeGenerator(generateCode);
}
return node;
}
program(body) {
return new Program({body});
}
require(path) {
path = makeNode(path);
let callee = 'require';
let args = [ path ];
return new FunctionCall({callee, args});
}
returnStatement(argument) {
argument = makeNode(argument);
return new Return({argument});
}
selfInvokingFunction(params, args, body) {
if (arguments.length === 1) {
body = arguments[0];
params = null;
args = null;
}
return new SelfInvokingFunction({params, args, body});
}
slot(onDone) {
return new Slot({onDone});
}
strictEquality(left, right) {
left = makeNode(left);
right = makeNode(right);
var operator = '===';
return new BinaryExpression({left, right, operator});
}
templateRoot(body) {
return new TemplateRoot({body});
}
text(argument, escape) {
argument = makeNode(argument);
return new Text({argument, escape});
}
unaryExpression(argument, operator, prefix) {
argument = makeNode(argument);
return new UnaryExpression({argument, operator, prefix});
}
updateExpression(argument, operator, prefix) {
argument = makeNode(argument);
return new UpdateExpression({argument, operator, prefix});
}
vars(declarations, kind) {
if (declarations) {
if (Array.isArray(declarations)) {
for (let i=0; i<declarations.length; i++) {
var declaration = declarations[i];
if (typeof declaration === 'string') {
declarations[i] = {
id: makeNode(declaration)
};
} else if (declaration instanceof Identifier) {
declarations[i] = {
id: declaration
};
}
}
} else if (typeof declarations === 'object') {
// Convert the object into an array of variables
declarations = Object.keys(declarations).map((key) => {
let id = new Identifier({name: key});
let init = makeNode(declarations[key]);
return { id, init };
});
}
}
return new Vars({declarations, kind});
}
}
module.exports = Builder;