Include location information in all opcodes

This commit is contained in:
kpdecker
2014-11-06 09:44:38 -06:00
parent ea6b0be910
commit 249f559104
2 changed files with 50 additions and 45 deletions
+49 -45
View File
@@ -130,36 +130,36 @@ Compiler.prototype = {
// now that the simple mustache is resolved, we need to // now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing` // evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program); this.opcode('pushProgram', block, program);
this.opcode('pushProgram', inverse); this.opcode('pushProgram', block, inverse);
this.opcode('emptyHash'); this.opcode('emptyHash', block);
this.opcode('blockValue', sexpr.id.original); this.opcode('blockValue', block, sexpr.id.original);
} else { } else {
this.ambiguousSexpr(sexpr, program, inverse); this.ambiguousSexpr(sexpr, program, inverse);
// now that the simple mustache is resolved, we need to // now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing` // evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program); this.opcode('pushProgram', block, program);
this.opcode('pushProgram', inverse); this.opcode('pushProgram', block, inverse);
this.opcode('emptyHash'); this.opcode('emptyHash', block);
this.opcode('ambiguousBlockValue'); this.opcode('ambiguousBlockValue', block);
} }
this.opcode('append'); this.opcode('append', block);
}, },
hash: function(hash) { hash: function(hash) {
var pairs = hash.pairs, i, l; var pairs = hash.pairs, i, l;
this.opcode('pushHash'); this.opcode('pushHash', hash);
for(i=0, l=pairs.length; i<l; i++) { for(i=0, l=pairs.length; i<l; i++) {
this.pushParam(pairs[i][1]); this.pushParam(pairs[i][1]);
} }
while(i--) { while(i--) {
this.opcode('assignToHash', pairs[i][0]); this.opcode('assignToHash', hash, pairs[i][0]);
} }
this.opcode('popHash'); this.opcode('popHash', hash);
}, },
partial: function(partial) { partial: function(partial) {
@@ -169,28 +169,28 @@ Compiler.prototype = {
if (partial.hash) { if (partial.hash) {
this.accept(partial.hash); this.accept(partial.hash);
} else { } else {
this.opcode('push', 'undefined'); this.opcode('pushLiteral', partial, 'undefined');
} }
if (partial.context) { if (partial.context) {
this.accept(partial.context); this.accept(partial.context);
} else { } else {
this.opcode('getContext', 0); this.opcode('getContext', partial, 0);
this.opcode('pushContext'); this.opcode('pushContext', partial);
} }
var indent = partial.indent || ''; var indent = partial.indent || '';
if (this.options.preventIndent && indent) { if (this.options.preventIndent && indent) {
this.opcode('appendContent', indent); this.opcode('appendContent', partial, indent);
indent = ''; indent = '';
} }
this.opcode('invokePartial', partialName.name, indent); this.opcode('invokePartial', partial, partialName.name, indent);
this.opcode('append'); this.opcode('append', partial);
}, },
content: function(content) { content: function(content) {
if (content.string) { if (content.string) {
this.opcode('appendContent', content.string); this.opcode('appendContent', content, content.string);
} }
}, },
@@ -198,9 +198,9 @@ Compiler.prototype = {
this.sexpr(mustache.sexpr); this.sexpr(mustache.sexpr);
if(mustache.escaped && !this.options.noEscape) { if(mustache.escaped && !this.options.noEscape) {
this.opcode('appendEscaped'); this.opcode('appendEscaped', mustache);
} else { } else {
this.opcode('append'); this.opcode('append', mustache);
} }
}, },
@@ -209,14 +209,14 @@ Compiler.prototype = {
name = id.parts[0], name = id.parts[0],
isBlock = program != null || inverse != null; isBlock = program != null || inverse != null;
this.opcode('getContext', id.depth); this.opcode('getContext', sexpr, id.depth);
this.opcode('pushProgram', program); this.opcode('pushProgram', sexpr, program);
this.opcode('pushProgram', inverse); this.opcode('pushProgram', sexpr, inverse);
this.ID(id); this.ID(id);
this.opcode('invokeAmbiguous', name, isBlock); this.opcode('invokeAmbiguous', sexpr, name, isBlock);
}, },
simpleSexpr: function(sexpr) { simpleSexpr: function(sexpr) {
@@ -229,11 +229,11 @@ Compiler.prototype = {
} else { } else {
// Simplified ID for `this` // Simplified ID for `this`
this.addDepth(id.depth); this.addDepth(id.depth);
this.opcode('getContext', id.depth); this.opcode('getContext', sexpr, id.depth);
this.opcode('pushContext'); this.opcode('pushContext', sexpr);
} }
this.opcode('resolvePossibleLambda'); this.opcode('resolvePossibleLambda', sexpr);
}, },
helperSexpr: function(sexpr, program, inverse) { helperSexpr: function(sexpr, program, inverse) {
@@ -242,14 +242,14 @@ Compiler.prototype = {
name = id.parts[0]; name = id.parts[0];
if (this.options.knownHelpers[name]) { if (this.options.knownHelpers[name]) {
this.opcode('invokeKnownHelper', params.length, name); this.opcode('invokeKnownHelper', sexpr, params.length, name);
} else if (this.options.knownHelpersOnly) { } else if (this.options.knownHelpersOnly) {
throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr); throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
} else { } else {
id.falsy = true; id.falsy = true;
this.ID(id); this.ID(id);
this.opcode('invokeHelper', params.length, id.original, id.isSimple); this.opcode('invokeHelper', sexpr, params.length, id.original, id.isSimple);
} }
}, },
@@ -267,39 +267,43 @@ Compiler.prototype = {
ID: function(id) { ID: function(id) {
this.addDepth(id.depth); this.addDepth(id.depth);
this.opcode('getContext', id.depth); this.opcode('getContext', id, id.depth);
var name = id.parts[0]; var name = id.parts[0];
if (!name) { if (!name) {
// Context reference, i.e. `{{foo .}}` or `{{foo ..}}` // Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
this.opcode('pushContext'); this.opcode('pushContext', id);
} else { } else {
this.opcode('lookupOnContext', id.parts, id.falsy, id.isScoped); this.opcode('lookupOnContext', id, id.parts, id.falsy, id.isScoped);
} }
}, },
DATA: function(data) { DATA: function(data) {
this.options.data = true; this.options.data = true;
this.opcode('lookupData', data.id.depth, data.id.parts); this.opcode('lookupData', data, data.id.depth, data.id.parts);
}, },
STRING: function(string) { STRING: function(string) {
this.opcode('pushString', string.string); this.opcode('pushString', string, string.string);
}, },
NUMBER: function(number) { NUMBER: function(number) {
this.opcode('pushLiteral', number.number); this.opcode('pushLiteral', number, number.number);
}, },
BOOLEAN: function(bool) { BOOLEAN: function(bool) {
this.opcode('pushLiteral', bool.bool); this.opcode('pushLiteral', bool, bool.bool);
}, },
comment: function() {}, comment: function() {},
// HELPERS // HELPERS
opcode: function(name) { opcode: function(name, node) {
this.opcodes.push({ opcode: name, args: slice.call(arguments, 1) }); var loc = {
firstLine: node.firstLine, firstColumn: node.firstColumn,
lastLine: node.lastLine, lastColumn: node.lastColumn
};
this.opcodes.push({ opcode: name, args: slice.call(arguments, 2), loc: loc });
}, },
addDepth: function(depth) { addDepth: function(depth) {
@@ -344,8 +348,8 @@ Compiler.prototype = {
if(val.depth) { if(val.depth) {
this.addDepth(val.depth); this.addDepth(val.depth);
} }
this.opcode('getContext', val.depth || 0); this.opcode('getContext', val, val.depth || 0);
this.opcode('pushStringParam', val.stringModeValue, val.type); this.opcode('pushStringParam', val, val.stringModeValue, val.type);
if (val.type === 'sexpr') { if (val.type === 'sexpr') {
// Subexpressions get evaluated and passed in // Subexpressions get evaluated and passed in
@@ -354,7 +358,7 @@ Compiler.prototype = {
} }
} else { } else {
if (this.trackIds) { if (this.trackIds) {
this.opcode('pushId', val.type, val.idName || val.stringModeValue); this.opcode('pushId', val, val.type, val.idName || val.stringModeValue);
} }
this.accept(val); this.accept(val);
} }
@@ -364,13 +368,13 @@ Compiler.prototype = {
var params = sexpr.params; var params = sexpr.params;
this.pushParams(params); this.pushParams(params);
this.opcode('pushProgram', program); this.opcode('pushProgram', sexpr, program);
this.opcode('pushProgram', inverse); this.opcode('pushProgram', sexpr, inverse);
if (sexpr.hash) { if (sexpr.hash) {
this.hash(sexpr.hash); this.hash(sexpr.hash);
} else { } else {
this.opcode('emptyHash'); this.opcode('emptyHash', sexpr);
} }
return params; return params;
@@ -84,6 +84,7 @@ JavaScriptCompiler.prototype = {
for (i = 0, l = opcodes.length; i < l; i++) { for (i = 0, l = opcodes.length; i < l; i++) {
opcode = opcodes[i]; opcode = opcodes[i];
this.currentLoc = opcode.loc;
this[opcode.opcode].apply(this, opcode.args); this[opcode.opcode].apply(this, opcode.args);
} }