generator -> codegen

This commit is contained in:
Patrick Steele-Idem 2015-12-28 21:55:29 -07:00
parent 21ff7769e5
commit fb6b436063
41 changed files with 243 additions and 243 deletions

View File

@ -9,19 +9,19 @@ const Container = require('./ast/Container');
const util = require('util'); const util = require('util');
class Slot { class Slot {
constructor(generator, slotNode) { constructor(codegen, slotNode) {
this._content = null; this._content = null;
this._start = generator._code.length; this._start = codegen._code.length;
generator.write('/* slot */'); codegen.write('/* slot */');
if (slotNode.statement) { if (slotNode.statement) {
generator.write('\n'); codegen.write('\n');
} }
this._end = generator._code.length; this._end = codegen._code.length;
this._currentIndent = generator._currentIndent; this._currentIndent = codegen._currentIndent;
this._inFunction = generator.inFunction; this._inFunction = codegen.inFunction;
this._statement = slotNode.statement; this._statement = slotNode.statement;
} }
@ -29,36 +29,36 @@ class Slot {
this._content = content; this._content = content;
} }
generateCode(generator) { generateCode(codegen) {
let content = this._content; let content = this._content;
let slotCode; let slotCode;
if (content) { if (content) {
let isStatement = this._statement; let isStatement = this._statement;
generator._currentIndent = this._currentIndent; codegen._currentIndent = this._currentIndent;
generator.inFunction = this._inFunction; codegen.inFunction = this._inFunction;
let capture = generator._beginCaptureCode(); let capture = codegen._beginCaptureCode();
if (isArray(content) || (content instanceof Container)) { if (isArray(content) || (content instanceof Container)) {
content.forEach((node) => { content.forEach((node) => {
node.statement = isStatement; node.statement = isStatement;
generator.generateCode(node); codegen.generateCode(node);
}); });
} else { } else {
content.statement = isStatement; content.statement = isStatement;
generator.generateCode(content); codegen.generateCode(content);
} }
slotCode = capture.end(); slotCode = capture.end();
} }
let oldCode = generator._code; let oldCode = codegen._code;
let beforeCode = oldCode.substring(0, this._start); let beforeCode = oldCode.substring(0, this._start);
let afterCode = oldCode.substring(this._end); let afterCode = oldCode.substring(this._end);
generator._code = beforeCode + (slotCode || '') + afterCode; codegen._code = beforeCode + (slotCode || '') + afterCode;
} }
} }
@ -83,7 +83,7 @@ class Generator {
ok(this.builder, '"this.builder" is required'); ok(this.builder, '"this.builder" is required');
this._generatorCodeMethodName = 'generate' + this._codegenCodeMethodName = 'generate' +
this.outputType.charAt(0).toUpperCase() + this.outputType.charAt(0).toUpperCase() +
this.outputType.substring(1) + this.outputType.substring(1) +
'Code'; 'Code';
@ -153,10 +153,10 @@ class Generator {
let generateCodeMethod = node.generateCode; let generateCodeMethod = node.generateCode;
if (!generateCodeMethod) { if (!generateCodeMethod) {
generateCodeMethod = node[this._generatorCodeMethodName]; generateCodeMethod = node[this._codegenCodeMethodName];
if (!generateCodeMethod) { if (!generateCodeMethod) {
throw new Error('No code generator for node of type "' + throw new Error('No code codegen for node of type "' +
node.type + node.type +
'" (output type: "' + this.outputType + '"). Node: ' + util.inspect(node)); '" (output type: "' + this.outputType + '"). Node: ' + util.inspect(node));
} }
@ -299,10 +299,10 @@ class Generator {
this._code = ''; this._code = '';
return { return {
generator: this, codegen: this,
end() { end() {
let newCode = this.generator._code; let newCode = this.codegen._code;
this.generator._code = oldCode; this.codegen._code = oldCode;
return newCode; return newCode;
} }
}; };

View File

@ -10,24 +10,24 @@ class Assignment extends Node {
this.operator = def.operator; this.operator = def.operator;
} }
generateCode(generator) { generateCode(codegen) {
var left = this.left; var left = this.left;
var right = this.right; var right = this.right;
var operator = this.operator; var operator = this.operator;
generator.generateCode(left); codegen.generateCode(left);
generator.write(' ' + (operator || '=') + ' '); codegen.write(' ' + (operator || '=') + ' ');
var wrap = right instanceof Assignment; var wrap = right instanceof Assignment;
if (wrap) { if (wrap) {
generator.write('('); codegen.write('(');
} }
generator.generateCode(right); codegen.generateCode(right);
if (wrap) { if (wrap) {
generator.write(')'); codegen.write(')');
} }
} }

View File

@ -3,17 +3,17 @@
var Node = require('./Node'); var Node = require('./Node');
var isCompoundExpression = require('../util/isCompoundExpression'); var isCompoundExpression = require('../util/isCompoundExpression');
function generateCodeForOperand(node, generator) { function generateCodeForOperand(node, codegen) {
var wrap = isCompoundExpression(node); var wrap = isCompoundExpression(node);
if (wrap) { if (wrap) {
generator.write('('); codegen.write('(');
} }
generator.generateCode(node); codegen.generateCode(node);
if (wrap) { if (wrap) {
generator.write(')'); codegen.write(')');
} }
} }
@ -25,7 +25,7 @@ class BinaryExpression extends Node {
this.right = def.right; this.right = def.right;
} }
generateCode(generator) { generateCode(codegen) {
var left = this.left; var left = this.left;
var operator = this.operator; var operator = this.operator;
var right = this.right; var right = this.right;
@ -34,11 +34,11 @@ class BinaryExpression extends Node {
throw new Error('Invalid BinaryExpression: ' + this); throw new Error('Invalid BinaryExpression: ' + this);
} }
generateCodeForOperand(left, generator); generateCodeForOperand(left, codegen);
generator.write(' '); codegen.write(' ');
generator.generateCode(operator); codegen.generateCode(operator);
generator.write(' '); codegen.write(' ');
generateCodeForOperand(right, generator); generateCodeForOperand(right, codegen);
} }
isCompoundExpression() { isCompoundExpression() {

View File

@ -68,12 +68,12 @@ class CustomTag extends HtmlElement {
this.tagDef = tagDef; this.tagDef = tagDef;
} }
generateCode(generator) { generateCode(codegen) {
var loadRendererVar = generator.addStaticVar('__renderer', '__helpers.r'); var loadRendererVar = codegen.addStaticVar('__renderer', '__helpers.r');
var tagVar = generator.addStaticVar('__tag', '__helpers.t'); var tagVar = codegen.addStaticVar('__tag', '__helpers.t');
var builder = generator.builder; var builder = codegen.builder;
var context = generator.context; var context = codegen.context;
var tagDef = this.tagDef; var tagDef = this.tagDef;
@ -83,7 +83,7 @@ class CustomTag extends HtmlElement {
let requireRendererFunctionCall = builder.require(JSON.stringify(rendererRequirePath)); let requireRendererFunctionCall = builder.require(JSON.stringify(rendererRequirePath));
let loadRendererFunctionCall = builder.functionCall(loadRendererVar, [ requireRendererFunctionCall ]); let loadRendererFunctionCall = builder.functionCall(loadRendererVar, [ requireRendererFunctionCall ]);
let rendererVar = generator.addStaticVar(removeExt(rendererPath), loadRendererFunctionCall); let rendererVar = codegen.addStaticVar(removeExt(rendererPath), loadRendererFunctionCall);
var inputProps = buildInputProps(this, context); var inputProps = buildInputProps(this, context);
var tagArgs = [ 'out', rendererVar, inputProps ]; var tagArgs = [ 'out', rendererVar, inputProps ];
var tagFunctionCall = builder.functionCall(tagVar, tagArgs); var tagFunctionCall = builder.functionCall(tagVar, tagArgs);

View File

@ -9,16 +9,16 @@ class Else extends Node {
this.matched = false; this.matched = false;
} }
generateCode(generator) { generateCode(codegen) {
if (!this.matched) { if (!this.matched) {
generator.addError('Unmatched else statement'); codegen.addError('Unmatched else statement');
return; return;
} }
var body = this.body; var body = this.body;
generator.write('else '); codegen.write('else ');
generator.generateBlock(body); codegen.generateBlock(body);
generator.write('\n'); codegen.write('\n');
} }
} }

View File

@ -11,15 +11,15 @@ class ElseIf extends Node {
this.matched = false; this.matched = false;
} }
generateCode(generator) { generateCode(codegen) {
if (!this.matched) { if (!this.matched) {
generator.addError('Unmatched else statement'); codegen.addError('Unmatched else statement');
return; return;
} }
var ifStatement = generator.builder.ifStatement(this.test, this.body, this.else); var ifStatement = codegen.builder.ifStatement(this.test, this.body, this.else);
generator.write('else '); codegen.write('else ');
generator.generateCode(ifStatement); codegen.generateCode(ifStatement);
} }
} }

View File

@ -10,8 +10,8 @@ class Expression extends Node {
ok(this.value != null, 'Invalid expression'); ok(this.value != null, 'Invalid expression');
} }
generateCode(generator) { generateCode(codegen) {
generator.generateCode(this.value); codegen.generateCode(this.value);
} }
isCompoundExpression() { isCompoundExpression() {

View File

@ -16,14 +16,14 @@ class ForEach extends Node {
ok(this.in != null, '"in" is required'); ok(this.in != null, '"in" is required');
} }
generateCode(generator) { generateCode(codegen) {
var varName = this.varName; var varName = this.varName;
var inExpression = this.in; var inExpression = this.in;
var separator = this.separator; var separator = this.separator;
var statusVarName = this.statusVarName; var statusVarName = this.statusVarName;
var iterator = this.iterator; var iterator = this.iterator;
var builder = generator.builder; var builder = codegen.builder;
if (separator && !statusVarName) { if (separator && !statusVarName) {
statusVarName = '__loop'; statusVarName = '__loop';
@ -41,7 +41,7 @@ class ForEach extends Node {
builder.functionDeclaration(null, params, this.body) builder.functionDeclaration(null, params, this.body)
]); ]);
} else if (statusVarName) { } else if (statusVarName) {
let forEachVarName = generator.addStaticVar('forEachWithStatusVar', '__helpers.fv'); let forEachVarName = codegen.addStaticVar('forEachWithStatusVar', '__helpers.fv');
let body = this.body; let body = this.body;
if (separator) { if (separator) {
@ -63,7 +63,7 @@ class ForEach extends Node {
builder.functionDeclaration(null, [varName, statusVarName], body) builder.functionDeclaration(null, [varName, statusVarName], body)
]); ]);
} else { } else {
let forEachVarName = generator.addStaticVar('forEach', '__helpers.f'); let forEachVarName = codegen.addStaticVar('forEach', '__helpers.f');
return builder.functionCall(forEachVarName, [ return builder.functionCall(forEachVarName, [
inExpression, inExpression,

View File

@ -15,15 +15,15 @@ class ForEachProp extends Node {
ok(this.in != null, '"in" is required'); ok(this.in != null, '"in" is required');
} }
generateCode(generator) { generateCode(codegen) {
var nameVarName = this.nameVarName; var nameVarName = this.nameVarName;
var valueVarName = this.valueVarName; var valueVarName = this.valueVarName;
var inExpression = this.in; var inExpression = this.in;
var body = this.body; var body = this.body;
var builder = generator.builder; var builder = codegen.builder;
let forEachVarName = generator.addStaticVar('forEachProp', '__helpers.fp'); let forEachVarName = codegen.addStaticVar('forEachProp', '__helpers.fp');
return builder.functionCall(forEachVarName, [ return builder.functionCall(forEachVarName, [
inExpression, inExpression,

View File

@ -17,13 +17,13 @@ class ForRange extends Node {
ok(this.from != null, '"from" is required'); ok(this.from != null, '"from" is required');
} }
generateCode(generator) { generateCode(codegen) {
var varName = this.varName; var varName = this.varName;
var from = this.from; var from = this.from;
var to = this.to; var to = this.to;
var step = this.step; var step = this.step;
var builder = generator.builder; var builder = codegen.builder;
var comparison = '<='; var comparison = '<=';

View File

@ -11,35 +11,35 @@ class ForStatement extends Node {
this.body = this.makeContainer(def.body); this.body = this.makeContainer(def.body);
} }
generateCode(generator) { generateCode(codegen) {
var init = this.init; var init = this.init;
var test = this.test; var test = this.test;
var update = this.update; var update = this.update;
var body = this.body; var body = this.body;
generator.write('for ('); codegen.write('for (');
if (init) { if (init) {
generator.generateCode(init); codegen.generateCode(init);
} }
generator.write('; '); codegen.write('; ');
if (test) { if (test) {
generator.generateCode(test); codegen.generateCode(test);
} }
generator.write('; '); codegen.write('; ');
if (update) { if (update) {
generator.generateCode(update); codegen.generateCode(update);
} }
generator.write(') '); codegen.write(') ');
generator.generateBlock(body); codegen.generateBlock(body);
generator.write('\n'); codegen.write('\n');
} }
} }

View File

@ -13,29 +13,29 @@ class FunctionCall extends Node {
} }
} }
generateCode(generator) { generateCode(codegen) {
var callee = this.callee; var callee = this.callee;
var args = this.args; var args = this.args;
generator.generateCode(callee); codegen.generateCode(callee);
generator.write('('); codegen.write('(');
if (args && args.length) { if (args && args.length) {
for (let i=0, argsLen = args.length; i<argsLen; i++) { for (let i=0, argsLen = args.length; i<argsLen; i++) {
if (i !== 0) { if (i !== 0) {
generator.write(', '); codegen.write(', ');
} }
let arg = args[i]; let arg = args[i];
if (!arg) { if (!arg) {
throw new Error('Arg ' + i + ' is not valid for function call: ' + JSON.stringify(this.toJSON())); throw new Error('Arg ' + i + ' is not valid for function call: ' + JSON.stringify(this.toJSON()));
} }
generator.generateCode(arg); codegen.generateCode(arg);
} }
} }
generator.write(')'); codegen.write(')');
} }
} }

View File

@ -11,7 +11,7 @@ class FunctionDeclaration extends Node {
this.body = this.makeContainer(def.body); this.body = this.makeContainer(def.body);
} }
generateCode(generator) { generateCode(codegen) {
var name = this.name; var name = this.name;
var params = this.params; var params = this.params;
var body = this.body; var body = this.body;
@ -21,34 +21,34 @@ class FunctionDeclaration extends Node {
ok(typeof name === 'string', 'Function name should be a string'); ok(typeof name === 'string', 'Function name should be a string');
} }
generator.write('function' + (name ? ' ' + name : '') + '('); codegen.write('function' + (name ? ' ' + name : '') + '(');
if (params && params.length) { if (params && params.length) {
for (let i=0, paramsLen = params.length; i<paramsLen; i++) { for (let i=0, paramsLen = params.length; i<paramsLen; i++) {
if (i !== 0) { if (i !== 0) {
generator.write(', '); codegen.write(', ');
} }
var param = params[i]; var param = params[i];
if (typeof param === 'string') { if (typeof param === 'string') {
generator.write(param); codegen.write(param);
} else { } else {
if (param.type !== 'Identifier') { if (param.type !== 'Identifier') {
throw new Error('Illegal param: ' + param); throw new Error('Illegal param: ' + param);
} }
generator.generateCode(param); codegen.generateCode(param);
} }
} }
} }
generator.write(') '); codegen.write(') ');
var oldInFunction = generator.inFunction; var oldInFunction = codegen.inFunction;
generator.inFunction = true; codegen.inFunction = true;
generator.generateBlock(body); codegen.generateBlock(body);
generator.inFunction = oldInFunction; codegen.inFunction = oldInFunction;
if (statement) { if (statement) {
generator.write('\n'); codegen.write('\n');
} }
} }

View File

@ -12,9 +12,9 @@ class Html extends Node {
return this.argument instanceof Node && this.argument.type === 'Literal'; return this.argument instanceof Node && this.argument.type === 'Literal';
} }
generateHtmlCode(generator) { generateHtmlCode(codegen) {
let argument = this.argument; let argument = this.argument;
generator.addWrite(argument); codegen.addWrite(argument);
} }
} }

View File

@ -8,13 +8,13 @@ class HtmlComment extends Node {
this.comment = def.comment; this.comment = def.comment;
} }
generateHtmlCode(generator) { generateHtmlCode(codegen) {
var comment = this.comment; var comment = this.comment;
var literal = generator.builder.literal; var literal = codegen.builder.literal;
generator.addWrite(literal('<--')); codegen.addWrite(literal('<--'));
generator.addWrite(comment); codegen.addWrite(comment);
generator.addWrite(literal('-->')); codegen.addWrite(literal('-->'));
} }
} }

View File

@ -36,12 +36,12 @@ class HtmlElement extends Node {
this._dynamicAttributesExpressionArray = undefined; this._dynamicAttributesExpressionArray = undefined;
} }
generateHtmlCode(generator) { generateHtmlCode(codegen) {
var tagName = this.tagName; var tagName = this.tagName;
// Convert the tag name into a Node so that we generate the code correctly // Convert the tag name into a Node so that we generate the code correctly
if (tagName) { if (tagName) {
tagName = generator.builder.literal(tagName); tagName = codegen.builder.literal(tagName);
} else { } else {
tagName = this.dynamicTagName; tagName = this.dynamicTagName;
} }
@ -50,12 +50,12 @@ class HtmlElement extends Node {
var startTagOnly = this.startTagOnly; var startTagOnly = this.startTagOnly;
var allowSelfClosing = this.allowSelfClosing; var allowSelfClosing = this.allowSelfClosing;
var hasBody = body && body.length; var hasBody = body && body.length;
var builder = generator.builder; var builder = codegen.builder;
// Starting tag // Starting tag
generator.addWriteLiteral('<'); codegen.addWriteLiteral('<');
generator.addWrite(tagName); codegen.addWrite(tagName);
var attributes = this._attributes && this._attributes.all; var attributes = this._attributes && this._attributes.all;
@ -69,51 +69,51 @@ class HtmlElement extends Node {
var literalValue = attrValue.value; var literalValue = attrValue.value;
if (typeof literalValue === 'boolean') { if (typeof literalValue === 'boolean') {
if (literalValue === true) { if (literalValue === true) {
generator.addWriteLiteral(' ' + attrName); codegen.addWriteLiteral(' ' + attrName);
} }
} else if (literalValue != null) { } else if (literalValue != null) {
generator.addWriteLiteral(' ' + attrName + '="' + escapeXmlAttr(literalValue) + '"'); codegen.addWriteLiteral(' ' + attrName + '="' + escapeXmlAttr(literalValue) + '"');
} }
} else if (attrValue) { } else if (attrValue) {
generator.addWriteLiteral(' ' + attrName + '="'); codegen.addWriteLiteral(' ' + attrName + '="');
generator.isInAttribute = true; codegen.isInAttribute = true;
// TODO Deal with escaping dynamic HTML attribute expression // TODO Deal with escaping dynamic HTML attribute expression
generator.addWrite(attrValue); codegen.addWrite(attrValue);
generator.isInAttribute = false; codegen.isInAttribute = false;
generator.addWriteLiteral('"'); codegen.addWriteLiteral('"');
} else if (attr.argument) { } else if (attr.argument) {
generator.addWriteLiteral(' ' + attrName + '('); codegen.addWriteLiteral(' ' + attrName + '(');
generator.addWriteLiteral(attr.argument); codegen.addWriteLiteral(attr.argument);
generator.addWriteLiteral(')'); codegen.addWriteLiteral(')');
} }
} }
} }
if (this._dynamicAttributesExpressionArray) { if (this._dynamicAttributesExpressionArray) {
this._dynamicAttributesExpressionArray.forEach(function(attrsExpression) { this._dynamicAttributesExpressionArray.forEach(function(attrsExpression) {
generator.addStaticVar('attrs', '__helpers.as'); codegen.addStaticVar('attrs', '__helpers.as');
let attrsFunctionCall = builder.functionCall('attrs', [attrsExpression]); let attrsFunctionCall = builder.functionCall('attrs', [attrsExpression]);
generator.addWrite(attrsFunctionCall); codegen.addWrite(attrsFunctionCall);
}); });
} }
// Body // Body
if (hasBody) { if (hasBody) {
generator.addWriteLiteral('>'); codegen.addWriteLiteral('>');
generator.generateStatements(body); codegen.generateStatements(body);
generator.addWriteLiteral('</'); codegen.addWriteLiteral('</');
generator.addWrite(tagName); codegen.addWrite(tagName);
generator.addWriteLiteral('>'); codegen.addWriteLiteral('>');
} else { } else {
if (startTagOnly) { if (startTagOnly) {
generator.addWriteLiteral('>'); codegen.addWriteLiteral('>');
} else if (allowSelfClosing) { } else if (allowSelfClosing) {
generator.addWriteLiteral('/>'); codegen.addWriteLiteral('/>');
} else { } else {
generator.addWriteLiteral('></'); codegen.addWriteLiteral('></');
generator.addWrite(tagName); codegen.addWrite(tagName);
generator.addWriteLiteral('>'); codegen.addWriteLiteral('>');
} }
} }
} }

View File

@ -8,9 +8,9 @@ class Identifier extends Node {
this.name = def.name; this.name = def.name;
} }
generateCode(generator) { generateCode(codegen) {
var name = this.name; var name = this.name;
generator.write(name); codegen.write(name);
} }
} }

View File

@ -17,7 +17,7 @@ class If extends Node {
this.else = def.else; this.else = def.else;
} }
generateCode(generator) { generateCode(codegen) {
if (this.else) { if (this.else) {
this.else.matched = true; this.else.matched = true;
@ -62,15 +62,15 @@ class If extends Node {
var test = this.test; var test = this.test;
var body = this.body; var body = this.body;
generator.write('if ('); codegen.write('if (');
generator.generateCode(test); codegen.generateCode(test);
generator.write(') '); codegen.write(') ');
generator.generateBlock(body); codegen.generateBlock(body);
if (this.else) { if (this.else) {
generator.write(' '); codegen.write(' ');
generator.generateCode(this.else); codegen.generateCode(this.else);
} else { } else {
generator.write('\n'); codegen.write('\n');
} }
} }

View File

@ -8,9 +8,9 @@ class Literal extends Node {
this.value = def.value; this.value = def.value;
} }
generateCode(generator) { generateCode(codegen) {
var value = this.value; var value = this.value;
generator.writeLiteral(value); codegen.writeLiteral(value);
} }
} }

View File

@ -10,20 +10,20 @@ class MemberExpression extends Node {
this.computed = def.computed; this.computed = def.computed;
} }
generateCode(generator) { generateCode(codegen) {
var object = this.object; var object = this.object;
var property = this.property; var property = this.property;
var computed = this.computed; var computed = this.computed;
generator.generateCode(object); codegen.generateCode(object);
if (computed) { if (computed) {
generator.write('['); codegen.write('[');
generator.generateCode(property); codegen.generateCode(property);
generator.write(']'); codegen.write(']');
} else { } else {
generator.write('.'); codegen.write('.');
generator.generateCode(property); codegen.generateCode(property);
} }
} }

View File

@ -7,12 +7,12 @@ class Program extends Node {
this.body = def.body; this.body = def.body;
} }
generateCode(generator) { generateCode(codegen) {
var body = this.body; var body = this.body;
generator.generateStatements(body); codegen.generateStatements(body);
if (generator._bufferedWrites) { if (codegen._bufferedWrites) {
generator._write('\n'); codegen._write('\n');
generator._flushBufferedWrites(); codegen._flushBufferedWrites();
} }
} }
} }

View File

@ -8,17 +8,17 @@ class Return extends Node {
this.argument = def.argument; this.argument = def.argument;
} }
generateCode(generator) { generateCode(codegen) {
if (!generator.inFunction) { if (!codegen.inFunction) {
throw new Error('"return" not allowed outside a function body'); throw new Error('"return" not allowed outside a function body');
} }
var argument = this.argument; var argument = this.argument;
generator.write('return '); codegen.write('return ');
if (argument) { if (argument) {
generator.generateCode(argument); codegen.generateCode(argument);
} }
} }
} }

View File

@ -10,17 +10,17 @@ class SelfInvokingFunction extends Node {
this.body = this.makeContainer(def.body); this.body = this.makeContainer(def.body);
} }
generateCode(generator) { generateCode(codegen) {
var params = this.params || []; var params = this.params || [];
var args = this.args || []; var args = this.args || [];
var body = this.body; var body = this.body;
generator.write('('); codegen.write('(');
var functionDeclaration = generator.builder.functionDeclaration(null, params, body); var functionDeclaration = codegen.builder.functionDeclaration(null, params, body);
var functionCall = generator.builder.functionCall(functionDeclaration, args); var functionCall = codegen.builder.functionCall(functionDeclaration, args);
generator.generateCode(functionCall); codegen.generateCode(functionCall);
generator.write(')'); codegen.write(')');
} }
} }

View File

@ -6,24 +6,24 @@ class Slot extends Node {
constructor(def) { constructor(def) {
super('Slot'); super('Slot');
this.onDone = def.onDone; this.onDone = def.onDone;
this.generatorSlot = null; this.codegenSlot = null;
} }
generateCode(generator) { generateCode(codegen) {
if (this.onDone) { if (this.onDone) {
generator.onDone((generator) => { codegen.onDone((codegen) => {
this.onDone(this, generator); this.onDone(this, codegen);
}); });
} }
// At the time the code for this node is to be generated we instead // At the time the code for this node is to be generated we instead
// create a slot. A slot is just a marker in the output code stream // create a slot. A slot is just a marker in the output code stream
// that we can later inject code into. The injection happens after // that we can later inject code into. The injection happens after
// the entire tree has been walked. // the entire tree has been walked.
this.generatorSlot = generator.beginSlot(this); this.codegenSlot = codegen.beginSlot(this);
} }
setContent(content) { setContent(content) {
this.generatorSlot.setContent(content); this.codegenSlot.setContent(content);
} }
toJSON() { toJSON() {

View File

@ -17,14 +17,14 @@ class TemplateRoot extends Node {
this.body = this.makeContainer(def.body); this.body = this.makeContainer(def.body);
} }
generateCode(generator) { generateCode(codegen) {
var body = this.body; var body = this.body;
generator.addStaticVar('str', '__helpers.s'); codegen.addStaticVar('str', '__helpers.s');
generator.addStaticVar('empty', '__helpers.e'); codegen.addStaticVar('empty', '__helpers.e');
generator.addStaticVar('notEmpty', '__helpers.ne'); codegen.addStaticVar('notEmpty', '__helpers.ne');
generator.addStaticVar('escapeXml', '__helpers.x'); codegen.addStaticVar('escapeXml', '__helpers.x');
var builder = generator.builder; var builder = codegen.builder;
var program = builder.program; var program = builder.program;
var functionDeclaration = builder.functionDeclaration; var functionDeclaration = builder.functionDeclaration;
var vars = builder.vars; var vars = builder.vars;
@ -43,9 +43,9 @@ class TemplateRoot extends Node {
'(module.exports = require("marko").c(__filename)).c(create)' '(module.exports = require("marko").c(__filename)).c(create)'
]); ]);
generator.generateCode(outputNode); codegen.generateCode(outputNode);
var staticVars = generator.getStaticVars(); var staticVars = codegen.getStaticVars();
staticsSlot.setContent([ staticsSlot.setContent([
vars(createVarsArray(staticVars)) vars(createVarsArray(staticVars))

View File

@ -38,7 +38,7 @@ class Text extends Node {
return this.argument instanceof Node && this.argument.type === 'Literal'; return this.argument instanceof Node && this.argument.type === 'Literal';
} }
generateHtmlCode(generator) { generateHtmlCode(codegen) {
this.normalizeText(); this.normalizeText();
var argument = this.argument; var argument = this.argument;
@ -48,7 +48,7 @@ class Text extends Node {
return; return;
} }
} else { } else {
let builder = generator.builder; let builder = codegen.builder;
// TODO Only escape if necessary // TODO Only escape if necessary
argument = builder.functionCall( argument = builder.functionCall(
@ -56,10 +56,10 @@ class Text extends Node {
[argument]); [argument]);
} }
generator.addWrite(argument); codegen.addWrite(argument);
} }
normalizeText(generator) { normalizeText(codegen) {
if (this.normalized) { if (this.normalized) {
return; return;
} }

View File

@ -11,33 +11,33 @@ class UnaryExpression extends Node {
this.prefix = def.prefix === true; this.prefix = def.prefix === true;
} }
generateCode(generator) { generateCode(codegen) {
var argument = this.argument; var argument = this.argument;
var operator = this.operator; var operator = this.operator;
var prefix = this.prefix; var prefix = this.prefix;
if (prefix) { if (prefix) {
generator.write(operator); codegen.write(operator);
if (operator === 'typeof') { if (operator === 'typeof') {
generator.write(' '); codegen.write(' ');
} }
} }
var wrap = isCompoundExpression(argument); var wrap = isCompoundExpression(argument);
if (wrap) { if (wrap) {
generator.write('('); codegen.write('(');
} }
generator.generateCode(argument); codegen.generateCode(argument);
if (wrap) { if (wrap) {
generator.write(')'); codegen.write(')');
} }
if (!prefix) { if (!prefix) {
generator.write(operator); codegen.write(operator);
} }
} }

View File

@ -11,29 +11,29 @@ class UpdateExpression extends Node {
this.prefix = def.prefix === true; this.prefix = def.prefix === true;
} }
generateCode(generator) { generateCode(codegen) {
var argument = this.argument; var argument = this.argument;
var operator = this.operator; var operator = this.operator;
var prefix = this.prefix; var prefix = this.prefix;
if (prefix) { if (prefix) {
generator.generateCode(operator); codegen.generateCode(operator);
} }
var wrap = isCompoundExpression(argument); var wrap = isCompoundExpression(argument);
if (wrap) { if (wrap) {
generator.write('('); codegen.write('(');
} }
generator.generateCode(argument); codegen.generateCode(argument);
if (wrap) { if (wrap) {
generator.write(')'); codegen.write(')');
} }
if (!prefix) { if (!prefix) {
generator.generateCode(operator); codegen.generateCode(operator);
} }
} }

View File

@ -11,7 +11,7 @@ class Vars extends Node {
this.body = this.makeContainer(def.body); this.body = this.makeContainer(def.body);
} }
generateCode(generator) { generateCode(codegen) {
var declarations = this.declarations; var declarations = this.declarations;
var kind = this.kind; var kind = this.kind;
var isStatement = this.statement; var isStatement = this.statement;
@ -21,7 +21,7 @@ class Vars extends Node {
if(!selfInvoking && hasBody) { if(!selfInvoking && hasBody) {
this.setFlag('selfInvoking'); this.setFlag('selfInvoking');
return generator.builder.selfInvokingFunction([ this ]); return codegen.builder.selfInvokingFunction([ this ]);
} }
if (!declarations || !declarations.length) { if (!declarations || !declarations.length) {
@ -32,10 +32,10 @@ class Vars extends Node {
var declaration = declarations[i]; var declaration = declarations[i];
if (i === 0) { if (i === 0) {
generator.write(kind + ' '); codegen.write(kind + ' ');
} else { } else {
generator.incIndent(4); codegen.incIndent(4);
generator.writeLineIndent(); codegen.writeLineIndent();
} }
var varId = declaration.id || declaration.name; var varId = declaration.id || declaration.name;
@ -45,7 +45,7 @@ class Vars extends Node {
} }
// TODO Validate the variable name // TODO Validate the variable name
generator.generateCode(varId); codegen.generateCode(varId);
var initValue; var initValue;
if (declaration.hasOwnProperty('init')) { if (declaration.hasOwnProperty('init')) {
@ -55,24 +55,24 @@ class Vars extends Node {
} }
if (initValue != null) { if (initValue != null) {
generator.write(' = '); codegen.write(' = ');
generator.generateCode(initValue); codegen.generateCode(initValue);
} }
if (i !== 0) { if (i !== 0) {
generator.decIndent(4); codegen.decIndent(4);
} }
if (i < declarations.length - 1) { if (i < declarations.length - 1) {
generator.write(',\n'); codegen.write(',\n');
} else { } else {
if (isStatement) { if (isStatement) {
generator.write(';\n'); codegen.write(';\n');
} }
} }
} }
if(hasBody) { if(hasBody) {
generator.generateCode(body); codegen.generateCode(body);
} }
} }
} }

View File

@ -165,7 +165,7 @@ TagHandlers.prototype = {
* A custom tag can be mapped to module that is is used * A custom tag can be mapped to module that is is used
* to generate compile-time code for the custom tag. A * to generate compile-time code for the custom tag. A
* node type is created based on the methods and methods * node type is created based on the methods and methods
* exported by the code generator module. * exported by the code codegen module.
*/ */
codeGenerator: function(value) { codeGenerator: function(value) {
var tag = this.tag; var tag = this.tag;

View File

@ -1,18 +1,18 @@
var createLoopNode = require('./util/createLoopNode'); var createLoopNode = require('./util/createLoopNode');
module.exports = function codeGenerator(elNode, generator) { module.exports = function codeGenerator(elNode, codegen) {
var argument = elNode.argument; var argument = elNode.argument;
if (!argument) { if (!argument) {
generator.addError('Invalid <for> tag. Argument is missing. Example; <for(color in colors)>'); codegen.addError('Invalid <for> tag. Argument is missing. Example; <for(color in colors)>');
return elNode; return elNode;
} }
var builder = generator.builder; var builder = codegen.builder;
var loopNode = createLoopNode(argument, elNode.body, builder); var loopNode = createLoopNode(argument, elNode.body, builder);
if (loopNode.error) { if (loopNode.error) {
generator.addError(loopNode.error); codegen.addError(loopNode.error);
return elNode; return elNode;
} }

View File

@ -12,7 +12,7 @@ var autotest = require('./autotest');
var CompileContext = require('../compiler/CompileContext'); var CompileContext = require('../compiler/CompileContext');
var CodeGenerator = require('../compiler/CodeGenerator'); var CodeGenerator = require('../compiler/CodeGenerator');
function createGenerator() { function createCodeGenerator() {
var context = new CompileContext('dummy', 'dummy.marko', builder); var context = new CompileContext('dummy', 'dummy.marko', builder);
return new CodeGenerator(context); return new CodeGenerator(context);
} }
@ -24,9 +24,9 @@ describe('compiler/codegen', function() {
var main = require(path.join(dir, 'index.js')); var main = require(path.join(dir, 'index.js'));
var generateCodeFunc = main; var generateCodeFunc = main;
var ast = generateCodeFunc(builder); var ast = generateCodeFunc(builder);
var generator = createGenerator(); var codegen = createCodeGenerator();
generator.generateCode(ast); codegen.generateCode(ast);
return generator.getCode(); return codegen.getCode();
}); });
it('should not allow a return outside a function', function() { it('should not allow a return outside a function', function() {
@ -37,8 +37,8 @@ describe('compiler/codegen', function() {
builder.returnStatement('foo') builder.returnStatement('foo')
]); ]);
var generator = createGenerator(); var codegen = createCodeGenerator();
generator.generateCode(rootNode); codegen.generateCode(rootNode);
}).to.throw('"return" not allowed outside a function body'); }).to.throw('"return" not allowed outside a function body');
}); });
}); });

View File

@ -1,8 +1,8 @@
'use strict'; 'use strict';
module.exports = function(builder) { module.exports = function(builder) {
return builder.node(function(node, generator) { return builder.node(function(node, codegen) {
var builder = generator.builder; var builder = codegen.builder;
return builder.text(builder.literal('Hello World!')); return builder.text(builder.literal('Hello World!'));
}); });
}; };

View File

@ -5,19 +5,19 @@ module.exports = function(builder) {
return builder.program([ return builder.program([
builder.assignment('a', builder.literal('abc')), builder.assignment('a', builder.literal('abc')),
builder.slot((slot, generator) => { builder.slot((slot, codegen) => {
slot.setContent(generator.builder.vars(vars)); slot.setContent(codegen.builder.vars(vars));
}), }),
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'foo', id: 'foo',
init: generator.builder.literal('abc') init: codegen.builder.literal('abc')
}); });
}), }),
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'bar', id: 'bar',
init: generator.builder.literal(123) init: codegen.builder.literal(123)
}); });
}), }),
builder.assignment('b', builder.literal('def')) builder.assignment('b', builder.literal('def'))

View File

@ -3,21 +3,21 @@
module.exports = function(builder) { module.exports = function(builder) {
var vars = []; var vars = [];
var varsSlot = builder.slot((slot, generator) => { var varsSlot = builder.slot((slot, codegen) => {
slot.setContent(generator.builder.vars(vars)); slot.setContent(codegen.builder.vars(vars));
}); });
return builder.program([ return builder.program([
builder.ifStatement('true', [ builder.ifStatement('true', [
builder.text(builder.literal('BEFORE - Hello World')), builder.text(builder.literal('BEFORE - Hello World')),
varsSlot, varsSlot,
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'foo', id: 'foo',
init: builder.literal('abc') init: builder.literal('abc')
}); });
}), }),
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'bar', id: 'bar',
init: builder.literal(123) init: builder.literal(123)

View File

@ -3,20 +3,20 @@
module.exports = function(builder) { module.exports = function(builder) {
var vars = []; var vars = [];
var varsSlot = builder.slot((slot, generator) => { var varsSlot = builder.slot((slot, codegen) => {
slot.setContent(generator.builder.vars(vars)); slot.setContent(codegen.builder.vars(vars));
}); });
return builder.program([ return builder.program([
builder.text(builder.literal('BEFORE - Hello World')), builder.text(builder.literal('BEFORE - Hello World')),
varsSlot, varsSlot,
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'foo', id: 'foo',
init: builder.literal('abc') init: builder.literal('abc')
}); });
}), }),
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'bar', id: 'bar',
init: builder.literal(123) init: builder.literal(123)

View File

@ -4,19 +4,19 @@ module.exports = function(builder) {
var vars = []; var vars = [];
return builder.program([ return builder.program([
builder.slot((slot, generator) => { builder.slot((slot, codegen) => {
slot.setContent(generator.builder.vars(vars)); slot.setContent(codegen.builder.vars(vars));
}), }),
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'foo', id: 'foo',
init: generator.builder.literal('abc') init: codegen.builder.literal('abc')
}); });
}), }),
builder.node(function(node, generator) { builder.node(function(node, codegen) {
vars.push({ vars.push({
id: 'bar', id: 'bar',
init: generator.builder.literal(123) init: codegen.builder.literal(123)
}); });
}) })
]); ]);

View File

@ -1,5 +1,5 @@
module.exports = function generateCode(elNode, generator) { module.exports = function generateCode(elNode, codegen) {
var builder = generator.builder; var builder = codegen.builder;
return [ return [
builder.text(builder.literal('Hello ')), builder.text(builder.literal('Hello ')),
builder.text(elNode.getAttributeValue('name')) builder.text(elNode.getAttributeValue('name'))

View File

@ -1,5 +1,5 @@
module.exports = function generateCode(elNode, generator) { module.exports = function generateCode(elNode, codegen) {
var builder = generator.builder; var builder = codegen.builder;
return builder.functionCall('out.write', [ return builder.functionCall('out.write', [
builder.binaryExpression('"Hello "', '+', elNode.getAttributeValue('name')) builder.binaryExpression('"Hello "', '+', elNode.getAttributeValue('name'))
]); ]);

View File

@ -1,5 +1,5 @@
module.exports = function generateCode(elNode, generator) { module.exports = function generateCode(elNode, codegen) {
var builder = generator.builder; var builder = codegen.builder;
elNode.setAttributeValue('foo', builder.literal('bar')); elNode.setAttributeValue('foo', builder.literal('bar'));
return elNode; return elNode;
}; };

View File

@ -1,5 +1,5 @@
module.exports = function generateCode(elNode, generator) { module.exports = function generateCode(elNode, codegen) {
var builder = generator.builder; var builder = codegen.builder;
return builder.htmlElement( return builder.htmlElement(
'div', 'div',