aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@mozilla.com>2010-12-25 12:28:30 -0800
committerAlon Zakai <azakai@mozilla.com>2010-12-25 12:28:30 -0800
commit8e5c52df194f951187e897e5213849828e41b490 (patch)
tree4f42c35f387cf5553893fa8db58299330bf582bd /src
parent7985433ea6d2beb324f8ae7cd653407376955555 (diff)
code cleanup
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js37
-rw-r--r--src/compiler.js3
-rw-r--r--src/framework.js3
-rw-r--r--src/intertyper.js25
-rw-r--r--src/jsifier.js46
-rw-r--r--src/parseTools.js4
-rw-r--r--src/utility.js48
7 files changed, 67 insertions, 99 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 4aad192b..8f4ba95e 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -124,7 +124,7 @@ function analyzer(data, givenTypes) {
if (['['].indexOf(type) != -1) return;
data.types[type] = {
name_: type,
- fields: [ 'i32' ], // XXX
+ fields: [ 'i' + (QUANTUM_SIZE*8) ], // a single quantum size
flatSize: 1,
lineNum: '?'
};
@@ -245,7 +245,7 @@ function analyzer(data, givenTypes) {
func.variables[item.ident] = {
ident: item.ident,
type: item.value.type,
- origin: item.value.intertype, // XXX should say something in the case of fastgetelementptrload
+ origin: item.intertype === 'assign' ? item.value.intertype : 'fastgetelementptrload',
lineNum: item.lineNum,
uses: parseInt(item.value.tokens.slice(-1)[0].item.tokens[0].text.split('=')[1])
};
@@ -292,8 +292,8 @@ function analyzer(data, givenTypes) {
var pointedType = removePointing(variable.type);
if (variable.origin == 'getelementptr') {
// Use our implementation that emulates pointers etc.
- // XXX Can we perhaps nativize some of these? However to do so, we need to discover their
- // true types; we have '?' for them now, as they cannot be discovered in the intertyper.
+ // TODO Can we perhaps nativize some of these? However to do so, we need to discover their
+ // true types; we have '?' for them now, as they cannot be discovered in the intertyper.
variable.impl = VAR_EMULATED;
} else if (variable.origin == 'funcparam') {
variable.impl = VAR_EMULATED;
@@ -378,7 +378,7 @@ function analyzer(data, givenTypes) {
}
});
- var BRANCH_INVOKE = searchable('branch', 'invoke');
+ var BRANCH_INVOKE = set('branch', 'invoke');
function operateOnLabels(line, func) {
function process(item, id) {
['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) {
@@ -513,13 +513,13 @@ function analyzer(data, givenTypes) {
dprint('// ' + label.ident + ' :origOut : ' + JSON.stringify(label.originalOutLabels));
}
- // Convert to searchables, for speed (we mainly do lookups here) and code clarity (x in Xlabels)
+ // Convert to set, for speed (we mainly do lookups here) and code clarity (x in Xlabels)
// Also removes duplicates (which we can get in llvm switches)
- // FIXME TODO XXX do we need all these?
- label.outLabels = searchable(label.outLabels);
- label.inLabels = searchable(label.inLabels);
- label.allOutLabels = searchable(label.allOutLabels);
- label.allInLabels = searchable(label.allInLabels);
+ // TODO do we need all these?
+ label.outLabels = set(label.outLabels);
+ label.inLabels = set(label.inLabels);
+ label.allOutLabels = set(label.allOutLabels);
+ label.allInLabels = set(label.allInLabels);
});
}
@@ -571,7 +571,7 @@ function analyzer(data, givenTypes) {
calcLabelBranchingData(labels, labelsDict);
- var s_entries = searchable(entries);
+ var s_entries = set(entries);
dprint('relooping', 'makeBlock: ' + entries + ',' + labels.length + ' labels');
var entryLabels = entries.map(function(entry) { return labelsDict[entry] });
@@ -600,14 +600,9 @@ function analyzer(data, givenTypes) {
var nextEntries = keys(entryLabel.outLabels);
dprint('relooping', ' Creating simple emulated, outlabels: ' + nextEntries);
- //if (nextEntries.length == 1) {
- // replaceLabelLabels([entryLabel], set(nextEntries), 'BNOPP|XXX'); // remove unneeded branch XXX - this is dangerous, as we may
- // // have 1 next entry, but 1 or more B-labels...
- //} else {
- nextEntries.forEach(function(nextEntry) {
- replaceLabelLabels([entryLabel], set(nextEntry), 'BJSET|' + nextEntry); // Just SET __label__ - no break or continue or whatnot
- });
- //}
+ nextEntries.forEach(function(nextEntry) {
+ replaceLabelLabels([entryLabel], set(nextEntry), 'BJSET|' + nextEntry); // Just SET __label__ - no break or continue or whatnot
+ });
return {
type: 'emulated',
id: blockId,
@@ -648,7 +643,7 @@ function analyzer(data, givenTypes) {
// We will be in a loop, |continue| gets us back to the entry
entries.forEach(function(entry) {
- replaceLabelLabels(internals, searchable(entries), 'BCONT|' + blockId);
+ replaceLabelLabels(internals, set(entries), 'BCONT|' + blockId);
});
// To get to any of our (not our parents') exit labels, we will break.
diff --git a/src/compiler.js b/src/compiler.js
index bc53a5c2..1cdc0002 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -22,6 +22,7 @@ load('jsifier.js');
//===============================
// Override settings.js
+
var settings = JSON.parse(readline());
for (setting in settings) {
this[setting] = settings[setting];
@@ -35,6 +36,7 @@ load('runtime.js');
assert(!(USE_TYPED_ARRAYS && SAFE_HEAP));
// Read llvm
+
var lines = [];
var line;
do {
@@ -44,6 +46,7 @@ do {
} while(true);
// Do it
+
eval(preprocess(read('library.js'), CONSTANTS));
print(JSify(analyzer(intertyper(lines))));
diff --git a/src/framework.js b/src/framework.js
index 8fd396b6..e9ff592e 100644
--- a/src/framework.js
+++ b/src/framework.js
@@ -128,8 +128,7 @@ Substrate.prototype = {
if (DEBUG) print("Solving complete: no remaining items");
finalComment();
this.results.forEach(function(output) {
- delete output.__result__; // Might recycle these
- delete output.__uid__;
+ delete output.__uid__; // Might recycle these
});
return this.results;
}
diff --git a/src/intertyper.js b/src/intertyper.js
index f72d33a4..9897884b 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -67,7 +67,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (!parseFunctions) {
var func = funcHeader.processItem(tokenizer.processItem({ lineText: currFunctionLines[0] }, true))[0];
unparsedFunctions.push({
- __result__: true,
intertype: 'unparsedFunction',
// We need this early, to know basic function info - ident, params, varargs
ident: toNiceIdent(func.ident),
@@ -276,7 +275,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (tokensLength >= 3 && token0Text == 'phi')
return 'Phi';
} else if (item.indent === 0) {
- if ((tokensLength >= 1 && token0Text.substr(-1) == ':') || // XXX LLVM 2.7 format, or llvm-gcc in 2.8
+ if ((tokensLength >= 1 && token0Text.substr(-1) == ':') || // LLVM 2.7 format, or llvm-gcc in 2.8
(tokensLength >= 3 && token1Text == '<label>'))
return 'Label';
if (tokensLength >= 4 && token0Text == 'declare')
@@ -291,7 +290,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
}
if (tokensLength >= 3 && (token0Text == 'call' || token1Text == 'call'))
return 'Call';
- if (token0Text in searchable(';', 'target'))
+ if (token0Text in set(';', 'target'))
return '/dev/null';
if (tokensLength >= 3 && token0Text == 'invoke')
return 'Invoke';
@@ -320,7 +319,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
// Clang sometimes has |= i32| instead of |= { i32 }|
fields = [item.tokens[3].text];
} else if (item.tokens[3].text != 'opaque') {
- if (item.tokens[3].type == '<') { // type <{ i8 }> XXX - check spec
+ if (item.tokens[3].type == '<') { // type <{ i8 }> - TODO: check spec
item.tokens[3] = tokenizer.processItem({ lineText: '{ ' + item.tokens[3].item.tokens[0].text + ' }' }, true).tokens[0];
}
var subTokens = item.tokens[3].tokens;
@@ -333,7 +332,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
}
}
return [{
- __result__: true, // XXX can remove these
intertype: 'type',
name_: item.tokens[0].text,
fields: fields,
@@ -350,7 +348,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
item.tokens.splice(2, 1);
}
var ret = {
- __result__: true,
intertype: 'globalVariable',
ident: ident,
type: item.tokens[2].text,
@@ -366,7 +363,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
});
}
} else {
- if (item.tokens[3].type == '<') { // type <{ i8 }> XXX - check spec
+ if (item.tokens[3].type == '<') { // type <{ i8 }> TODO - check spec
item.tokens[3] = item.tokens[3].item.tokens;
}
@@ -389,7 +386,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
return !(token.text in LLVM.LINKAGES || token.text in set('noalias', 'hidden', 'signext', 'zeroext', 'nounwind', 'define', 'inlinehint', '{', 'fastcc'));
});
var ret = {
- __result__: true,
intertype: 'function',
ident: item.tokens[1].text,
returnType: item.tokens[0],
@@ -411,7 +407,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
substrate.addActor('Label', {
processItem: function(item) {
return [{
- __result__: true,
intertype: 'label',
ident: item.tokens[0].text.substr(-1) == ':' ?
'%' + item.tokens[0].text.substr(0, item.tokens[0].text.length-1) :
@@ -551,7 +546,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (item.indent == 2) {
// standalone call - not in assign
item.standalone = true;
- item.__result__ = true;
return [item];
}
this.forwardItem(item, 'Reintegrator');
@@ -576,7 +570,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (item.indent == 2) {
// standalone call - not in assign
item.standalone = true;
- item.__result__ = true;
return [item];
}
this.forwardItem(item, 'Reintegrator');
@@ -621,7 +614,7 @@ function intertyper(data, parseFunctions, baseLineNum) {
item.variant = item.tokens[1].text;
item.tokens.splice(1, 1);
}
- if (item.tokens[1].text == 'exact') item.tokens.splice(1, 1); // XXX - do we need a check at runtime?
+ if (item.tokens[1].text == 'exact') item.tokens.splice(1, 1); // TODO: Implement trap values
var segments = splitTokenList(item.tokens.slice(1));
for (var i = 1; i <= 4; i++) {
if (segments[i-1]) {
@@ -645,7 +638,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (item.tokens[0].text == 'volatile') item.tokens.shift(0);
var segments = splitTokenList(item.tokens.slice(1));
var ret = {
- __result__: true,
intertype: 'store',
valueType: item.tokens[1].text,
value: parseLLVMSegment(segments[0]), // TODO: Make everything use this method, with finalizeLLVMParameter too
@@ -662,14 +654,12 @@ function intertyper(data, parseFunctions, baseLineNum) {
processItem: function(item) {
if (item.tokens[1].text == 'label') {
return [{
- __result__: true,
intertype: 'branch',
label: toNiceIdent(item.tokens[2].text),
lineNum: item.lineNum
}];
} else {
return [{
- __result__: true,
intertype: 'branch',
ident: item.tokens[2].text,
labelTrue: toNiceIdent(item.tokens[5].text),
@@ -683,7 +673,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
substrate.addActor('Return', {
processItem: function(item) {
return [{
- __result__: true,
intertype: 'return',
type: item.tokens[1].text,
value: item.tokens[2] ? parseLLVMSegment(item.tokens.slice(2)) : null,
@@ -707,7 +696,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
return ret;
}
return [{
- __result__: true,
intertype: 'switch',
type: item.tokens[1].text,
ident: item.tokens[2].text,
@@ -721,7 +709,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
substrate.addActor('FuncEnd', {
processItem: function(item) {
return [{
- __result__: true,
intertype: 'functionEnd',
lineNum: item.lineNum
}];
@@ -734,7 +721,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
item.tokens.splice(1, 1);
}
return [{
- __result__: true,
intertype: 'functionStub',
ident: item.tokens[2].text,
returnType: item.tokens[1],
@@ -747,7 +733,6 @@ function intertyper(data, parseFunctions, baseLineNum) {
substrate.addActor('Unreachable', {
processItem: function(item) {
return [{
- __result__: true,
intertype: 'unreachable',
lineNum: item.lineNum
}];
diff --git a/src/jsifier.js b/src/jsifier.js
index 90f4ae86..85108b7d 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -9,7 +9,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
// Now that analysis has completed, we can get around to handling unparsedFunctions
(functionsOnly ? data.functions : data.unparsedFunctions.concat(data.functions)).forEach(function(func) {
- // XXX Save just what we need, to save memory - whether there are varargs, and the # of parameters
+ // Save just what we need, to save memory - whether there are varargs, and the # of parameters
FUNCTIONS[func.ident] = {
hasVarArgs: func.hasVarArgs,
numParams: func.params.length
@@ -33,7 +33,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
if (type.needsFlattening && !type.flatFactor) {
item.JS += 'var ' + niceName + '___FLATTENER = ' + JSON.stringify(TYPES[item.name_].flatIndexes) + ';';
}
- item.__result__ = true;
return [item];
}
});
@@ -172,7 +171,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
return '0';
} else if (segment[1].text == 'zeroinitializer') {
return makeEmptyStruct(segment[0].text);
- } else if (segment[1].text in searchable('bitcast', 'inttoptr', 'ptrtoint')) { // TODO: Use parse/finalizeLLVMFunctionCall
+ } else if (segment[1].text in set('bitcast', 'inttoptr', 'ptrtoint')) { // TODO: Use parse/finalizeLLVMFunctionCall
var type = segment[2].item.tokens.slice(-1)[0].text; // TODO: Use this?
return handleSegment(segment[2].item.tokens.slice(0, -2));
} else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
@@ -228,7 +227,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
substrate.addActor('GlobalVariable', {
processItem: function(item) {
item.intertype = 'GlobalVariableStub';
- item.__result__ = true;
var ret = [item];
if (item.ident == '_llvm_global_ctors') {
item.JS = '\n__globalConstructor__ = function() {\n' +
@@ -248,7 +246,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
ret.push({
intertype: 'GlobalVariablePostSet',
JS: 'IHEAP[' + item.ident + '+' + i + '] = ' + value + ';',
- __result__: true
});
constant[i] = '0';
}
@@ -259,7 +256,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
return ret.concat({
intertype: 'GlobalVariable',
JS: item.ident + ' = ' + constant + ';',
- __result__: true
});
}
}
@@ -288,7 +284,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
} else {
item.JS = '// stub for ' + item.ident;
}
- item.__result__ = true;
return [item];
}
});
@@ -442,7 +437,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
if (LABEL_DEBUG) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n";
func.JS += '}\n';
func.JS += func.ident + '.__index__ = Runtime.getFunctionIndex(' + func.ident + ', "' + func.ident + '");\n';
- func.__result__ = true;
return func;
}
});
@@ -518,7 +512,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
return substrate.addActor('Intertype:' + intertype, {
processItem: function(item) {
item.JS = func(item);
- if (!item.JS) throw "XXX - no JS generated for " + dump(item);
+ if (!item.JS) throw "No JS generated for " + dump(item);
this.forwardItem(item, 'FuncLineTriager');
}
});
@@ -556,7 +550,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
label = label.substr(1);
if (label === 'entry') return '-1';
if (label === parseInt(label)) return label; // clang
- //return '"' + label + '"'; // XXX debugging
+ //return '"' + label + '"'; // debugging
label = toNiceIdent(label);
if (label in LABEL_IDs) return LABEL_IDs[label];
return LABEL_IDs[label] = LABEL_ID_COUNTER ++;
@@ -721,12 +715,12 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
case 'sdiv': case 'udiv': return checkOverflow('Math.floor(' + ident1 + ' / ' + ident2 + ')');
case 'mul': return checkOverflow(ident1 + ' * ' + ident2);
case 'urem': case 'srem': return 'Math.floor(' + ident1 + ' % ' + ident2 + ')';
- case 'or': return ident1 + ' | ' + ident2; // XXX this forces into a 32-bit int - add overflow-style checks?
- case 'and': return ident1 + ' & ' + ident2; // XXX ^
- case 'xor': return ident1 + ' ^ ' + ident2; // XXX ^
- case 'shl': return ident1 + ' << ' + ident2; // XXX ^
- case 'ashr': return ident1 + ' >> ' + ident2; // XXX ^
- case 'lshr': return ident1 + ' >>> ' + ident2; // XXX ^
+ case 'or': return ident1 + ' | ' + ident2; // TODO this forces into a 32-bit int - add overflow-style checks? also other bitops below us
+ case 'and': return ident1 + ' & ' + ident2;
+ case 'xor': return ident1 + ' ^ ' + ident2;
+ case 'shl': return ident1 + ' << ' + ident2;
+ case 'ashr': return ident1 + ' >> ' + ident2;
+ case 'lshr': return ident1 + ' >>> ' + ident2;
case 'fadd': return ident1 + ' + ' + ident2;
case 'fsub': return ident1 + ' - ' + ident2;
case 'fdiv': return ident1 + ' / ' + ident2;
@@ -746,8 +740,8 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
}
case 'fcmp': {
switch (variant) {
- // XXX 'o' ones should be 'ordered (no NaN) and',
- // 'u' ones should be 'unordered or'.
+ // TODO 'o' ones should be 'ordered (no NaN) and',
+ // 'u' ones should be 'unordered or'.
case 'uge': case 'oge': return ident1 + ' >= ' + ident2;
case 'ule': case 'ole': return ident1 + ' <= ' + ident2;
case 'ugt': case 'ogt': return ident1 + ' > ' + ident2;
@@ -770,14 +764,8 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
return '((' + ident1 + ') & ' + (Math.pow(2, bitsLeft)-1) + ')';
}
case 'select': return ident1 + ' ? ' + ident2 + ' : ' + ident3;
- case 'ptrtoint': {
- //if (type != 'i8*') print('// XXX Warning: Risky ptrtoint operation on line ' + lineNum);
- return ident1;
- }
- case 'inttoptr': {
- //print('// XXX Warning: inttoptr operation on line ' + lineNum);
- return ident1;
- }
+ case 'ptrtoint': return ident1;
+ case 'inttoptr': return ident1;
default: throw 'Unknown mathcmp op: ' + item.op;
}
} });
@@ -843,7 +831,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
}
} else {
if (curr != 0) {
- indexes.push(curr); // XXX QUANTUM_SIZE?
+ indexes.push(curr);
}
}
if (!isNumber(curr) || parseInt(curr) < 0) {
@@ -866,7 +854,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
function finalizeLLVMFunctionCall(item) {
switch(item.intertype) {
- case 'getelementptr': // XXX finalizeLLVMParameter on the ident and the indexes?
+ case 'getelementptr': // TODO finalizeLLVMParameter on the ident and the indexes?
return makePointer(makeGetSlab(item.ident, item.type), getGetElementPtrIndexes(item), null, item.type);
case 'bitcast':
case 'inttoptr':
@@ -906,8 +894,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
}
makeFuncLineActor('bitcast', function(item) {
- // XXX Don't we need to copy ptr - i.e. create new ones (at least if uses > just the next line)?
- // XXX hardcoded ptr impl - as ptrs are ints, we don't need to copy
var ident = toNiceIdent(item.ident);
return ident;
});
diff --git a/src/parseTools.js b/src/parseTools.js
index 58b1ed71..a5a20939 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -163,7 +163,7 @@ function splitTokenList(tokens) {
if (tokens.slice(-1)[0].text != ',') tokens.push({text:','});
var ret = [];
var seg = [];
- var SPLITTERS = searchable(',', 'to'); // 'to' can separate parameters as well...
+ var SPLITTERS = set(',', 'to'); // 'to' can separate parameters as well...
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token.text in SPLITTERS) {
@@ -317,7 +317,7 @@ function cleanSegment(segment) {
return segment;
}
-PARSABLE_LLVM_FUNCTIONS = searchable('getelementptr', 'bitcast', 'inttoptr', 'ptrtoint', 'mul', 'icmp', 'zext');
+PARSABLE_LLVM_FUNCTIONS = set('getelementptr', 'bitcast', 'inttoptr', 'ptrtoint', 'mul', 'icmp', 'zext');
// Parses a function call of form
// TYPE functionname MODIFIERS (...)
diff --git a/src/utility.js b/src/utility.js
index ce726fbe..6973362d 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -1,4 +1,5 @@
-// General JS utilities
+// General JS utilities - things that might be useful in any JS project.
+// Nothing specific to Emscripten appears here.
function safeQuote(x) {
return x.replace(/"/g, '\\"')
@@ -90,15 +91,6 @@ function zeros(size) {
return ret;
}
-function searchable() {
- if (typeof arguments[0] === 'object') arguments = arguments[0];
- var ret = {};
- for (var i = 0; i < arguments.length; i++) {
- ret[arguments[i]] = 0;
- }
- return ret;
-}
-
function walkJSON(item, func) {
if (item.length) {
for (var x = 0; x < item.length; x++) {
@@ -204,9 +196,30 @@ function mergeInto(obj, other) {
return obj;
}
+function isNumber(x) {
+ return x == parseFloat(x);
+}
+
+function flatten(x) {
+ if (typeof x !== 'object') return x;
+ var ret = [];
+ for (var i = 0; i < x.length; i++) {
+ ret = ret.concat(flatten(x[i]));
+ }
+ return ret;
+}
+
// Sets
-set = searchable; // Create a 'set'
+function set() {
+ if (typeof arguments[0] === 'object') arguments = arguments[0];
+ var ret = {};
+ for (var i = 0; i < arguments.length; i++) {
+ ret[arguments[i]] = 0;
+ }
+ return ret;
+}
+
function setSub(x, y) {
var ret = set(values(x));
for (yy in y) {
@@ -228,16 +241,3 @@ function setIntersect(x, y) {
return ret;
}
-function isNumber(x) {
- return x == parseFloat(x);
-}
-
-function flatten(x) {
- if (typeof x !== 'object') return x;
- var ret = [];
- for (var i = 0; i < x.length; i++) {
- ret = ret.concat(flatten(x[i]));
- }
- return ret;
-}
-