diff options
-rw-r--r-- | src/analyzer.js | 197 | ||||
-rw-r--r-- | src/intertyper.js | 161 | ||||
-rw-r--r-- | src/jsifier.js | 46 | ||||
-rw-r--r-- | src/parseTools.js | 52 | ||||
-rw-r--r-- | src/utility.js | 11 |
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) { |