aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-02-04 21:16:45 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-02-04 21:16:45 -0800
commit3e7c8fb5e15ab6786da8cc72a802720e224271d1 (patch)
tree61d74e0bf30e00d82c588306745d3a339fdadf4d /src
parent1cb7cf18b704920eeead32b3ea681780c3aad05e (diff)
refactor out the 'assign' intertype, simplifying and optimizing the compiler
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js197
-rw-r--r--src/intertyper.js161
-rw-r--r--src/jsifier.js46
-rw-r--r--src/parseTools.js52
-rw-r--r--src/utility.js11
5 files changed, 181 insertions, 286 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index c5a8cea3..fcddb3cb 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -162,12 +162,9 @@ function analyzer(data, sidePass) {
if (item[slot].intertype == 'value') return i;
// TODO: unfold multiple slots at once
var tempIdent = '$$emscripten$temp$' + i;
- lines.splice(i, 0, {
- intertype: 'assign',
- ident: tempIdent,
- value: item[slot],
- lineNum: lines[i].lineNum - 0.5
- });
+ item[slot].assignTo = tempIdent;
+ item[slot].lineNum = lines[i].lineNum - 0.5;
+ lines.splice(i, 0, item[slot]);
item[slot] = { intertype: 'value', ident: tempIdent, type: item[slot].type };
return i+1;
}
@@ -188,18 +185,15 @@ function analyzer(data, sidePass) {
elements.forEach(function(element) {
var tempVar = '$st$' + i + '$' + j;
label.lines.splice(i+j*2, 0, {
- intertype: 'assign',
- ident: tempVar,
- value: {
- intertype: 'getelementptr',
- ident: item.pointer.ident,
- type: '[0 x i32]*',
- params: [
- { intertype: 'value', ident: item.pointer.ident, type: '[0 x i32]*' }, // technically a bitcase is needed in llvm, but not for us
- { intertype: 'value', ident: '0', type: 'i32' },
- { intertype: 'value', ident: j.toString(), type: 'i32' }
- ],
- },
+ intertype: 'getelementptr',
+ assignTo: tempVar,
+ ident: item.pointer.ident,
+ type: '[0 x i32]*',
+ params: [
+ { intertype: 'value', ident: item.pointer.ident, type: '[0 x i32]*' }, // technically a bitcase is needed in llvm, but not for us
+ { intertype: 'value', ident: '0', type: 'i32' },
+ { intertype: 'value', ident: j.toString(), type: 'i32' }
+ ],
lineNum: item.lineNum + (j/100)
});
var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
@@ -219,8 +213,8 @@ function analyzer(data, sidePass) {
i += j*2;
continue;
}
- } else if (item.intertype == 'assign') {
- var value = item.value;
+ } else if (item.assignTo) {
+ var value = item;
switch (value.intertype) {
case 'load': {
if (isIllegalType(value.valueType)) {
@@ -228,40 +222,33 @@ function analyzer(data, sidePass) {
i = unfold(label.lines, i, value, 'pointer');
label.lines.splice(i, 1);
bits = getBits(value.valueType);
-// assert(value.pointer.intertype == 'value', 'TODO: unfolding');
- var elements = getLegalVars(item.ident, bits);
+ var elements = getLegalVars(item.assignTo, bits);
var j = 0;
elements.forEach(function(element) {
var tempVar = '$st$' + i + '$' + j;
label.lines.splice(i+j*2, 0, {
- intertype: 'assign',
- ident: tempVar,
- value: {
- intertype: 'getelementptr',
- ident: value.pointer.ident,
- type: '[0 x i32]*',
- params: [
- { intertype: 'value', ident: value.pointer.ident, type: '[0 x i32]*' }, // technically bitcast is needed in llvm, but not for us
- { intertype: 'value', ident: '0', type: 'i32' },
- { intertype: 'value', ident: j.toString(), type: 'i32' }
- ],
- },
+ intertype: 'getelementptr',
+ assignTo: tempVar,
+ ident: value.pointer.ident,
+ type: '[0 x i32]*',
+ params: [
+ { intertype: 'value', ident: value.pointer.ident, type: '[0 x i32]*' }, // technically bitcast is needed in llvm, but not for us
+ { intertype: 'value', ident: '0', type: 'i32' },
+ { intertype: 'value', ident: j.toString(), type: 'i32' }
+ ],
lineNum: item.lineNum + (j/100)
});
var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
label.lines.splice(i+j*2+1, 0, {
- intertype: 'assign',
- ident: element.ident,
- value: {
- intertype: 'load',
- pointerType: actualSizeType + '*',
- valueType: actualSizeType,
- type: actualSizeType, // XXX why is this missing from intertyper?
- pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
- ident: tempVar,
- pointerType: actualSizeType + '*',
- align: value.align,
- },
+ intertype: 'load',
+ assignTo: element.ident,
+ pointerType: actualSizeType + '*',
+ valueType: actualSizeType,
+ type: actualSizeType, // XXX why is this missing from intertyper?
+ pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
+ ident: tempVar,
+ pointerType: actualSizeType + '*',
+ align: value.align,
lineNum: item.lineNum + ((j+0.5)/100)
});
j++;
@@ -337,7 +324,7 @@ function analyzer(data, sidePass) {
}
// Do the legalization
assert(isNumber(shifts), 'TODO: handle nonconstant shifts');
- var targetElements = getLegalVars(item.ident, targetBits);
+ var targetElements = getLegalVars(item.assignTo, targetBits);
var sign = shifts >= 0 ? 1 : -1;
var shiftOp = shifts >= 0 ? 'shl' : 'lshr';
var shiftOpReverse = shifts >= 0 ? 'lshr' : 'shl';
@@ -390,12 +377,9 @@ function analyzer(data, sidePass) {
if (processor) {
result = processor(result, j);
}
- toAdd.push({
- intertype: 'assign',
- ident: targetElements[j].ident,
- value: result,
- lineNum: item.lineNum + (j/100)
- });
+ result.assignTo = targetElements[j].ident;
+ result.lineNum = item.lineNum + (j/100);
+ toAdd.push(result);
}
if (targetBits <= 64) {
// We are generating a normal legal type here
@@ -417,12 +401,9 @@ function analyzer(data, sidePass) {
} else {
throw 'Invalid legal type as target of legalization ' + targetBits;
}
- toAdd.push({
- intertype: 'assign',
- ident: item.ident,
- value: legalValue,
- lineNum: item.lineNum + ((j+1)/100)
- });
+ legalValue.assignTo = item.assignTo;
+ legalValue.lineNum = item.lineNum + ((j+1)/100);
+ toAdd.push(legalValue);
}
Array.prototype.splice.apply(label.lines, [i, 0].concat(toAdd));
i += toAdd.length;
@@ -639,16 +620,16 @@ function analyzer(data, sidePass) {
// Normal variables
func.lines.forEach(function(item, i) {
- if (item.intertype === 'assign') {
- var variable = func.variables[item.ident] = {
- ident: item.ident,
- type: item.value.type,
- origin: item.value.intertype,
+ if (item.assignTo) {
+ var variable = func.variables[item.assignTo] = {
+ ident: item.assignTo,
+ type: item.type,
+ origin: item.intertype,
lineNum: item.lineNum,
rawLinesIndex: i
};
if (variable.origin === 'alloca') {
- variable.allocatedNum = item.value.allocatedNum;
+ variable.allocatedNum = item.allocatedNum;
}
}
});
@@ -657,19 +638,19 @@ function analyzer(data, sidePass) {
// Second pass over variables - notice when types are crossed by bitcast
func.lines.forEach(function(item) {
- if (item.intertype === 'assign' && item.value.intertype === 'bitcast') {
+ if (item.assignTo && item.intertype === 'bitcast') {
// bitcasts are unique in that they convert one pointer to another. We
// sometimes need to know the original type of a pointer, so we save that.
//
// originalType is the type this variable is created from
// derivedTypes are the types that this variable is cast into
- func.variables[item.ident].originalType = item.value.type2;
+ func.variables[item.assignTo].originalType = item.type2;
- if (!isNumber(item.value.ident)) {
- if (!func.variables[item.value.ident].derivedTypes) {
- func.variables[item.value.ident].derivedTypes = [];
+ if (!isNumber(item.assignTo)) {
+ if (!func.variables[item.assignTo].derivedTypes) {
+ func.variables[item.assignTo].derivedTypes = [];
}
- func.variables[item.value.ident].derivedTypes.push(item.value.type);
+ func.variables[item.assignTo].derivedTypes.push(item.type);
}
}
});
@@ -699,7 +680,7 @@ function analyzer(data, sidePass) {
walkInterdata(line, function(item) {
if (item.intertype == 'noop') inNoop++;
if (!inNoop) {
- if (item.ident in func.variables && item.intertype != 'assign') {
+ if (item.ident in func.variables) {
func.variables[item.ident].uses++;
if (item.intertype != 'load' && item.intertype != 'store') {
@@ -711,6 +692,8 @@ function analyzer(data, sidePass) {
if (item.intertype == 'noop') inNoop--;
});
});
+
+ //if (dcheck('vars')) dprint('analyzed variables: ' + dump(func.variables));
}
// Filter out no longer used variables, collapsing more as we go
@@ -724,12 +707,14 @@ function analyzer(data, sidePass) {
if (variable.uses == 0 && variable.origin != 'funcparam') {
// Eliminate this variable if we can
var sideEffects = false;
- walkInterdata(func.lines[variable.rawLinesIndex].value, function(item) {
+ walkInterdata(func.lines[variable.rawLinesIndex], function(item) {
if (item.intertype in SIDE_EFFECT_CAUSERS) sideEffects = true;
});
if (!sideEffects) {
dprint('vars', 'Eliminating ' + vname);
- func.lines[variable.rawLinesIndex].intertype = func.lines[variable.rawLinesIndex].value.intertype = 'noop';
+ func.lines[variable.rawLinesIndex].intertype = 'noop';
+ func.lines[variable.rawLinesIndex].assignTo = null;
+ // in theory we can also null out some fields here to save memory
delete func.variables[vname];
recalc = true;
}
@@ -806,22 +791,22 @@ function analyzer(data, sidePass) {
item.functions.forEach(function(func) {
func.lines.forEach(function(line, i) {
- if (line.intertype === 'assign' && line.value.intertype === 'load') {
+ if (line.intertype === 'load') {
// Floats have no concept of signedness. Mark them as 'signed', which is the default, for which we do nothing
- if (line.value.type in Runtime.FLOAT_TYPES) {
- line.value.unsigned = false;
+ if (line.type in Runtime.FLOAT_TYPES) {
+ line.unsigned = false;
return;
}
// Booleans are always unsigned
- var data = func.variables[line.ident];
+ var data = func.variables[line.assignTo];
if (data.type === 'i1') {
- line.value.unsigned = true;
+ line.unsigned = true;
return;
}
var total = data.uses;
if (total === 0) return;
- var obj = { ident: line.ident, found: 0, unsigned: 0, signed: 0, total: total };
+ var obj = { ident: line.assignTo, found: 0, unsigned: 0, signed: 0, total: total };
// in loops with phis, we can also be used *before* we are defined
var j = i-1, k = i+1;
while(1) {
@@ -840,8 +825,8 @@ function analyzer(data, sidePass) {
// we also leave the loop above potentially early due to this. otherwise, though, we end up scanning the
// entire function in some cases which is very slow
assert(obj.found >= obj.total, 'Could not Signalyze line ' + line.lineNum);
- line.value.unsigned = obj.unsigned > 0;
- dprint('vars', 'Signalyzer: ' + line.ident + ' has unsigned == ' + line.value.unsigned + ' (line ' + line.lineNum + ')');
+ line.unsigned = obj.unsigned > 0;
+ dprint('vars', 'Signalyzer: ' + line.assignTo + ' has unsigned == ' + line.unsigned + ' (line ' + line.lineNum + ')');
}
});
});
@@ -1035,18 +1020,17 @@ function analyzer(data, sidePass) {
// we need __lastLabel__.
func.needsLastLabel = false;
func.labels.forEach(function(label) {
- var phis = [], phi;
- label.lines.forEach(function(line) {
- if ((phi = line.value) && phi.intertype == 'phi') {
+ var phis = [];
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
for (var i = 0; i < phi.params.length; i++) {
var sourceLabelId = getActualLabelId(phi.params[i].label);
var sourceLabel = func.labelsDict[sourceLabelId];
var lastLine = sourceLabel.lines.slice(-1)[0];
- if (lastLine.intertype == 'assign') lastLine = lastLine.value;
assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]);
lastLine.currLabelId = sourceLabelId;
}
- phis.push(line);
+ phis.push(phi);
func.needsLastLabel = true;
}
});
@@ -1055,12 +1039,12 @@ function analyzer(data, sidePass) {
// Multiple phis have the semantics that they all occur 'in parallel', i.e., changes to
// a variable that is the result of a phi should *not* affect the other results. We must
// therefore be careful!
- phis[phis.length-1].value.postSet = '; /* post-phi: */';
+ phis[phis.length-1].postSet = '; /* post-phi: */';
for (var i = 0; i < phis.length-1; i++) {
- var ident = phis[i].ident;
+ var ident = phis[i].assignTo;
var phid = ident+'$phi'
- phis[phis.length-1].value.postSet += ident + '=' + phid + ';';
- phis[i].ident = phid;
+ phis[phis.length-1].postSet += ident + '=' + phid + ';';
+ phis[i].assignTo = phid;
func.variables[phid] = {
ident: phid,
type: func.variables[ident].type,
@@ -1078,15 +1062,13 @@ function analyzer(data, sidePass) {
// First, push phis back
func.labels.forEach(function(label) {
- label.lines.forEach(function(line) {
- var phi;
- if ((phi = line.value) && phi.intertype == 'phi') {
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
for (var i = 0; i < phi.params.length; i++) {
var param = phi.params[i];
var sourceLabelId = getActualLabelId(param.label);
var sourceLabel = func.labelsDict[sourceLabelId];
var lastLine = sourceLabel.lines.slice(-1)[0];
- if (lastLine.intertype == 'assign') lastLine = lastLine.value;
assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]);
if (!lastLine.phi) {
lastLine.phi = true;
@@ -1098,14 +1080,15 @@ function analyzer(data, sidePass) {
};
lastLine.dependent.params.push({
intertype: 'phiassign',
- ident: line.ident,
+ ident: phi.assignTo,
value: param.value,
targetLabel: label.ident
});
}
// The assign to phi is now just a var
- line.intertype = 'var';
- line.value = null;
+ phi.intertype = 'var';
+ phi.ident = phi.assignTo;
+ phi.assignTo = null;
}
});
});
@@ -1121,11 +1104,10 @@ function analyzer(data, sidePass) {
data.functions.forEach(function(func) {
var lines = func.labels[0].lines;
for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
- var item = line.value;
- if (!item || item.intertype != 'alloca') break;
+ var item = lines[i];
+ if (!item.assignTo || item.intertype != 'alloca') break;
assert(isNumber(item.allocatedNum));
- item.allocatedSize = func.variables[line.ident].impl === VAR_EMULATED ?
+ item.allocatedSize = func.variables[item.assignTo].impl === VAR_EMULATED ?
calcAllocatedSize(item.allocatedType)*item.allocatedNum: 0;
if (USE_TYPED_ARRAYS === 2) {
// We need to keep the stack aligned
@@ -1134,8 +1116,8 @@ function analyzer(data, sidePass) {
}
var index = 0;
for (var i = 0; i < lines.length; i++) {
- var item = lines[i].value;
- if (!item || item.intertype != 'alloca') break;
+ var item = lines[i];
+ if (!item.assignTo || item.intertype != 'alloca') break;
item.allocatedIndex = index;
index += item.allocatedSize;
delete item.allocatedSize;
@@ -1159,8 +1141,8 @@ function analyzer(data, sidePass) {
// Allocas
var finishedInitial = false;
for (var i = 0; i < lines.length; i++) {
- var item = lines[i].value;
- if (!item || item.intertype != 'alloca') {
+ var item = lines[i];
+ if (!item.assignTo || item.intertype != 'alloca') {
finishedInitial = true;
continue;
}
@@ -1174,7 +1156,6 @@ function analyzer(data, sidePass) {
// Varargs
for (var i = 0; i < lines.length; i++) {
var item = lines[i];
- if (item.value) item = item.value;
if (item.intertype == 'call' && isVarArgsFunctionType(item.type)) {
func.otherStackAllocations = true;
break;
@@ -1199,8 +1180,6 @@ function analyzer(data, sidePass) {
}
if (line.intertype in BRANCH_INVOKE) {
process(line);
- } else if (line.intertype == 'assign' && line.value.intertype == 'invoke') {
- process(line.value);
} else if (line.intertype == 'switch') {
process(line);
line.switchLabels.forEach(process);
diff --git a/src/intertyper.js b/src/intertyper.js
index 341598fc..6148e824 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -295,81 +295,78 @@ function intertyper(data, sidePass, baseLineNums) {
substrate.addActor('Triager', {
processItem: function _triager(item) {
function triage() {
- if (!item.intertype) {
- var token0Text = item.tokens[0].text;
- var token1Text = item.tokens[1] ? item.tokens[1].text : null;
- var tokensLength = item.tokens.length;
- if (item.indent === 2) {
- if (tokensLength >= 5 &&
- (token0Text == 'store' || token1Text == 'store'))
- return 'Store';
- if (tokensLength >= 3 && findTokenText(item, '=') >= 0)
- return 'Assign';
- if (tokensLength >= 3 && token0Text == 'br')
- return 'Branch';
- if (tokensLength >= 2 && token0Text == 'ret')
- return 'Return';
- if (tokensLength >= 2 && token0Text == 'switch')
- return 'Switch';
- if (token0Text == 'unreachable')
- return 'Unreachable';
- if (tokensLength >= 3 && token0Text == 'indirectbr')
- return 'IndirectBr';
- if (tokensLength >= 2 && token0Text == 'resume')
- return 'Resume';
- } else if (item.indent === -1) {
- if (tokensLength >= 3 &&
- (token0Text == 'load' || token1Text == 'load'))
- return 'Load';
- if (tokensLength >= 3 &&
- token0Text in MATHOPS)
- return 'Mathops';
- if (tokensLength >= 3 && token0Text == 'bitcast')
- return 'Bitcast';
- if (tokensLength >= 3 && token0Text == 'getelementptr')
- return 'GEP';
- if (tokensLength >= 2 && token0Text == 'alloca')
- return 'Alloca';
- if (tokensLength >= 3 && token0Text == 'extractvalue')
- return 'ExtractValue';
- if (tokensLength >= 3 && token0Text == 'insertvalue')
- return 'InsertValue';
- if (tokensLength >= 3 && token0Text == 'phi')
- return 'Phi';
- if (tokensLength >= 3 && token0Text == 'landingpad')
- return 'Landingpad';
- } else if (item.indent === 0) {
- if ((tokensLength >= 1 && token0Text.substr(-1) == ':') ||
- (tokensLength >= 3 && token1Text == '<label>'))
- return 'Label';
- if (tokensLength >= 4 && token0Text == 'declare')
- return 'External';
- if (tokensLength >= 3 && token1Text == '=')
- return 'Global';
- if (tokensLength >= 4 && token0Text == 'define' &&
- item.tokens.slice(-1)[0].text == '{')
- return 'FuncHeader';
- if (tokensLength >= 1 && token0Text == '}')
- return 'FuncEnd';
- }
- if (tokensLength >= 3 && (token0Text == 'call' || token1Text == 'call'))
- return 'Call';
- if (token0Text == 'target')
- return '/dev/null';
- if (token0Text == ';')
- return '/dev/null';
- if (tokensLength >= 3 && token0Text == 'invoke')
- return 'Invoke';
- if (tokensLength >= 3 && token0Text == 'atomicrmw' || token0Text == 'cmpxchg')
- return 'Atomic';
- } else {
- // Already intertyped
- if (item.parentSlot)
- return 'Reintegrator';
+ assert(!item.intertype);
+ var token0Text = item.tokens[0].text;
+ var token1Text = item.tokens[1] ? item.tokens[1].text : null;
+ var tokensLength = item.tokens.length;
+ if (item.indent === 2) {
+ if (tokensLength >= 5 &&
+ (token0Text == 'store' || token1Text == 'store'))
+ return 'Store';
+ if (tokensLength >= 3 && token0Text == 'br')
+ return 'Branch';
+ if (tokensLength >= 2 && token0Text == 'ret')
+ return 'Return';
+ if (tokensLength >= 2 && token0Text == 'switch')
+ return 'Switch';
+ if (token0Text == 'unreachable')
+ return 'Unreachable';
+ if (tokensLength >= 3 && token0Text == 'indirectbr')
+ return 'IndirectBr';
+ if (tokensLength >= 2 && token0Text == 'resume')
+ return 'Resume';
+ if (tokensLength >= 3 &&
+ (token0Text == 'load' || token1Text == 'load'))
+ return 'Load';
+ if (tokensLength >= 3 &&
+ token0Text in MATHOPS)
+ return 'Mathops';
+ if (tokensLength >= 3 && token0Text == 'bitcast')
+ return 'Bitcast';
+ if (tokensLength >= 3 && token0Text == 'getelementptr')
+ return 'GEP';
+ if (tokensLength >= 2 && token0Text == 'alloca')
+ return 'Alloca';
+ if (tokensLength >= 3 && token0Text == 'extractvalue')
+ return 'ExtractValue';
+ if (tokensLength >= 3 && token0Text == 'insertvalue')
+ return 'InsertValue';
+ if (tokensLength >= 3 && token0Text == 'phi')
+ return 'Phi';
+ if (tokensLength >= 3 && token0Text == 'landingpad')
+ return 'Landingpad';
+ } else if (item.indent === 0) {
+ if ((tokensLength >= 1 && token0Text.substr(-1) == ':') ||
+ (tokensLength >= 3 && token1Text == '<label>'))
+ return 'Label';
+ if (tokensLength >= 4 && token0Text == 'declare')
+ return 'External';
+ if (tokensLength >= 3 && token1Text == '=')
+ return 'Global';
+ if (tokensLength >= 4 && token0Text == 'define' &&
+ item.tokens.slice(-1)[0].text == '{')
+ return 'FuncHeader';
+ if (tokensLength >= 1 && token0Text == '}')
+ return 'FuncEnd';
}
+ if (tokensLength >= 3 && (token0Text == 'call' || token1Text == 'call'))
+ return 'Call';
+ if (token0Text == 'target')
+ return '/dev/null';
+ if (token0Text == ';')
+ return '/dev/null';
+ if (tokensLength >= 3 && token0Text == 'invoke')
+ return 'Invoke';
+ if (tokensLength >= 3 && token0Text == 'atomicrmw' || token0Text == 'cmpxchg')
+ return 'Atomic';
throw 'Invalid token, cannot triage: ' + dump(item);
}
- this.forwardItem(item, triage(item));
+ var eq;
+ if (item.indent == 2 && (eq = findTokenText(item, '=')) >= 0) {
+ item.assignTo = toNiceIdent(combineTokens(item.tokens.slice(0, eq)).text);
+ item.tokens = item.tokens.slice(eq+1);
+ }
+ this.forwardItem(item, triage());
}
});
@@ -564,27 +561,13 @@ function intertyper(data, sidePass, baseLineNums) {
}
});
- // assignment
- substrate.addActor('Assign', {
+ // TODO: remove dis
+ substrate.addActor('Reintegrator', {
processItem: function(item) {
- var opIndex = findTokenText(item, '=');
- var commentIndex = getTokenIndexByText(item.tokens, ';');
- var pair = splitItem({
- intertype: 'assign',
- ident: toNiceIdent(combineTokens(item.tokens.slice(0, opIndex)).text),
- lineNum: item.lineNum,
- }, 'value');
- this.forwardItem(pair.parent, 'Reintegrator');
- pair.child.indent = -1;
- pair.child.tokens = item.tokens.slice(opIndex+1);
- this.forwardItem(pair.child, 'Triager');
+ this.forwardItem(item, '/dev/stdout');
}
});
- substrate.addActor('Reintegrator', makeReintegrator(function(parent, child) {
- this.forwardItem(parent, '/dev/stdout');
- }));
-
// 'load'
substrate.addActor('Load', {
processItem: function(item) {
diff --git a/src/jsifier.js b/src/jsifier.js
index e66f7b69..71533309 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -658,36 +658,25 @@ function JSify(data, functionsOnly, givenFunctions) {
substrate.addActor('FuncLineTriager', {
processItem: function(item) {
if (item.intertype == 'function') {
- this.forwardItem(item, 'FunctionReconstructor');
+ this.forwardItem(item, 'FunctionReconstructor'); // XXX not really needed
} else if (item.JS) {
- if (item.parentLineNum) {
- this.forwardItem(item, 'AssignReintegrator');
- } else {
- this.forwardItem(item, 'FunctionReconstructor');
- }
+ this.forwardItem(item, 'FunctionReconstructor'); // XXX not really needed
} else {
this.forwardItem(item, 'Intertype:' + item.intertype);
}
}
});
- // assignment
- substrate.addActor('Intertype:assign', {
- processItem: function(item) {
- var pair = splitItem(item, 'value', ['funcData']);
- this.forwardItem(pair.parent, 'AssignReintegrator');
- this.forwardItem(pair.child, 'FuncLineTriager');
- }
- });
- substrate.addActor('AssignReintegrator', makeReintegrator(function(item, child) {
- // 'var', since this is SSA - first assignment is the only assignment, and where it is defined
+ // An interitem that has |assignTo| is an assign to that item. They call this function which
+ // generates the actual assignment.
+ function makeAssign(item) {
+ var valueJS = item.JS;
item.JS = '';
if (CLOSURE_ANNOTATIONS) item.JS += '/** @type {number} */ ';
- item.JS += (item.overrideSSA ? '' : 'var ') + toNiceIdent(item.ident);
+ item.JS += (item.overrideSSA ? '' : 'var ') + toNiceIdent(item.assignTo);
- var type = item.value.type;
- var value = parseNumerical(item.value.JS);
- var impl = getVarImpl(item.funcData, item.ident);
+ var value = parseNumerical(valueJS);
+ var impl = getVarImpl(item.funcData, item.assignTo);
switch (impl) {
case VAR_NATIVE: {
break;
@@ -702,12 +691,13 @@ function JSify(data, functionsOnly, givenFunctions) {
}
default: throw 'zz unknown impl: ' + impl;
}
- if (value)
+ if (value && value != ';') {
item.JS += '=' + value;
- item.JS += ';';
-
- this.forwardItem(item, 'FunctionReconstructor');
- }));
+ }
+ if (item.JS[item.JS.length-1] != ';') {
+ item.JS += ';';
+ }
+ }
// Function lines
function makeFuncLineActor(intertype, func) {
@@ -715,7 +705,11 @@ function JSify(data, functionsOnly, givenFunctions) {
processItem: function(item) {
item.JS = func(item);
if (!item.JS) throw "No JS generated for " + dump(item);
- this.forwardItem(item, 'FuncLineTriager');
+ if (item.assignTo) {
+ makeAssign(item);
+ if (!item.JS) throw "No assign JS generated for " + dump(item);
+ }
+ this.forwardItem(item, 'FunctionReconstructor');
}
});
}
diff --git a/src/parseTools.js b/src/parseTools.js
index b68365a1..e58dad6a 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -254,58 +254,6 @@ function splitTokenList(tokens) {
return ret;
}
-// Splits an item, with the intent of later reintegration
-function splitItem(parent, childSlot, copySlots) {
- if (!copySlots) copySlots = [];
- if (!parent[childSlot]) parent[childSlot] = {};
- var child = parent[childSlot];
- parent[childSlot] = null;
- child.parentUid = parent.__uid__;
- child.parentSlot = childSlot;
- child.parentLineNum = child.lineNum = parent.lineNum;
- copySlots.forEach(function(slot) { child[slot] = parent[slot] });
- return {
- parent: parent,
- child: child
- };
-}
-
-function makeReintegrator(afterFunc) {
- // Reintegration - find intermediate representation-parsed items and
- // place back in parents
- return {
- process: function(items) {
- var ret = [];
- var lineDict = {};
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (!item.parentSlot) {
- assert(!lineDict[item.lineNum]);
- lineDict[item.lineNum] = i;
- }
- }
- for (var i = 0; i < items.length; i++) {
- var child = items[i];
- if (!child) continue; // it might have been removed by a previous pass
- var j = lineDict[child.parentLineNum];
- if (typeof j === 'number') {
- var parent = items[j];
- // process the pair
- parent[child.parentSlot] = child;
- delete child.parentLineNum;
- afterFunc.call(this, parent, child);
-
- items[i] = null;
- items[j] = null;
- lineDict[child.parentLineNum] = null;
- }
- }
- this.forwardItems(items.filter(function(item) { return !!item }), this.name_); // next time hopefully
- return ret;
- }
- };
-}
-
function parseParamTokens(params) {
if (params.length === 0) return [];
var ret = [];
diff --git a/src/utility.js b/src/utility.js
index 5c934483..4ffe46a0 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -9,17 +9,8 @@ function safeQuote(x) {
}
function dump(item) {
- var CHUNK = 500;
- function lineify(text) {
- var ret = '';
- while (text.length > 80) {
- ret += '// ' + text.substr(0,80) + '\n';
- text = text.substr(80);
- }
- return ret + '// ' + text;
- }
try {
- return lineify(JSON.stringify(item).substr(0, 80*25));
+ return '// ' + JSON.stringify(item, null, ' ').replace(/\n/g, '\n// ');
} catch(e) {
var ret = [];
for (var i in item) {