Restored range looping functionality

This commit is contained in:
Patrick Steele-Idem 2015-12-07 13:21:02 -07:00
parent a9fd496589
commit 4b38989892
10 changed files with 178 additions and 30 deletions

View File

@ -1,6 +1,5 @@
'use strict';
var isArray = Array.isArray;
var ok = require('assert').ok;
var Program = require('./ast/Program');
var TemplateRoot = require('./ast/TemplateRoot');
@ -21,6 +20,8 @@ var TextOutput = require('./ast/TextOutput');
var ForEach = require('./ast/ForEach');
var Slot = require('./ast/Slot');
var HtmlComment = require('./ast/HtmlComment');
var SelfInvokingFunction = require('./ast/SelfInvokingFunction');
var ForStatement = require('./ast/ForStatement');
class Builder {
program(body) {
@ -47,6 +48,16 @@ class Builder {
return new FunctionCall({callee, args});
}
selfInvokingFunction(params, args, body) {
if (arguments.length === 1) {
body = arguments[0];
params = null;
args = null;
}
return new SelfInvokingFunction({params, args, body});
}
literal(value) {
return new Literal({value});
}
@ -128,6 +139,15 @@ class Builder {
let args = [ path ];
return new FunctionCall({callee, args});
}
forStatement(init, test, update, body) {
if (typeof init === 'object' && !init.type) {
var def = arguments[0];
return new ForStatement(def);
} else {
return new ForStatement({init, test, update, body});
}
}
}
module.exports = Builder;

View File

@ -26,15 +26,28 @@ class Slot {
}
generateCode(generator) {
if (!this._content) {
var content = this._content;
if (!content) {
return;
}
var isStatement = this._statement;
generator._currentIndent = this._currentIndent;
generator.inFunction = this._inFunction;
var capture = generator._beginCaptureCode();
generator.generateCode(this._content);
if (isArray(content) || (content instanceof Container)) {
content.forEach((node) => {
node.statement = isStatement;
generator.generateCode(node);
});
} else {
content.statement = isStatement;
generator.generateCode(content);
}
var slotCode = capture.end();
@ -96,9 +109,11 @@ class Generator {
}
generateCode(node) {
ok(node, '"node" is required');
ok(node != null, '"node" is required');
if (typeof node === 'string') {
if (typeof node === 'string' ||
typeof node === 'number' ||
typeof node === 'boolean') {
this.write(node);
return;
} else if (isArray(node) || (node instanceof Container)) {

View File

@ -15,7 +15,7 @@ class ForEach extends Node {
this.step = def.step;
ok(this.varName, '"varName" is required');
ok(this.target, '"target" is required');
ok(this.target != null || this.from != null, '"target" or "from" is required');
}
generateCode(generator) {
@ -26,9 +26,9 @@ class ForEach extends Node {
var builder = generator.builder;
if (this.from) {
if (this.from != null) {
// This is a range loop
var from = This.from;
var from = this.from;
var to = this.to;
var step = this.step;
var comparison = '<=';
@ -54,12 +54,16 @@ class ForEach extends Node {
step = varName + '+=' + step;
}
// template.statement('(function() {').indent(function () {
// template.statement('for (var ' + nameVar + '=' + from + '; ' + nameVar + comparison + to + '; ' + step + ') {').indent(function () {
// this.generateCodeForChildren(template);
// }, this).line('}');
// }, this).line('}());');
return;
return builder.selfInvokingFunction([
builder.forStatement({
init: [
builder.vars([ { id: varName, init: from }])
],
test: varName + comparison + to,
update: step,
body: this.body
})
]);
}
if (separator && !statusVarName) {

View File

@ -0,0 +1,46 @@
'use strict';
var Node = require('./Node');
class ForStatement extends Node {
constructor(def) {
super('ForStatement');
this.init = def.init;
this.test = def.test;
this.update = def.update;
this.body = this.makeContainer(def.body);
}
generateCode(generator) {
var init = this.init;
var test = this.test;
var update = this.update;
var body = this.body;
generator.write('for (');
if (init) {
generator.generateCode(init);
}
generator.write('; ');
if (test) {
generator.generateCode(test);
}
generator.write('; ');
if (update) {
generator.generateCode(update);
}
generator.write(') ');
generator.generateBlock(body);
generator.write('\n');
}
}
module.exports = ForStatement;

View File

@ -0,0 +1,32 @@
'use strict';
var Node = require('./Node');
class SelfInvokingFunction extends Node {
constructor(def) {
super('SelfInvokingFunction');
this.params = def.params;
this.args = def.args;
this.body = this.makeContainer(def.body);
}
generateCode(generator) {
var params = this.params || [];
var args = this.args || [];
var body = this.body;
var isStatement = this.statement;
generator.write('(');
var functionDeclaration = generator.builder.functionDeclaration(null, params, body);
var functionCall = generator.builder.functionCall(functionDeclaration, args);
generator.generateCode(functionCall);
generator.write(')');
if (isStatement) {
generator.write('\n');
}
}
}
module.exports = SelfInvokingFunction;

View File

@ -12,6 +12,7 @@ class Vars extends Node {
generateCode(generator) {
var declarations = this.declarations;
var kind = this.kind;
var isStatement = this.statement;
if (!declarations || !declarations.length) {
return;
@ -43,7 +44,7 @@ class Vars extends Node {
initValue = declaration.value;
}
if (initValue) {
if (initValue != null) {
generator.write(' = ');
generator.generateCode(initValue);
}
@ -51,7 +52,9 @@ class Vars extends Node {
if (i < declarations.length - 1) {
generator.write(',\n');
} else {
generator.write(';\n');
if (isStatement) {
generator.write(';\n');
}
}
}
}

View File

@ -55,27 +55,28 @@ exports.scanDir = function(autoTestDir, run, options) {
files = fs.readdirSync(autoTestDir);
} catch(e) {
console.warn('autotest directory does not exist: ' + autoTestDir);
return;
}
files.forEach(function(name) {
if (name.charAt(0) === '.') {
return;
}
if (files) {
files.forEach(function(name) {
if (name.charAt(0) === '.') {
return;
}
var itFunc = it;
var itFunc = it;
if (enabledTest && name === enabledTest) {
itFunc = it.only;
}
if (enabledTest && name === enabledTest) {
itFunc = it.only;
}
var dir = path.join(autoTestDir, name);
var dir = path.join(autoTestDir, name);
itFunc(`[${name}] `, function() {
autoTest(name, dir, run, options);
});
itFunc(`[${name}] `, function() {
autoTest(name, dir, run, options);
});
});
}
var pendingFiles;
try {

View File

@ -0,0 +1,27 @@
<for(i from 0 to 9)>
${i}
</for>
-
<for(i from 9 to 0)>
${i}
</for>
-
<for(i from 9 to 0 step -1)>
${i}
</for>
-
<for(i from 0 to 9 step 2)>
${i}
</for>
-
<for(i from 9 to 0 step -2)>
${i}
</for>
-
<for(i from 0 to 'abc'.length)>
${i}
</for>
-
<for(i from ''.length to 'abc'.length)>
${i}
</for>