Track source node via accept call rather vs opcode
This commit is contained in:
@@ -62,6 +62,7 @@ Compiler.prototype = {
|
||||
guid: 0,
|
||||
|
||||
compile: function(program, options) {
|
||||
this.sourceNode = [];
|
||||
this.opcodes = [];
|
||||
this.children = [];
|
||||
this.depths = {list: []};
|
||||
@@ -91,11 +92,15 @@ Compiler.prototype = {
|
||||
},
|
||||
|
||||
accept: function(node) {
|
||||
return this[node.type](node);
|
||||
this.sourceNode.unshift(node);
|
||||
var ret = this[node.type](node);
|
||||
this.sourceNode.shift();
|
||||
return ret;
|
||||
},
|
||||
|
||||
Program: function(program) {
|
||||
var body = program.body;
|
||||
|
||||
for(var i=0, l=body.length; i<l; i++) {
|
||||
this.accept(body[i]);
|
||||
}
|
||||
@@ -144,22 +149,22 @@ Compiler.prototype = {
|
||||
|
||||
// now that the simple mustache is resolved, we need to
|
||||
// evaluate it by executing `blockHelperMissing`
|
||||
this.opcode('pushProgram', block, program);
|
||||
this.opcode('pushProgram', block, inverse);
|
||||
this.opcode('emptyHash', block);
|
||||
this.opcode('blockValue', block, sexpr.path.original);
|
||||
this.opcode('pushProgram', program);
|
||||
this.opcode('pushProgram', inverse);
|
||||
this.opcode('emptyHash');
|
||||
this.opcode('blockValue', sexpr.path.original);
|
||||
} else {
|
||||
this.ambiguousSexpr(sexpr, program, inverse);
|
||||
|
||||
// now that the simple mustache is resolved, we need to
|
||||
// evaluate it by executing `blockHelperMissing`
|
||||
this.opcode('pushProgram', block, program);
|
||||
this.opcode('pushProgram', block, inverse);
|
||||
this.opcode('emptyHash', block);
|
||||
this.opcode('ambiguousBlockValue', block);
|
||||
this.opcode('pushProgram', program);
|
||||
this.opcode('pushProgram', inverse);
|
||||
this.opcode('emptyHash');
|
||||
this.opcode('ambiguousBlockValue');
|
||||
}
|
||||
|
||||
this.opcode('append', block);
|
||||
this.opcode('append');
|
||||
},
|
||||
|
||||
PartialStatement: function(partial) {
|
||||
@@ -177,26 +182,26 @@ Compiler.prototype = {
|
||||
|
||||
var indent = partial.indent || '';
|
||||
if (this.options.preventIndent && indent) {
|
||||
this.opcode('appendContent', partial, indent);
|
||||
this.opcode('appendContent', indent);
|
||||
indent = '';
|
||||
}
|
||||
this.opcode('invokePartial', partial, partialName, indent);
|
||||
this.opcode('append', partial);
|
||||
this.opcode('invokePartial', partialName, indent);
|
||||
this.opcode('append');
|
||||
},
|
||||
|
||||
MustacheStatement: function(mustache) {
|
||||
this.accept(mustache.sexpr);
|
||||
|
||||
if(mustache.escaped && !this.options.noEscape) {
|
||||
this.opcode('appendEscaped', mustache);
|
||||
this.opcode('appendEscaped');
|
||||
} else {
|
||||
this.opcode('append', mustache);
|
||||
this.opcode('append');
|
||||
}
|
||||
},
|
||||
|
||||
ContentStatement: function(content) {
|
||||
if (content.value) {
|
||||
this.opcode('appendContent', content, content.value);
|
||||
this.opcode('appendContent', content.value);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -218,19 +223,19 @@ Compiler.prototype = {
|
||||
name = path.parts[0],
|
||||
isBlock = program != null || inverse != null;
|
||||
|
||||
this.opcode('getContext', sexpr, path.depth);
|
||||
this.opcode('getContext', path.depth);
|
||||
|
||||
this.opcode('pushProgram', sexpr, program);
|
||||
this.opcode('pushProgram', sexpr, inverse);
|
||||
this.opcode('pushProgram', program);
|
||||
this.opcode('pushProgram', inverse);
|
||||
|
||||
this.accept(path);
|
||||
|
||||
this.opcode('invokeAmbiguous', sexpr, name, isBlock);
|
||||
this.opcode('invokeAmbiguous', name, isBlock);
|
||||
},
|
||||
|
||||
simpleSexpr: function(sexpr) {
|
||||
this.accept(sexpr.path);
|
||||
this.opcode('resolvePossibleLambda', sexpr);
|
||||
this.opcode('resolvePossibleLambda');
|
||||
},
|
||||
|
||||
helperSexpr: function(sexpr, program, inverse) {
|
||||
@@ -239,62 +244,62 @@ Compiler.prototype = {
|
||||
name = path.parts[0];
|
||||
|
||||
if (this.options.knownHelpers[name]) {
|
||||
this.opcode('invokeKnownHelper', sexpr, params.length, name);
|
||||
this.opcode('invokeKnownHelper', params.length, name);
|
||||
} else if (this.options.knownHelpersOnly) {
|
||||
throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
|
||||
} else {
|
||||
path.falsy = true;
|
||||
|
||||
this.accept(path);
|
||||
this.opcode('invokeHelper', sexpr, params.length, path.original, simpleId(path));
|
||||
this.opcode('invokeHelper', params.length, path.original, simpleId(path));
|
||||
}
|
||||
},
|
||||
|
||||
PathExpression: function(path) {
|
||||
this.addDepth(path.depth);
|
||||
this.opcode('getContext', path, path.depth);
|
||||
this.opcode('getContext', path.depth);
|
||||
|
||||
var name = path.parts[0];
|
||||
if (!name) {
|
||||
// Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
|
||||
this.opcode('pushContext', path);
|
||||
this.opcode('pushContext');
|
||||
} else if (path.data) {
|
||||
this.options.data = true;
|
||||
this.opcode('lookupData', path, path.depth, path.parts);
|
||||
this.opcode('lookupData', path.depth, path.parts);
|
||||
} else {
|
||||
this.opcode('lookupOnContext', path, path.parts, path.falsy, scopedId(path));
|
||||
this.opcode('lookupOnContext', path.parts, path.falsy, scopedId(path));
|
||||
}
|
||||
},
|
||||
|
||||
StringLiteral: function(string) {
|
||||
this.opcode('pushString', string, string.value);
|
||||
this.opcode('pushString', string.value);
|
||||
},
|
||||
|
||||
NumberLiteral: function(number) {
|
||||
this.opcode('pushLiteral', number, number.value);
|
||||
this.opcode('pushLiteral', number.value);
|
||||
},
|
||||
|
||||
BooleanLiteral: function(bool) {
|
||||
this.opcode('pushLiteral', bool, bool.value);
|
||||
this.opcode('pushLiteral', bool.value);
|
||||
},
|
||||
|
||||
Hash: function(hash) {
|
||||
var pairs = hash.pairs, i, l;
|
||||
|
||||
this.opcode('pushHash', hash);
|
||||
this.opcode('pushHash');
|
||||
|
||||
for (i=0, l=pairs.length; i<l; i++) {
|
||||
this.pushParam(pairs[i].value);
|
||||
}
|
||||
while (i--) {
|
||||
this.opcode('assignToHash', hash, pairs[i].key);
|
||||
this.opcode('assignToHash', pairs[i].key);
|
||||
}
|
||||
this.opcode('popHash', hash);
|
||||
this.opcode('popHash');
|
||||
},
|
||||
|
||||
// HELPERS
|
||||
opcode: function(name, node) {
|
||||
this.opcodes.push({ opcode: name, args: slice.call(arguments, 2), loc: node.loc });
|
||||
opcode: function(name) {
|
||||
this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
|
||||
},
|
||||
|
||||
addDepth: function(depth) {
|
||||
@@ -359,8 +364,8 @@ Compiler.prototype = {
|
||||
if(val.depth) {
|
||||
this.addDepth(val.depth);
|
||||
}
|
||||
this.opcode('getContext', val, val.depth || 0);
|
||||
this.opcode('pushStringParam', val, value, val.type);
|
||||
this.opcode('getContext', val.depth || 0);
|
||||
this.opcode('pushStringParam', value, val.type);
|
||||
|
||||
if (val.type === 'SubExpression') {
|
||||
// SubExpressions get evaluated and passed in
|
||||
@@ -376,7 +381,7 @@ Compiler.prototype = {
|
||||
.replace(/^\.$/g, '');
|
||||
}
|
||||
|
||||
this.opcode('pushId', val, val.type, value);
|
||||
this.opcode('pushId', val.type, value);
|
||||
}
|
||||
this.accept(val);
|
||||
}
|
||||
@@ -386,13 +391,13 @@ Compiler.prototype = {
|
||||
var params = sexpr.params;
|
||||
this.pushParams(params);
|
||||
|
||||
this.opcode('pushProgram', sexpr, program);
|
||||
this.opcode('pushProgram', sexpr, inverse);
|
||||
this.opcode('pushProgram', program);
|
||||
this.opcode('pushProgram', inverse);
|
||||
|
||||
if (sexpr.hash) {
|
||||
this.accept(sexpr.hash);
|
||||
} else {
|
||||
this.opcode('emptyHash', sexpr, omitEmpty);
|
||||
this.opcode('emptyHash', omitEmpty);
|
||||
}
|
||||
|
||||
return params;
|
||||
|
||||
Reference in New Issue
Block a user