[pypy-commit] benchmarks default: Add ICBD as a benchmark. This comes from Kevin Modzelewski on pypy-dev.
arigo
noreply at buildbot.pypy.org
Wed Dec 10 10:26:58 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r292:67706c915134
Date: 2014-12-10 09:15 +0000
http://bitbucket.org/pypy/benchmarks/changeset/67706c915134/
Log: Add ICBD as a benchmark. This comes from Kevin Modzelewski on pypy-
dev.
diff too long, truncating to 2000 out of 90238 lines
diff --git a/benchmarks.py b/benchmarks.py
--- a/benchmarks.py
+++ b/benchmarks.py
@@ -82,7 +82,8 @@
'spectral-norm', 'chaos', 'telco', 'go', 'pyflate-fast',
'raytrace-simple', 'crypto_pyaes', 'bm_mako', 'bm_chameleon',
'json_bench', 'pidigits', 'hexiom2', 'eparse', 'deltablue',
- 'bm_dulwich_log', 'bm_krakatau', 'bm_mdp', 'pypy_interp']:
+ 'bm_dulwich_log', 'bm_krakatau', 'bm_mdp', 'pypy_interp',
+ 'bm_icbd']:
_register_new_bm(name, name, globals(), **opts.get(name, {}))
for name in ['names', 'iteration', 'tcp', 'pb', ]:#'web']:#, 'accepts']:
diff --git a/own/bm_icbd.py b/own/bm_icbd.py
new file mode 100644
--- /dev/null
+++ b/own/bm_icbd.py
@@ -0,0 +1,35 @@
+import sys, os, subprocess, time
+this_dir = os.path.abspath(os.path.dirname(__file__))
+
+def main(n):
+ # HAAAAAACK with subprocess because I can't get the thing
+ # to run in-process :-( As a result, it doesn't make
+ # sense to run it more than once.
+
+ d = os.environ.copy()
+ d['PYTHONPATH'] = 'icbd'
+ t0 = time.time()
+ popen = subprocess.Popen(
+ [sys.executable,
+ '-m', 'icbd.type_analyzer.analyze_all',
+ '-I', 'stdlib/python2.5_tiny',
+ '-I', '.',
+ '-E', 'icbd/type_analyzer/tests',
+ '-E', 'icbd/compiler/benchmarks',
+ '-E', 'icbd/compiler/tests',
+ '-I', 'stdlib/type_mocks',
+ '-n',
+ 'icbd'], cwd=this_dir, env=d, stdout=subprocess.PIPE)
+ popen.communicate()
+ time_elapsed = time.time() - t0
+ return [time_elapsed] * n
+
+if __name__ == "__main__":
+ import util, optparse
+ parser = optparse.OptionParser(
+ usage="%prog [options]",
+ description="Test the performance of the ICBD benchmark")
+ util.add_standard_options_to(parser)
+ options, args = parser.parse_args()
+
+ util.run_benchmark(options, options.num_runs, main)
diff --git a/own/icbd/.gitignore b/own/icbd/.gitignore
new file mode 100644
--- /dev/null
+++ b/own/icbd/.gitignore
@@ -0,0 +1,24 @@
+*.pyc
+*.d
+*.sw?
+*.out
+*.out[0-9]
+*.o
+*.s
+*.s[0-9]
+*.gen.bc
+*.gen.c
+*.comb.ll
+*.gen.ll
+*opt.ll
+*.so
+icbd/compiler/tests/[0-9]
+icbd/compiler/tests/[0-9][0-9]
+icbd/compiler/tests/*.hpp
+icbd/compiler/tests/*[0-9].cpp
+icbd/compiler/tests/Makefile
+*.shed
+*.ppm
+icbd/compiler/dist
+*.pyicbd
+*.pyd
diff --git a/own/icbd/LICENSE b/own/icbd/LICENSE
new file mode 100644
--- /dev/null
+++ b/own/icbd/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014, Kevin Modzelewski
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/own/icbd/README.md b/own/icbd/README.md
new file mode 100644
--- /dev/null
+++ b/own/icbd/README.md
@@ -0,0 +1,109 @@
+# icbd
+
+> ICBD is a defunct project, but I'm releasing the source code in case any one is interested.
+
+ICBD is a static type analyzer and static compiler for Python. It originated
+from the desire at Dropbox to have additional type information for our growing
+codebases, without requiring programmers to add type annotations. There are
+other static type analyzers for Python out there; the goal of ICBD was to
+produce one that would work well on the Dropbox codebase, which meant
+concretely:
+
+- Handling untypable code as gracefully as possible
+- "Acceptable" running times for multi-100k LOC codebases
+- A plugin system for handling code that is inherently not statically analyzable
+
+These goals were somewhat met, perhaps to the limits of using whole-program type
+inference; the running time for the Dropbox codebase was about 15 minutes, which
+I believe is better than alternatives but is not good enough for easy use.
+
+The plugin system was able to get anecdotally get ICBD to successfully analyze a
+sufficient fraction of the Dropbox codebase, though when typing failed, it was
+difficult to tell why.
+
+### Testing it out
+
+You need to install pygments and simplejson to run ICBD; once you do, run
+
+```
+bash icbd/type_analyzer/run.sh icbd
+```
+
+to have ICBD analyze its own codebase (it doesn't do particularly well since
+there are no plugins for its getattr usage). You can see the output at
+file:///tmp/icbd_icbd/icbd/type_analyzer/type_checker.html
+
+### Technical approach
+
+ICBD treats every Python expression as a constraint on the allowable types of
+the program: `a = o.x` encodes the constraint that "a will have the type of o's
+x attribute", `f(x)` encodes the constaint that "f accepts a type argument of
+type type(x)", etc. At a high level, ICBD then does a graph fixed-point
+analysis to determine a set of types that satisfy the constraints, and emits
+errors when types could not be found (ex: `a, b, c = 1, 2`).
+
+The guessed types start at the BOTTOM type, and ICBD iteratively finds
+unsatisfied constraints and raises the involved types to attempt to satisfy the
+constraints. In theory, if ICBD always raises types monotonically and to the
+minimum satisfying type, this process will converge on a deterministic set of
+lowest (or in some sense, most descriptive) types.
+
+In practice, this is somewhat harder because the type constraints are dependent
+on other types -- for example, attribute lookup dependencies can change based on
+learning that an attribute may actually be a instance attribute. This doesn't
+seem to be that big a deal, though.
+
+### Comparison to Python type analyzers
+
+ICBD only analyzes a single version of each function, and assumes that any
+combination of seen argument types could occur together. For example, in this
+snippet:
+
+```python
+def add_int_or_str(a, b):
+ return a + b
+
+add_int_or_str(1, 2)
+add_int_or_str("hello ", "world")
+```
+
+ICBD will report an error, saying that an int cannot be added to a string.
+Other analyzers will notice that add_int_or_str does not actually receive an
+(int, str) combination of arguments and handle this correctly, but at an
+exponentially-large cost.
+
+This means that ICBD does not handle polymorphic functions very gracefully,
+but in practice this seems to net be a common thing for applications code, and
+the plugin system makes it possible to handle on a one-off basis.
+
+#### Quick note about HM
+
+People often ask "why don't you just apply HM (Hindley-Milner) which computes
+the types ideally". Yes, it's true that HM has some nice ideality properties,
+but it only applies to a fairly-restrictive type system. I'm not a type
+theorist, but my understanding is that to properly represent the Python type
+system you need
+
+- Dependent types to represent attributes, and
+- Rank-n polymorphism to represent global variables
+
+both of which I believe make the inference problem undecidable. (Is there
+really any Haskell program that uses 0 type annotations?)
+
+Of course in theory it's possible to translate Python code into, for example,
+Haskell, but I don't see any reason to believe this can be done in an automated
+way such that the generated Haskell has any meaningful relation to the original
+Python. For example, one could build an X86 emulator in Haskell, and use that
+to run the Python interpreter, but the types on the Haskell program have no
+usefulness to the original Python programmer.
+
+# Compiler
+
+ICBD also includes a static compiler, in icbd/compiler. Assuming that the type
+analyzer can come up with a complete set of types for your program (a big
+assumption), in theory it should be possible to compile the Python as if it were
+a more traditionally-typed static language.
+
+In practice I doubt that real code can really be 100% typed; the ICBD compiler
+served as the starting point for the [Pyston](https://github.com/dropbox/pyston)
+project, which replaces it.
diff --git a/own/icbd/demos/demo.py b/own/icbd/demos/demo.py
new file mode 100644
--- /dev/null
+++ b/own/icbd/demos/demo.py
@@ -0,0 +1,291 @@
+if 0:
+ ""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Basic type analysis:
+ a = 2
+ b = '3'
+ d = {a:b}
+ ch = ord(b[2].lower()[0])
+ print ch
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Name errors:
+ ch *= e
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Nested-type manipulation:
+ d = {1:[1], 3:[4]}
+ d[1].append(2)
+
+ l = [range(i) for i in xrange(5)]
+ l.append([-1])
+ l2 = [k[0] for k in l]
+ l2.append(1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Function type inference:
+ def func(x, y):
+ return b * (x + y)
+ r = func(3, 4)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Higher-level types:
+ def f(x):
+ def g():
+ return x
+ return g
+
+ inner = f(2)
+ print f(1)() + inner()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Control-flow analysis:
+ if inner():
+ x = 3
+ else:
+ x = [0]
+ print l2[x]
+
+ def fib(x):
+ if x <= 1:
+ return x
+ return fib(x-1) + fib(x-2)
+ fib(2)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def foo():
+ return foo()
+ if 0:
+ x = 0
+ else:
+ x = foo()
+ print x
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Classes:
+ class C(object):
+ def __init__(self, x):
+ self.x = x
+ def bar(self, z):
+ return self.x * z
+ def baz(self, k):
+ return k**2
+
+ c = C(2)
+ c.baz(3)
+
+
+
+
+
+
+
+
+
+
+ # attributes
+ print c.x
+ z = c.bar(3)
+ c.y = 3
+ z = c.x * c.y
+ z *= c.z
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Complex type analysis:
+ def f1(x):
+ def g(y):
+ return x * y
+ return g
+
+ a = f1('')
+ b = a(2)
+
+ def f2(x):
+ def g(y):
+ return x * y
+ return g
+
+ a = f2(1)
+ b = a(2)
+
+
+
+
+
+
+ ""
diff --git a/own/icbd/demos/demo_compact.py b/own/icbd/demos/demo_compact.py
new file mode 100644
--- /dev/null
+++ b/own/icbd/demos/demo_compact.py
@@ -0,0 +1,105 @@
+# Basic type analysis:
+a = 2
+b = '3'
+d = {a:b}
+c = ord(b[2].lower()[0])
+print c
+
+
+# Name errors:
+c *= e
+
+# Nested-type manipulation:
+d = {1:[1], 3:[4]}
+d[1].append(2)
+
+l = [range(i) for i in xrange(5)]
+l.append([-1])
+l2 = [k[0] for k in l]
+l2.append(1)
+
+
+# Argument-type checking, based on inferred types
+l2.append('')
+
+
+
+# Function type inference:
+def f(x, y):
+ return b * (x + y)
+r = f(3, 4)
+
+
+
+# Higher-level types:
+def f(x):
+ def g():
+ return x
+ return g
+
+f1 = f(2)
+print f(1)() + f1()
+
+
+
+
+# Control-flow analysis:
+if f1():
+ x = 3
+else:
+ x = [0]
+print l2[x]
+
+def fib(x):
+ if x <= 1:
+ return x
+ return fib(x-1) + fib(x-2)
+fib(2)
+
+
+def foo():
+ return foo()
+if 0:
+ x = 0
+else:
+ x = foo()
+print x
+
+
+# Classes:
+class Foo(object):
+ def __init__(self, x):
+ self.x = x
+ def bar(self, z):
+ return self.x * z
+ def baz(self, k):
+ return k**2
+
+f = Foo(2)
+f.baz(3)
+
+# attributes
+print f.x
+z = f.bar(3)
+f.y = 3
+z = f.x * f.y
+z *= f.z
+
+
+# Complex type analysis:
+def f1(x):
+ def g(y):
+ return x * y
+ return g
+
+a = f1('')
+b = a(2)
+
+def f2(x):
+ def g(y):
+ return x * y
+ return g
+
+a = f2(1)
+b = a(2)
+
diff --git a/own/icbd/demos/ray.html b/own/icbd/demos/ray.html
new file mode 100644
--- /dev/null
+++ b/own/icbd/demos/ray.html
@@ -0,0 +1,15385 @@
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Emscripten-Generated Code</title>
+ <style>
+ .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
+ canvas.emscripten { border: 1px solid black; }
+ textarea.emscripten { font-family: monospace; width: 80%; }
+ div.emscripten { text-align: center; }
+ </style>
+ </head>
+ <body>
+ <hr/>
+ <div class="emscripten" id="status">Downloading...</div>
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <hr/>
+ <div class="emscripten"><input type="button" value="fullscreen" onclick="Module.requestFullScreen()"></div>
+ <hr/>
+ <textarea class="emscripten" id="output" rows="8"></textarea>
+ <hr>
+ <script type='text/javascript'>
+ // connect to canvas
+ var Module = {
+ preRun: [],
+ postRun: [],
+ print: (function() {
+ var element = document.getElementById('output');
+ element.value = ''; // clear browser cache
+ return function(text) {
+ // These replacements are necessary if you render to raw HTML
+ //text = text.replace(/&/g, "&");
+ //text = text.replace(/</g, "<");
+ //text = text.replace(/>/g, ">");
+ //text = text.replace('\n', '<br>', 'g');
+ element.value += text + "\n";
+ element.scrollTop = 99999; // focus on bottom
+ };
+ })(),
+ printErr: function(text) {
+ if (0) { // XXX disabled for safety typeof dump == 'function') {
+ dump(text + '\n'); // fast, straight to the real console
+ } else {
+ console.log(text);
+ }
+ },
+ canvas: document.getElementById('canvas'),
+ setStatus: function(text) {
+ if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
+ document.getElementById('status').innerHTML = text;
+ if (text) {
+ var counter = 0;
+ Module.setStatus.interval = setInterval(function() {
+ counter++;
+ counter %= 3;
+ var dots = ' ';
+ for (var i = 0; i < counter; i++) dots += '.';
+ dots += '*';
+ for (var i = counter; i < 2; i++) dots += '.';
+ document.getElementById('status').innerHTML = text.replace('...', dots);
+ }, 300);
+ }
+ },
+ totalDependencies: 0,
+ monitorRunDependencies: function(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ Module.setStatus(left ? 'Preparing: ' + (this.totalDependencies-left) + '/' + this.totalDependencies + '...' : 'All downloads complete.');
+ }
+ };
+ Module.setStatus('Downloading...');
+ </script>
+ <script type='text/javascript'>
+
+ // Note: Some Emscripten settings will significantly limit the speed of the generated code.
+// Note: Some Emscripten settings may limit the speed of the generated code.
+// TODO: " u s e s t r i c t ";
+
+try {
+ this['Module'] = Module;
+} catch(e) {
+ this['Module'] = Module = {};
+}
+
+// The environment setup code below is customized to use Module.
+// *** Environment setup code ***
+var ENVIRONMENT_IS_NODE = typeof process === 'object';
+var ENVIRONMENT_IS_WEB = typeof window === 'object';
+var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
+var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+
+if (ENVIRONMENT_IS_NODE) {
+ // Expose functionality in the same simple way that the shells work
+ // Note that we pollute the global namespace here, otherwise we break in node
+ Module['print'] = function(x) {
+ process['stdout'].write(x + '\n');
+ };
+ Module['printErr'] = function(x) {
+ process['stderr'].write(x + '\n');
+ };
+
+ var nodeFS = require('fs');
+ var nodePath = require('path');
+
+ Module['read'] = function(filename) {
+ filename = nodePath['normalize'](filename);
+ var ret = nodeFS['readFileSync'](filename).toString();
+ // The path is absolute if the normalized version is the same as the resolved.
+ if (!ret && filename != nodePath['resolve'](filename)) {
+ filename = path.join(__dirname, '..', 'src', filename);
+ ret = nodeFS['readFileSync'](filename).toString();
+ }
+ return ret;
+ };
+
+ Module['load'] = function(f) {
+ globalEval(read(f));
+ };
+
+ if (!Module['arguments']) {
+ Module['arguments'] = process['argv'].slice(2);
+ }
+} else if (ENVIRONMENT_IS_SHELL) {
+ Module['print'] = print;
+ if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm
+
+ // Polyfill over SpiderMonkey/V8 differences
+ if (typeof read != 'undefined') {
+ Module['read'] = read;
+ } else {
+ Module['read'] = function(f) { snarf(f) };
+ }
+
+ if (!Module['arguments']) {
+ if (typeof scriptArgs != 'undefined') {
+ Module['arguments'] = scriptArgs;
+ } else if (typeof arguments != 'undefined') {
+ Module['arguments'] = arguments;
+ }
+ }
+} else if (ENVIRONMENT_IS_WEB) {
+ if (!Module['print']) {
+ Module['print'] = function(x) {
+ console.log(x);
+ };
+ }
+
+ if (!Module['printErr']) {
+ Module['printErr'] = function(x) {
+ console.log(x);
+ };
+ }
+
+ Module['read'] = function(url) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.send(null);
+ return xhr.responseText;
+ };
+
+ if (!Module['arguments']) {
+ if (typeof arguments != 'undefined') {
+ Module['arguments'] = arguments;
+ }
+ }
+} else if (ENVIRONMENT_IS_WORKER) {
+ // We can do very little here...
+
+ Module['load'] = importScripts;
+
+} else {
+ throw 'Unknown runtime environment. Where are we?';
+}
+
+function globalEval(x) {
+ eval.call(null, x);
+}
+if (!Module['load'] == 'undefined' && Module['read']) {
+ Module['load'] = function(f) {
+ globalEval(Module['read'](f));
+ };
+}
+if (!Module['print']) {
+ Module['print'] = function(){};
+}
+if (!Module['printErr']) {
+ Module['printErr'] = Module['print'];
+}
+if (!Module['arguments']) {
+ Module['arguments'] = [];
+}
+// *** Environment setup code ***
+
+// Closure helpers
+Module.print = Module['print'];
+Module.printErr = Module['printErr'];
+
+// Callbacks
+if (!Module['preRun']) Module['preRun'] = [];
+if (!Module['postRun']) Module['postRun'] = [];
+
+
+// === Auto-generated preamble library stuff ===
+
+//========================================
+// Runtime code shared with compiler
+//========================================
+
+var Runtime = {
+ stackSave: function () {
+ return STACKTOP;
+ },
+ stackRestore: function (stackTop) {
+ STACKTOP = stackTop;
+ },
+ forceAlign: function (target, quantum) {
+ quantum = quantum || 4;
+ if (quantum == 1) return target;
+ if (isNumber(target) && isNumber(quantum)) {
+ return Math.ceil(target/quantum)*quantum;
+ } else if (isNumber(quantum) && isPowerOfTwo(quantum)) {
+ var logg = log2(quantum);
+ return '((((' +target + ')+' + (quantum-1) + ')>>' + logg + ')<<' + logg + ')';
+ }
+ return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum;
+ },
+ isNumberType: function (type) {
+ return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES;
+ },
+ isPointerType: function isPointerType(type) {
+ return type[type.length-1] == '*';
+},
+ isStructType: function isStructType(type) {
+ if (isPointerType(type)) return false;
+ if (/^\[\d+\ x\ (.*)\]/.test(type)) return true; // [15 x ?] blocks. Like structs
+ if (/<?{ ?[^}]* ?}>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types
+ // See comment in isStructPointerType()
+ return type[0] == '%';
+},
+ INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0},
+ FLOAT_TYPES: {"float":0,"double":0},
+ bitshift64: function (low, high, op, bits) {
+ var ander = Math.pow(2, bits)-1;
+ if (bits < 32) {
+ switch (op) {
+ case 'shl':
+ return [low << bits, (high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits))];
+ case 'ashr':
+ return [(((low >>> bits ) | ((high&ander) << (32 - bits))) >> 0) >>> 0, (high >> bits) >>> 0];
+ case 'lshr':
+ return [((low >>> bits) | ((high&ander) << (32 - bits))) >>> 0, high >>> bits];
+ }
+ } else if (bits == 32) {
+ switch (op) {
+ case 'shl':
+ return [0, low];
+ case 'ashr':
+ return [high, (high|0) < 0 ? ander : 0];
+ case 'lshr':
+ return [high, 0];
+ }
+ } else { // bits > 32
+ switch (op) {
+ case 'shl':
+ return [0, low << (bits - 32)];
+ case 'ashr':
+ return [(high >> (bits - 32)) >>> 0, (high|0) < 0 ? ander : 0];
+ case 'lshr':
+ return [high >>> (bits - 32) , 0];
+ }
+ }
+ abort('unknown bitshift64 op: ' + [value, op, bits]);
+ },
+ or64: function (x, y) {
+ var l = (x | 0) | (y | 0);
+ var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ and64: function (x, y) {
+ var l = (x | 0) & (y | 0);
+ var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ xor64: function (x, y) {
+ var l = (x | 0) ^ (y | 0);
+ var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ getNativeTypeSize: function (type, quantumSize) {
+ if (Runtime.QUANTUM_SIZE == 1) return 1;
+ var size = {
+ '%i1': 1,
+ '%i8': 1,
+ '%i16': 2,
+ '%i32': 4,
+ '%i64': 8,
+ "%float": 4,
+ "%double": 8
+ }['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc
+ if (!size) {
+ if (type[type.length-1] == '*') {
+ size = Runtime.QUANTUM_SIZE; // A pointer
+ } else if (type[0] == 'i') {
+ var bits = parseInt(type.substr(1));
+ assert(bits % 8 == 0);
+ size = bits/8;
+ }
+ }
+ return size;
+ },
+ getNativeFieldSize: function (type) {
+ return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
+ },
+ dedup: function dedup(items, ident) {
+ var seen = {};
+ if (ident) {
+ return items.filter(function(item) {
+ if (seen[item[ident]]) return false;
+ seen[item[ident]] = true;
+ return true;
+ });
+ } else {
+ return items.filter(function(item) {
+ if (seen[item]) return false;
+ seen[item] = true;
+ return true;
+ });
+ }
+},
+ set: function set() {
+ var args = typeof arguments[0] === 'object' ? arguments[0] : arguments;
+ var ret = {};
+ for (var i = 0; i < args.length; i++) {
+ ret[args[i]] = 0;
+ }
+ return ret;
+},
+ calculateStructAlignment: function calculateStructAlignment(type) {
+ type.flatSize = 0;
+ type.alignSize = 0;
+ var diffs = [];
+ var prev = -1;
+ type.flatIndexes = type.fields.map(function(field) {
+ var size, alignSize;
+ if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) {
+ size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s.
+ alignSize = size;
+ } else if (Runtime.isStructType(field)) {
+ size = Types.types[field].flatSize;
+ alignSize = Types.types[field].alignSize;
+ } else {
+ throw 'Unclear type in struct: ' + field + ', in ' + type.name_ + ' :: ' + dump(Types.types[type.name_]);
+ }
+ alignSize = type.packed ? 1 : Math.min(alignSize, Runtime.QUANTUM_SIZE);
+ type.alignSize = Math.max(type.alignSize, alignSize);
+ var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory
+ type.flatSize = curr + size;
+ if (prev >= 0) {
+ diffs.push(curr-prev);
+ }
+ prev = curr;
+ return curr;
+ });
+ type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize);
+ if (diffs.length == 0) {
+ type.flatFactor = type.flatSize;
+ } else if (Runtime.dedup(diffs).length == 1) {
+ type.flatFactor = diffs[0];
+ }
+ type.needsFlattening = (type.flatFactor != 1);
+ return type.flatIndexes;
+ },
+ generateStructInfo: function (struct, typeName, offset) {
+ var type, alignment;
+ if (typeName) {
+ offset = offset || 0;
+ type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName];
+ if (!type) return null;
+ assert(type.fields.length === struct.length, 'Number of named fields must match the type for ' + typeName);
+ alignment = type.flatIndexes;
+ } else {
+ var type = { fields: struct.map(function(item) { return item[0] }) };
+ alignment = Runtime.calculateStructAlignment(type);
+ }
+ var ret = {
+ __size__: type.flatSize
+ };
+ if (typeName) {
+ struct.forEach(function(item, i) {
+ if (typeof item === 'string') {
+ ret[item] = alignment[i] + offset;
+ } else {
+ // embedded struct
+ var key;
+ for (var k in item) key = k;
+ ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]);
+ }
+ });
+ } else {
+ struct.forEach(function(item, i) {
+ ret[item[1]] = alignment[i];
+ });
+ }
+ return ret;
+ },
+ addFunction: function (func) {
+ var ret = FUNCTION_TABLE.length;
+ FUNCTION_TABLE.push(func);
+ FUNCTION_TABLE.push(0);
+ return ret;
+ },
+ warnOnce: function (text) {
+ if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
+ if (!Runtime.warnOnce.shown[text]) {
+ Runtime.warnOnce.shown[text] = 1;
+ Module.printErr(text);
+ }
+ },
+ funcWrappers: {},
+ getFuncWrapper: function (func) {
+ if (!Runtime.funcWrappers[func]) {
+ Runtime.funcWrappers[func] = function() {
+ FUNCTION_TABLE[func].apply(null, arguments);
+ };
+ }
+ return Runtime.funcWrappers[func];
+ },
+ UTF8Processor: function () {
+ var buffer = [];
+ var needed = 0;
+ this.processCChar = function (code) {
+ code = code & 0xff;
+ if (needed) {
+ buffer.push(code);
+ needed--;
+ }
+ if (buffer.length == 0) {
+ if (code < 128) return String.fromCharCode(code);
+ buffer.push(code);
+ if (code > 191 && code < 224) {
+ needed = 1;
+ } else {
+ needed = 2;
+ }
+ return '';
+ }
+ if (needed > 0) return '';
+ var c1 = buffer[0];
+ var c2 = buffer[1];
+ var c3 = buffer[2];
+ var ret;
+ if (c1 > 191 && c1 < 224) {
+ ret = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
+ } else {
+ ret = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+ }
+ buffer.length = 0;
+ return ret;
+ }
+ this.processJSString = function(string) {
+ string = unescape(encodeURIComponent(string));
+ var ret = [];
+ for (var i = 0; i < string.length; i++) {
+ ret.push(string.charCodeAt(i));
+ }
+ return ret;
+ }
+ },
+ stackAlloc: function stackAlloc(size) { var ret = STACKTOP;STACKTOP += size;STACKTOP = ((((STACKTOP)+3)>>2)<<2);assert(STACKTOP < STACK_ROOT + STACK_MAX, "Ran out of stack"); return ret; },
+ staticAlloc: function staticAlloc(size) { var ret = STATICTOP;STATICTOP += size;STATICTOP = ((((STATICTOP)+3)>>2)<<2); if (STATICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; },
+ alignMemory: function alignMemory(size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 4))*(quantum ? quantum : 4); return ret; },
+ makeBigInt: function makeBigInt(low,high,unsigned) { var ret = (unsigned ? (((low)>>>0)+(((high)>>>0)*4294967296)) : (((low)>>>0)+(((high)|0)*4294967296))); return ret; },
+ QUANTUM_SIZE: 4,
+ __dummy__: 0
+}
+
+
+
+var CorrectionsMonitor = {
+ MAX_ALLOWED: 0, // XXX
+ corrections: 0,
+ sigs: {},
+
+ note: function(type, succeed, sig) {
+ if (!succeed) {
+ this.corrections++;
+ if (this.corrections >= this.MAX_ALLOWED) abort('\n\nToo many corrections!');
+ }
+ },
+
+ print: function() {
+ }
+};
+
+
+
+
+
+//========================================
+// Runtime essentials
+//========================================
+
+var __THREW__ = false; // Used in checking for thrown exceptions.
+
+var ABORT = false;
+
+var undef = 0;
+// tempInt is used for 32-bit signed values or smaller. tempBigInt is used
+// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt
+var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD;
+var tempI64, tempI64b;
+
+function abort(text) {
+ Module.print(text + ':\n' + (new Error).stack);
+ ABORT = true;
+ throw "Assertion: " + text;
+}
+
+function assert(condition, text) {
+ if (!condition) {
+ abort('Assertion failed: ' + text);
+ }
+}
+
+var globalScope = this;
+
+// C calling interface. A convenient way to call C functions (in C files, or
+// defined with extern "C").
+//
+// Note: LLVM optimizations can inline and remove functions, after which you will not be
+// able to call them. Adding
+//
+// __attribute__((used))
+//
+// to the function definition will prevent that.
+//
+// Note: Closure optimizations will minify function names, making
+// functions no longer callable. If you run closure (on by default
+// in -O2 and above), you should export the functions you will call
+// by calling emcc with something like
+//
+// -s EXPORTED_FUNCTIONS='["_func1","_func2"]'
+//
+// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C")
+// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
+// 'array' for JavaScript arrays and typed arrays).
+// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
+// except that 'array' is not possible (there is no way for us to know the length of the array)
+// @param args An array of the arguments to the function, as native JS values (as in returnType)
+// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
+// @return The return value, as a native JS value (as in returnType)
+function ccall(ident, returnType, argTypes, args) {
+ var stack = 0;
+ function toC(value, type) {
+ if (type == 'string') {
+ if (value === null || value === undefined || value === 0) return 0; // null string
+ if (!stack) stack = Runtime.stackSave();
+ var ret = Runtime.stackAlloc(value.length+1);
+ writeStringToMemory(value, ret);
+ return ret;
+ } else if (type == 'array') {
+ if (!stack) stack = Runtime.stackSave();
+ var ret = Runtime.stackAlloc(value.length);
+ writeArrayToMemory(value, ret);
+ return ret;
+ }
+ return value;
+ }
+ function fromC(value, type) {
+ if (type == 'string') {
+ return Pointer_stringify(value);
+ }
+ assert(type != 'array');
+ return value;
+ }
+ try {
+ var func = eval('_' + ident);
+ } catch(e) {
+ try {
+ func = globalScope['Module']['_' + ident]; // closure exported function
+ } catch(e) {}
+ }
+ assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)');
+ var i = 0;
+ var cArgs = args ? args.map(function(arg) {
+ return toC(arg, argTypes[i++]);
+ }) : [];
+ var ret = fromC(func.apply(null, cArgs), returnType);
+ if (stack) Runtime.stackRestore(stack);
+ return ret;
+}
+Module["ccall"] = ccall;
+
+// Returns a native JS wrapper for a C function. This is similar to ccall, but
+// returns a function you can call repeatedly in a normal way. For example:
+//
+// var my_function = cwrap('my_c_function', 'number', ['number', 'number']);
+// alert(my_function(5, 22));
+// alert(my_function(99, 12));
+//
+function cwrap(ident, returnType, argTypes) {
+ // TODO: optimize this, eval the whole function once instead of going through ccall each time
+ return function() {
+ return ccall(ident, returnType, argTypes, Array.prototype.slice.call(arguments));
+ }
+}
+Module["cwrap"] = cwrap;
+
+// Sets a value in memory in a dynamic way at run-time. Uses the
+// type data. This is the same as makeSetValue, except that
+// makeSetValue is done at compile-time and generates the needed
+// code then, whereas this function picks the right code at
+// run-time.
+// Note that setValue and getValue only do *aligned* writes and reads!
+// Note that ccall uses JS types as for defining types, while setValue and
+// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation
+function setValue(ptr, value, type, noSafe) {
+ type = type || 'i8';
+ if (type[type.length-1] === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': HEAP8[(ptr)]=value; break;
+ case 'i8': HEAP8[(ptr)]=value; break;
+ case 'i16': HEAP16[((ptr)>>1)]=value; break;
+ case 'i32': HEAP32[((ptr)>>2)]=value; break;
+ case 'i64': HEAP32[((ptr)>>2)]=value; break;
+ case 'float': HEAPF32[((ptr)>>2)]=value; break;
+ case 'double': (tempDoubleF64[0]=value,HEAP32[((ptr)>>2)]=tempDoubleI32[0],HEAP32[(((ptr)+(4))>>2)]=tempDoubleI32[1]); break;
+ default: abort('invalid type for setValue: ' + type);
+ }
+}
+Module['setValue'] = setValue;
+
+// Parallel to setValue.
+function getValue(ptr, type, noSafe) {
+ type = type || 'i8';
+ if (type[type.length-1] === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': return HEAP8[(ptr)];
+ case 'i8': return HEAP8[(ptr)];
+ case 'i16': return HEAP16[((ptr)>>1)];
+ case 'i32': return HEAP32[((ptr)>>2)];
+ case 'i64': return HEAP32[((ptr)>>2)];
+ case 'float': return HEAPF32[((ptr)>>2)];
+ case 'double': return (tempDoubleI32[0]=HEAP32[((ptr)>>2)],tempDoubleI32[1]=HEAP32[(((ptr)+(4))>>2)],tempDoubleF64[0]);
+ default: abort('invalid type for setValue: ' + type);
+ }
+ return null;
+}
+Module['getValue'] = getValue;
+
+// Allocates memory for some data and initializes it properly.
+
+var ALLOC_NORMAL = 0; // Tries to use _malloc()
+var ALLOC_STACK = 1; // Lives for the duration of the current function call
+var ALLOC_STATIC = 2; // Cannot be freed
+Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
+Module['ALLOC_STACK'] = ALLOC_STACK;
+Module['ALLOC_STATIC'] = ALLOC_STATIC;
+
+function allocate(slab, types, allocator) {
+ var zeroinit, size;
+ if (typeof slab === 'number') {
+ zeroinit = true;
+ size = slab;
+ } else {
+ zeroinit = false;
+ size = slab.length;
+ }
+
+ var singleType = typeof types === 'string' ? types : null;
+
+ var ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
+
+ if (zeroinit) {
+ _memset(ret, 0, size);
+ return ret;
+ }
+
+ var i = 0, type;
+ while (i < size) {
+ var curr = slab[i];
+
+ if (typeof curr === 'function') {
+ curr = Runtime.getFunctionIndex(curr);
+ }
+
+ type = singleType || types[i];
+ if (type === 0) {
+ i++;
+ continue;
+ }
+ assert(type, 'Must know what type to store in allocate!');
+
+ if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
+
+ setValue(ret+i, curr, type);
+ i += Runtime.getNativeTypeSize(type);
+ }
+
+ return ret;
+}
+Module['allocate'] = allocate;
+
+function Pointer_stringify(ptr, /* optional */ length) {
+ var utf8 = new Runtime.UTF8Processor();
+ var nullTerminated = typeof(length) == "undefined";
+ var ret = "";
+ var i = 0;
+ var t;
+ while (1) {
+ t = HEAPU8[((ptr)+(i))];
+ if (nullTerminated && t == 0) break;
+ ret += utf8.processCChar(t);
+ i += 1;
+ if (!nullTerminated && i == length) break;
+ }
+ return ret;
+}
+Module['Pointer_stringify'] = Pointer_stringify;
+
+function Array_stringify(array) {
+ var ret = "";
+ for (var i = 0; i < array.length; i++) {
+ ret += String.fromCharCode(array[i]);
+ }
+ return ret;
+}
+Module['Array_stringify'] = Array_stringify;
+
+// Memory management
+
+var FUNCTION_TABLE; // XXX: In theory the indexes here can be equal to pointers to stacked or malloced memory. Such comparisons should
+ // be false, but can turn out true. We should probably set the top bit to prevent such issues.
+
+var PAGE_SIZE = 4096;
+function alignMemoryPage(x) {
+ return ((x+4095)>>12)<<12;
+}
+
+var HEAP;
+var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
+
+var STACK_ROOT, STACKTOP, STACK_MAX;
+var STATICTOP;
+function enlargeMemory() {
+ // TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top.
+ Module.printErr('Warning: Enlarging memory arrays, this is not fast! ' + [STATICTOP, TOTAL_MEMORY]);
+ assert(STATICTOP >= TOTAL_MEMORY);
+ assert(TOTAL_MEMORY > 4); // So the loop below will not be infinite
+ while (TOTAL_MEMORY <= STATICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it
+ TOTAL_MEMORY = alignMemoryPage(2*TOTAL_MEMORY);
+ }
+ var oldHEAP8 = HEAP8;
+ var buffer = new ArrayBuffer(TOTAL_MEMORY);
+ HEAP8 = new Int8Array(buffer);
+ HEAP16 = new Int16Array(buffer);
+ HEAP32 = new Int32Array(buffer);
+ HEAPU8 = new Uint8Array(buffer);
+ HEAPU16 = new Uint16Array(buffer);
+ HEAPU32 = new Uint32Array(buffer);
+ HEAPF32 = new Float32Array(buffer);
+ HEAPF64 = new Float64Array(buffer);
+ HEAP8.set(oldHEAP8);
+}
+
+var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880;
+var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 10485760;
+var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152;
+
+// Initialize the runtime's memory
+// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
+ assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
+ 'Cannot fallback to non-typed array case: Code is too specialized');
+
+ var buffer = new ArrayBuffer(TOTAL_MEMORY);
+ HEAP8 = new Int8Array(buffer);
+ HEAP16 = new Int16Array(buffer);
+ HEAP32 = new Int32Array(buffer);
+ HEAPU8 = new Uint8Array(buffer);
+ HEAPU16 = new Uint16Array(buffer);
+ HEAPU32 = new Uint32Array(buffer);
+ HEAPF32 = new Float32Array(buffer);
+ HEAPF64 = new Float64Array(buffer);
+
+ // Endianness check (note: assumes compiler arch was little-endian)
+ HEAP32[0] = 255;
+ assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
+
+var base = intArrayFromString('(null)'); // So printing %s of NULL gives '(null)'
+ // Also this ensures we leave 0 as an invalid address, 'NULL'
+STATICTOP = base.length;
+for (var i = 0; i < base.length; i++) {
+ HEAP8[(i)]=base[i]
+}
+
+Module['HEAP'] = HEAP;
+Module['HEAP8'] = HEAP8;
+Module['HEAP16'] = HEAP16;
+Module['HEAP32'] = HEAP32;
+Module['HEAPU8'] = HEAPU8;
+Module['HEAPU16'] = HEAPU16;
+Module['HEAPU32'] = HEAPU32;
+Module['HEAPF32'] = HEAPF32;
+Module['HEAPF64'] = HEAPF64;
+
+STACK_ROOT = STACKTOP = Runtime.alignMemory(STATICTOP);
+STACK_MAX = STACK_ROOT + TOTAL_STACK;
+
+var tempDoublePtr = Runtime.alignMemory(STACK_MAX, 8);
+var tempDoubleI8 = HEAP8.subarray(tempDoublePtr);
+var tempDoubleI32 = HEAP32.subarray(tempDoublePtr >> 2);
+var tempDoubleF32 = HEAPF32.subarray(tempDoublePtr >> 2);
+var tempDoubleF64 = HEAPF64.subarray(tempDoublePtr >> 3);
+function copyTempFloat(ptr) { // functions, because inlining this code is increases code size too much
+ tempDoubleI8[0] = HEAP8[ptr];
+ tempDoubleI8[1] = HEAP8[ptr+1];
+ tempDoubleI8[2] = HEAP8[ptr+2];
+ tempDoubleI8[3] = HEAP8[ptr+3];
+}
+function copyTempDouble(ptr) {
+ tempDoubleI8[0] = HEAP8[ptr];
+ tempDoubleI8[1] = HEAP8[ptr+1];
+ tempDoubleI8[2] = HEAP8[ptr+2];
+ tempDoubleI8[3] = HEAP8[ptr+3];
+ tempDoubleI8[4] = HEAP8[ptr+4];
+ tempDoubleI8[5] = HEAP8[ptr+5];
+ tempDoubleI8[6] = HEAP8[ptr+6];
+ tempDoubleI8[7] = HEAP8[ptr+7];
+}
+STACK_MAX = tempDoublePtr + 8;
+
+STATICTOP = alignMemoryPage(STACK_MAX);
+
+function callRuntimeCallbacks(callbacks) {
+ while(callbacks.length > 0) {
+ var callback = callbacks.shift();
+ var func = callback.func;
+ if (typeof func === 'number') {
+ func = FUNCTION_TABLE[func];
+ }
+ func(callback.arg === undefined ? null : callback.arg);
+ }
+}
+
+var __ATINIT__ = []; // functions called during startup
+var __ATMAIN__ = []; // functions called when main() is to be run
+var __ATEXIT__ = []; // functions called during shutdown
+
+function initRuntime() {
+ callRuntimeCallbacks(__ATINIT__);
+}
+function preMain() {
+ callRuntimeCallbacks(__ATMAIN__);
+}
+function exitRuntime() {
+ callRuntimeCallbacks(__ATEXIT__);
+
+ // Print summary of correction activity
+ CorrectionsMonitor.print();
+}
+
+function String_len(ptr) {
+ var i = 0;
+ while (HEAP8[((ptr)+(i))]) i++; // Note: should be |!= 0|, technically. But this helps catch bugs with undefineds
+ return i;
+}
+Module['String_len'] = String_len;
+
+// Tools
+
+// This processes a JS string into a C-line array of numbers, 0-terminated.
+// For LLVM-originating strings, see parser.js:parseLLVMString function
+function intArrayFromString(stringy, dontAddNull, length /* optional */) {
+ var ret = (new Runtime.UTF8Processor()).processJSString(stringy);
+ if (length) {
+ ret.length = length;
+ }
+ if (!dontAddNull) {
+ ret.push(0);
+ }
+ return ret;
+}
+Module['intArrayFromString'] = intArrayFromString;
+
+function intArrayToString(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+ var chr = array[i];
+ if (chr > 0xFF) {
+ assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
+ chr &= 0xFF;
+ }
+ ret.push(String.fromCharCode(chr));
+ }
+ return ret.join('');
+}
+Module['intArrayToString'] = intArrayToString;
+
+// Write a Javascript array to somewhere in the heap
+function writeStringToMemory(string, buffer, dontAddNull) {
+ var array = intArrayFromString(string, dontAddNull);
+ var i = 0;
+ while (i < array.length) {
+ var chr = array[i];
+ HEAP8[((buffer)+(i))]=chr
+ i = i + 1;
+ }
+}
+Module['writeStringToMemory'] = writeStringToMemory;
+
+function writeArrayToMemory(array, buffer) {
+ for (var i = 0; i < array.length; i++) {
+ HEAP8[((buffer)+(i))]=array[i];
+ }
+}
+Module['writeArrayToMemory'] = writeArrayToMemory;
+
+var STRING_TABLE = [];
+
+function unSign(value, bits, ignore, sig) {
+ if (value >= 0) {
+ return value;
+ }
+ return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
+ : Math.pow(2, bits) + value;
+ // TODO: clean up previous line
+}
+function reSign(value, bits, ignore, sig) {
+ if (value <= 0) {
+ return value;
+ }
+ var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
+ : Math.pow(2, bits-1);
+ if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that
+ // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
+ // TODO: In i64 mode 1, resign the two parts separately and safely
+ value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
+ }
+ return value;
+}
+
+// A counter of dependencies for calling run(). If we need to
+// do asynchronous work before running, increment this and
+// decrement it. Incrementing must happen in a place like
+// PRE_RUN_ADDITIONS (used by emcc to add file preloading).
+// Note that you can add dependencies in preRun, even though
+// it happens right before run - run will be postponed until
+// the dependencies are met.
+var runDependencies = 0;
+function addRunDependency() {
+ runDependencies++;
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+}
+Module['addRunDependency'] = addRunDependency;
+function removeRunDependency() {
+ runDependencies--;
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+ if (runDependencies == 0) run();
+}
+Module['removeRunDependency'] = removeRunDependency;
+
+// === Body ===
+
+
+
+
+function ____init___0($self, $initx, $inity, $initz) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_70=(($self+4)|0);
+ (tempDoubleF64[0]=$initx,HEAP32[(($_tmp_70)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_70)+(4))>>2)]=tempDoubleI32[1]);
+ var $_tmp_71=(($self+20)|0);
+ (tempDoubleF64[0]=$inity,HEAP32[(($_tmp_71)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_71)+(4))>>2)]=tempDoubleI32[1]);
+ var $_tmp_72=(($self+12)|0);
+ (tempDoubleF64[0]=$initz,HEAP32[(($_tmp_72)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_72)+(4))>>2)]=tempDoubleI32[1]);
+ __label__ = 5; break;
+ case 5:
+ ;
+ return;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function ____init___1($self, $initx, $inity, $initz) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_218=(($self+4)|0);
+ (tempDoubleF64[0]=$initx,HEAP32[(($_tmp_218)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_218)+(4))>>2)]=tempDoubleI32[1]);
+ var $_tmp_219=(($self+20)|0);
+ (tempDoubleF64[0]=$inity,HEAP32[(($_tmp_219)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_219)+(4))>>2)]=tempDoubleI32[1]);
+ var $_tmp_220=(($self+12)|0);
+ (tempDoubleF64[0]=$initz,HEAP32[(($_tmp_220)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_220)+(4))>>2)]=tempDoubleI32[1]);
+ __label__ = 5; break;
+ case 5:
+ ;
+ return;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function _main($argc, $argv) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ var $call1=_SDL_Init(32);
+ var $w=HEAP32[((_MYW)>>2)];
+ var $h=HEAP32[((_MYH)>>2)];
+ var $call2=_SDL_SetVideoMode(2 * $w, 2 * $h, 32, 0);
+ HEAP32[((_screen)>>2)]=$call2;
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_8=((_global_closure+4)|0);
+ (tempDoubleF64[0]=0.00001,HEAP32[(($_tmp_8)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_8)+(4))>>2)]=tempDoubleI32[1]);
+ var $_tmp_9=((_global_closure+12)|0);
+ (tempDoubleF64[0]=1000000000,HEAP32[(($_tmp_9)>>2)]=tempDoubleI32[0],HEAP32[((($_tmp_9)+(4))>>2)]=tempDoubleI32[1]);
+ var $_tmp_10=_cls1_init();
+ var $_tmp_11=0;
+ var $_tmp_12=0;
+ var $_tmp_13=0;
+ ____init___0($_tmp_10, $_tmp_11, $_tmp_12, $_tmp_13);
+ var $_tmp_14=_cls1_init();
+ var $_tmp_15=1;
+ var $_tmp_16=0;
+ var $_tmp_17=0;
+ ____init___0($_tmp_14, $_tmp_15, $_tmp_16, $_tmp_17);
+ var $_tmp_18=_cls1_init();
+ var $_tmp_19=0;
+ var $_tmp_20=1;
+ var $_tmp_21=0;
+ ____init___0($_tmp_18, $_tmp_19, $_tmp_20, $_tmp_21);
+ var $_tmp_22=((_global_closure+24)|0);
+ HEAP32[(($_tmp_22)>>2)]=$_tmp_18;
+ _cls1_incref($_tmp_18);
+ var $_tmp_23=_cls1_init();
+ var $_tmp_24=0;
+ var $_tmp_25=0;
+ var $_tmp_26=1;
+ ____init___0($_tmp_23, $_tmp_24, $_tmp_25, $_tmp_26);
+ var $_tmp_27=__reflectThrough_0($_tmp_14, $_tmp_18);
+ var $_tmp_28=____eq___0($_tmp_27, $_tmp_14);
+ _cls1_decref($_tmp_27);
+ var $_tmp_29=_bool_nonzero($_tmp_28);
+ var $_tmp_30=$_tmp_29 ^ 1;
+ var $_tmp_31=_bool_nonzero($_tmp_30);
+ _cls1_decref($_tmp_23);
+ _cls1_decref($_tmp_10);
+ _cls1_decref($_tmp_14);
+ if ($_tmp_31) { __label__ = 5; break; } else { __label__ = 6; break; }
+ case 5:
+ __label__ = 7; break;
+ case 6:
+ __label__ = 8; break;
+ case 7:
+ var $_tmp_32=_int_div(1, 0);
+ var $_tmp_33=_int_str($_tmp_32);
+ var $_tmp_34=_str_buf($_tmp_33);
+ var $_tmp_35=_str_len($_tmp_33);
+ var $tmp4_0=((STRING_TABLE._str_0)|0);
+ var $0=_printf($tmp4_0, (tempInt=STACKTOP,STACKTOP += 8,assert(STACKTOP < STACK_ROOT + STACK_MAX, "Ran out of stack"),HEAP32[((tempInt)>>2)]=$_tmp_35,HEAP32[(((tempInt)+(4))>>2)]=$_tmp_34,tempInt));
+ _str_decref($_tmp_33);
+ __label__ = 8; break;
+ case 8:
+ var $_tmp_36=_cls1_init();
+ var $_tmp_37=-1;
+ var $_tmp_38=-1;
+ var $_tmp_39=0;
+ ____init___0($_tmp_36, $_tmp_37, $_tmp_38, $_tmp_39);
+ var $_tmp_40=__reflectThrough_0($_tmp_36, $_tmp_18);
+ _cls1_decref($_tmp_36);
+ var $_tmp_41=_cls1_init();
+ var $_tmp_42=-1;
+ var $_tmp_43=1;
+ var $_tmp_44=0;
+ ____init___0($_tmp_41, $_tmp_42, $_tmp_43, $_tmp_44);
+ var $_tmp_45=____eq___0($_tmp_40, $_tmp_41);
+ _cls1_decref($_tmp_40);
+ _cls1_decref($_tmp_41);
+ var $_tmp_46=_bool_nonzero($_tmp_45);
+ var $_tmp_47=$_tmp_46 ^ 1;
+ var $_tmp_48=_bool_nonzero($_tmp_47);
+ _cls1_decref($_tmp_18);
+ if ($_tmp_48) { __label__ = 9; break; } else { __label__ = 10; break; }
+ case 9:
+ __label__ = 11; break;
+ case 10:
+ __label__ = 12; break;
+ case 11:
+ var $_tmp_49=_int_div(1, 0);
+ var $_tmp_50=_int_str($_tmp_49);
+ var $_tmp_51=_str_buf($_tmp_50);
+ var $_tmp_52=_str_len($_tmp_50);
+ var $tmp8_0=((STRING_TABLE._str_0)|0);
+ var $1=_printf($tmp8_0, (tempInt=STACKTOP,STACKTOP += 8,assert(STACKTOP < STACK_ROOT + STACK_MAX, "Ran out of stack"),HEAP32[((tempInt)>>2)]=$_tmp_52,HEAP32[(((tempInt)+(4))>>2)]=$_tmp_51,tempInt));
+ _str_decref($_tmp_50);
+ __label__ = 12; break;
+ case 12:
+ var $_tmp_53=_cls0_init();
+ var $_tmp_54=0;
+ var $_tmp_55=0;
+ var $_tmp_56=0;
+ ____init___1($_tmp_53, $_tmp_54, $_tmp_55, $_tmp_56);
+ var $_tmp_57=((_global_closure+20)|0);
+ HEAP32[(($_tmp_57)>>2)]=$_tmp_53;
+ _cls0_incref($_tmp_53);
+ var $_tmp_58=_cls1_init();
+ var $_tmp_59=3;
+ var $_tmp_60=4;
+ var $_tmp_61=12;
+ ____init___0($_tmp_58, $_tmp_59, $_tmp_60, $_tmp_61);
+ var $_tmp_62=_cls1_init();
+ var $_tmp_63=1;
+ var $_tmp_64=1;
+ var $_tmp_65=1;
+ ____init___0($_tmp_62, $_tmp_63, $_tmp_64, $_tmp_65);
+ __main_0();
+ _cls1_decref($_tmp_58);
+ _cls0_decref($_tmp_53);
+ _cls1_decref($_tmp_62);
+ __label__ = 13; break;
+ case 13:
+ var $_tmp_68=HEAP32[((((_global_closure+20)|0))>>2)];
+ _cls0_decref($_tmp_68);
+ var $_tmp_69=HEAP32[((((_global_closure+24)|0))>>2)];
+ _cls1_decref($_tmp_69);
+ _teardown_runtime();
+ ;
+ return 0;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+Module["_main"] = _main;_main["X"]=1;
+
+function __magnitude_0($self) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_97=__dot_0($self, $self);
+ var $_tmp_98=_math_sqrt($_tmp_97);
+ ;
+ return $_tmp_98;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function ____add___0($self, $other) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_99=(($self+4)|0);
+ var $_tmp_100=(tempDoubleI32[0]=HEAP32[(($_tmp_99)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_99)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_101=(($other+4)|0);
+ var $_tmp_102=(tempDoubleI32[0]=HEAP32[(($_tmp_101)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_101)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_103=_float_add($_tmp_100, $_tmp_102);
+ var $_tmp_104=(($self+20)|0);
+ var $_tmp_105=(tempDoubleI32[0]=HEAP32[(($_tmp_104)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_104)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_106=(($other+20)|0);
+ var $_tmp_107=(tempDoubleI32[0]=HEAP32[(($_tmp_106)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_106)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_108=_float_add($_tmp_105, $_tmp_107);
+ var $_tmp_109=(($self+12)|0);
+ var $_tmp_110=(tempDoubleI32[0]=HEAP32[(($_tmp_109)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_109)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_111=(($other+12)|0);
+ var $_tmp_112=(tempDoubleI32[0]=HEAP32[(($_tmp_111)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_111)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_113=_float_add($_tmp_110, $_tmp_112);
+ var $_tmp_114=_cls1_init();
+ ____init___0($_tmp_114, $_tmp_103, $_tmp_108, $_tmp_113);
+ ;
+ return $_tmp_114;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function ____sub___0($self, $other) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_115=(($self+4)|0);
+ var $_tmp_116=(tempDoubleI32[0]=HEAP32[(($_tmp_115)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_115)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_117=(($other+4)|0);
+ var $_tmp_118=(tempDoubleI32[0]=HEAP32[(($_tmp_117)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_117)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_119=_float_sub($_tmp_116, $_tmp_118);
+ var $_tmp_120=(($self+20)|0);
+ var $_tmp_121=(tempDoubleI32[0]=HEAP32[(($_tmp_120)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_120)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_122=(($other+20)|0);
+ var $_tmp_123=(tempDoubleI32[0]=HEAP32[(($_tmp_122)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_122)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_124=_float_sub($_tmp_121, $_tmp_123);
+ var $_tmp_125=(($self+12)|0);
+ var $_tmp_126=(tempDoubleI32[0]=HEAP32[(($_tmp_125)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_125)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_127=(($other+12)|0);
+ var $_tmp_128=(tempDoubleI32[0]=HEAP32[(($_tmp_127)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_127)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_129=_float_sub($_tmp_126, $_tmp_128);
+ var $_tmp_130=_cls1_init();
+ ____init___0($_tmp_130, $_tmp_119, $_tmp_124, $_tmp_129);
+ ;
+ return $_tmp_130;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function __scale_0($self, $factor) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_131=(($self+4)|0);
+ var $_tmp_132=(tempDoubleI32[0]=HEAP32[(($_tmp_131)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_131)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_133=_float_mul($factor, $_tmp_132);
+ var $_tmp_134=(($self+20)|0);
+ var $_tmp_135=(tempDoubleI32[0]=HEAP32[(($_tmp_134)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_134)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_136=_float_mul($factor, $_tmp_135);
+ var $_tmp_137=(($self+12)|0);
+ var $_tmp_138=(tempDoubleI32[0]=HEAP32[(($_tmp_137)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_137)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_139=_float_mul($factor, $_tmp_138);
+ var $_tmp_140=_cls1_init();
+ ____init___0($_tmp_140, $_tmp_133, $_tmp_136, $_tmp_139);
+ ;
+ return $_tmp_140;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function __dot_0($self, $other) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_141=(($self+4)|0);
+ var $_tmp_142=(tempDoubleI32[0]=HEAP32[(($_tmp_141)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_141)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_143=(($other+4)|0);
+ var $_tmp_144=(tempDoubleI32[0]=HEAP32[(($_tmp_143)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_143)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_145=_float_mul($_tmp_142, $_tmp_144);
+ var $_tmp_146=(($self+20)|0);
+ var $_tmp_147=(tempDoubleI32[0]=HEAP32[(($_tmp_146)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_146)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_148=(($other+20)|0);
+ var $_tmp_149=(tempDoubleI32[0]=HEAP32[(($_tmp_148)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_148)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_150=_float_mul($_tmp_147, $_tmp_149);
+ var $_tmp_151=_float_add($_tmp_145, $_tmp_150);
+ var $_tmp_152=(($self+12)|0);
+ var $_tmp_153=(tempDoubleI32[0]=HEAP32[(($_tmp_152)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_152)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_154=(($other+12)|0);
+ var $_tmp_155=(tempDoubleI32[0]=HEAP32[(($_tmp_154)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_154)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_156=_float_mul($_tmp_153, $_tmp_155);
+ var $_tmp_157=_float_add($_tmp_151, $_tmp_156);
+ ;
+ return $_tmp_157;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function __cross_0($self, $other) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
+ var $_tmp_158=(($self+20)|0);
+ var $_tmp_159=(tempDoubleI32[0]=HEAP32[(($_tmp_158)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_158)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_160=(($other+12)|0);
+ var $_tmp_161=(tempDoubleI32[0]=HEAP32[(($_tmp_160)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_160)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_162=_float_mul($_tmp_159, $_tmp_161);
+ var $_tmp_163=(($self+12)|0);
+ var $_tmp_164=(tempDoubleI32[0]=HEAP32[(($_tmp_163)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_163)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_165=(($other+20)|0);
+ var $_tmp_166=(tempDoubleI32[0]=HEAP32[(($_tmp_165)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_165)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_167=_float_mul($_tmp_164, $_tmp_166);
+ var $_tmp_168=_float_sub($_tmp_162, $_tmp_167);
+ var $_tmp_169=(($self+12)|0);
+ var $_tmp_170=(tempDoubleI32[0]=HEAP32[(($_tmp_169)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_169)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_171=(($other+4)|0);
+ var $_tmp_172=(tempDoubleI32[0]=HEAP32[(($_tmp_171)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_171)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_173=_float_mul($_tmp_170, $_tmp_172);
+ var $_tmp_174=(($self+4)|0);
+ var $_tmp_175=(tempDoubleI32[0]=HEAP32[(($_tmp_174)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_174)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_176=(($other+12)|0);
+ var $_tmp_177=(tempDoubleI32[0]=HEAP32[(($_tmp_176)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_176)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_178=_float_mul($_tmp_175, $_tmp_177);
+ var $_tmp_179=_float_sub($_tmp_173, $_tmp_178);
+ var $_tmp_180=(($self+4)|0);
+ var $_tmp_181=(tempDoubleI32[0]=HEAP32[(($_tmp_180)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_180)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_182=(($other+20)|0);
+ var $_tmp_183=(tempDoubleI32[0]=HEAP32[(($_tmp_182)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_182)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_184=_float_mul($_tmp_181, $_tmp_183);
+ var $_tmp_185=(($self+20)|0);
+ var $_tmp_186=(tempDoubleI32[0]=HEAP32[(($_tmp_185)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_185)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_187=(($other+4)|0);
+ var $_tmp_188=(tempDoubleI32[0]=HEAP32[(($_tmp_187)>>2)],tempDoubleI32[1]=HEAP32[((($_tmp_187)+(4))>>2)],tempDoubleF64[0]);
+ var $_tmp_189=_float_mul($_tmp_186, $_tmp_188);
+ var $_tmp_190=_float_sub($_tmp_184, $_tmp_189);
+ var $_tmp_191=_cls1_init();
+ ____init___0($_tmp_191, $_tmp_168, $_tmp_179, $_tmp_190);
+ ;
+ return $_tmp_191;
+ default: assert(0, "bad label: " + __label__);
+ }
+}
+
+
+function __normalized_0($self) {
+ ;
+ var __label__;
+ __label__ = 2;
+ while(1) switch(__label__) {
+ case 2:
+ __label__ = 3; break;
+ case 3:
+ __label__ = 4; break;
+ case 4:
More information about the pypy-commit
mailing list