Reworked the examples to be more welcoming
This commit is contained in:
parent
3cb4860973
commit
8a1a6af3e7
@ -1,51 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Examples - Buffer</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Buffer</h1>
|
|
||||||
|
|
||||||
<a href="index.html">List</a> - <a href="buffer.py.html">Source</a> - <a href="buffer.wat.html">WebAssembly</a>
|
|
||||||
|
|
||||||
<div style="white-space: pre;" id="results"></div>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="./include.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
let importObject = {};
|
|
||||||
|
|
||||||
// Run a single test
|
|
||||||
function run_test(app, str)
|
|
||||||
{
|
|
||||||
let offset = alloc_bytes(app, str);
|
|
||||||
|
|
||||||
let js_chars = [];
|
|
||||||
let wasm_chars = [];
|
|
||||||
for(let idx = 0; idx < str.length; ++idx) {
|
|
||||||
js_chars.push(str.charCodeAt(idx));
|
|
||||||
wasm_chars.push(app.instance.exports.index(offset, idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = js_chars.every(function(value, index) { return value === wasm_chars[index]})
|
|
||||||
|
|
||||||
test_result(result, {
|
|
||||||
'summary': 'js_chars == wasm_chars, for "' + str + '"',
|
|
||||||
'attributes': {
|
|
||||||
'js_chars': js_chars,
|
|
||||||
'wasm_chars': wasm_chars,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
WebAssembly.instantiateStreaming(fetch('buffer.wasm'), importObject)
|
|
||||||
.then(app => {
|
|
||||||
run_test(app, '');
|
|
||||||
run_test(app, 'a');
|
|
||||||
run_test(app, 'Hello');
|
|
||||||
run_test(app, 'The quick brown fox jumps over the lazy dog');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
@exported
|
|
||||||
def index(inp: bytes, idx: u32) -> u8:
|
|
||||||
return inp[idx]
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def length(inp: bytes) -> u32:
|
|
||||||
return len(inp)
|
|
||||||
@ -2,245 +2,68 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Examples - CRC32</title>
|
<title>Examples - CRC32</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Buffer</h1>
|
<h1>Examples - CRC32</h1>
|
||||||
|
|
||||||
<a href="index.html">List</a> - <a href="crc32.py.html">Source</a> - <a href="crc32.wat.html">WebAssembly</a><br />
|
<div class="menu">
|
||||||
<br />
|
<a href="index.html">List</a> - <a href="crc32.py.html">Source</a> - <a href="crc32.wat.html">WebAssembly</a><br />
|
||||||
Note: This tests performs some timing comparison, please wait a few seconds for the results.<br />
|
</div>
|
||||||
<div style="white-space: pre;" id="results"></div>
|
|
||||||
|
|
||||||
<h2>Measurement log</h2>
|
<div class="description">
|
||||||
<h3>AMD Ryzen 7 3700X 8-Core, Ubuntu 20.04, Linux 5.4.0-124-generic</h3>
|
<p>
|
||||||
<h4>After optimizing fold over bytes by inlineing __subscript_bytes__</h4>
|
This example shows a fold implementation of a <a href="https://en.wikipedia.org/wiki/Cyclic_redundancy_check">cyclic redundancy check</a>.
|
||||||
<table>
|
There are actually many variations of these CRCs - this one is specifically know as CRC-32/ISO-HDLC.
|
||||||
<tr>
|
</p>
|
||||||
<td>Test</td>
|
</div>
|
||||||
<td>Interpreter</td>
|
|
||||||
<td>Setup</td>
|
|
||||||
<td>WebAssembly</td>
|
|
||||||
<td>Javascript</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Chromium 104.0.5112.101</td>
|
|
||||||
<td>DevTools closed</td>
|
|
||||||
<td>5.70</td>
|
|
||||||
<td>12.45</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Firefox 103</td>
|
|
||||||
<td>DevTools closed</td>
|
|
||||||
<td>5.16</td>
|
|
||||||
<td>5.72</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 1048576</td>
|
|
||||||
<td>Chromium 104.0.5112.101</td>
|
|
||||||
<td>DevTools closed</td>
|
|
||||||
<td>95.65</td>
|
|
||||||
<td>203.60</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 1048576</td>
|
|
||||||
<td>Firefox 103</td>
|
|
||||||
<td>DevTools closed</td>
|
|
||||||
<td>83.34</td>
|
|
||||||
<td>92.38</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<h4>Before optimizing fold over bytes by inlineing __subscript_bytes__</h4>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Test</td>
|
|
||||||
<td>Interpreter</td>
|
|
||||||
<td>Setup</td>
|
|
||||||
<td>WebAssembly</td>
|
|
||||||
<td>Javascript</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Chromium 104.0.5112.101</td>
|
|
||||||
<td>DevTools closed</td>
|
|
||||||
<td>9.35</td>
|
|
||||||
<td>12.56</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Chromium 104.0.5112.101</td>
|
|
||||||
<td>DevTools open</td>
|
|
||||||
<td>14.71</td>
|
|
||||||
<td>12.72</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Chromium 104.0.5112.101</td>
|
|
||||||
<td>Record page load</td>
|
|
||||||
<td>9.44</td>
|
|
||||||
<td>12.69</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Firefox 103</td>
|
|
||||||
<td>DevTools closed</td>
|
|
||||||
<td>9.02</td>
|
|
||||||
<td>5.86</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Firefox 103</td>
|
|
||||||
<td>DevTools open</td>
|
|
||||||
<td>9.01</td>
|
|
||||||
<td>5.83</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 65536</td>
|
|
||||||
<td>Firefox 103</td>
|
|
||||||
<td>Record page load</td>
|
|
||||||
<td>72.41</td>
|
|
||||||
<td>5.85</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
<h3>Try it out!</h3>
|
||||||
<td>Lynx * 1048576</td>
|
<div class="example">
|
||||||
<td>Chromium 104.0.5112.101</td>
|
<textarea id="example-data" style="width: 75%; height: 4em;">The quick brown fox jumps over the lazy dog</textarea><br />
|
||||||
<td>DevTools closed</td>
|
<button type="click" id="example-click" disabled>Calculate</button>
|
||||||
<td>149.24</td>
|
<input type="text" id="example-crc32" />
|
||||||
<td>202.36</td>
|
</div>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lynx * 1048576</td>
|
|
||||||
<td>Firefox 103</td>
|
|
||||||
<td>DevTools closed</td>
|
|
||||||
<td>145.01</td>
|
|
||||||
<td>91.44</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h4>Notes</h4>
|
<div class="example-list">
|
||||||
- Firefox seems faster than Chromium in my setup for Javascript, WebAssembly seems about the same.<br />
|
<ul>
|
||||||
- Having DevTools open in Chromium seems to slow down the WebAssembly by about 30%, but not when doing a recording of the page load.<br />
|
<li><a href="#" data-n="123456789">crc32("123456789")</a> = cbf43926</li>
|
||||||
- WebAssembly in Firefox seems to slow down when doing a recording of the page load, which makes sense, but the Javascript does not.<br />
|
<li><a href="#" data-n="Hello, world!">crc32("Hello, world!")</a> = ebe6c6e6</li>
|
||||||
|
<li><a href="#" data-n="The quick brown fox jumps over the lazy dog">crc32("The quick brown fox jumps over the lazy dog")</a> = 414fa339</li>
|
||||||
|
<li><a href="#" data-n="CRC-32/ISO-HDLC
|
||||||
|
Also referred to as ISO 3309, ITU-T V.42, CRC-32-IEEE, and many other names.
|
||||||
|
|
||||||
<script type="text/javascript" src="./include.js"></script>
|
The CRC of ASCII "123456789" is 0xcbf43926.
|
||||||
<script type="text/javascript">
|
|
||||||
let importObject = {};
|
|
||||||
|
|
||||||
// Build up a JS version
|
Examples of formats that use CRC-32/ISO-HDLC: ZIP, PNG, Gzip, ARJ.">crc32("CRC-32/ISO-HDLC...")</a> = 126afcf</li>
|
||||||
var makeCRCTable = function(){
|
</ul>
|
||||||
var c;
|
</div>
|
||||||
var crcTable = [];
|
|
||||||
for(var n =0; n < 256; n++){
|
<!-- We'll need to use some interface glue - WebAssembly doesn't let us pass strings directly. -->
|
||||||
c = n;
|
<script type="text/javascript" src="./include.js"></script>
|
||||||
for(var k =0; k < 8; k++){
|
<script>
|
||||||
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
|
let importObject = {};
|
||||||
}
|
let exampleN = document.querySelector('#example-data');
|
||||||
crcTable[n] = c;
|
let exampleClick = document.querySelector('#example-click');
|
||||||
|
let exampleCrc32 = document.querySelector('#example-crc32');
|
||||||
|
|
||||||
|
WebAssembly.instantiateStreaming(fetch('crc32.wasm'), importObject)
|
||||||
|
.then(app => {
|
||||||
|
exampleClick.addEventListener('click', event => {
|
||||||
|
let in_put = exampleN.value;
|
||||||
|
let in_put_addr = alloc_bytes(app, in_put);
|
||||||
|
let result = app.instance.exports.crc32(in_put_addr);
|
||||||
|
exampleCrc32.value = i32_to_u32(result).toString(16);
|
||||||
|
});
|
||||||
|
exampleClick.removeAttribute('disabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
for(let exmpl of document.querySelectorAll('a[data-n]') ) {
|
||||||
|
exmpl.addEventListener('click', event => {
|
||||||
|
exampleN.value = exmpl.getAttribute('data-n');
|
||||||
|
exampleClick.click();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return crcTable;
|
</script>
|
||||||
}
|
|
||||||
|
|
||||||
window.crcTable = makeCRCTable();
|
|
||||||
|
|
||||||
var crc32_js = function(i8arr) {
|
|
||||||
// console.log('crc32_js', i8arr.length);
|
|
||||||
|
|
||||||
var crcTable = window.crcTable;
|
|
||||||
var crc = 0 ^ (-1);
|
|
||||||
|
|
||||||
for (var i = 0; i < i8arr.length; i++ ) {
|
|
||||||
crc = (crc >>> 8) ^ crcTable[(crc ^ i8arr[i]) & 0xFF];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (crc ^ (-1)) >>> 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run a single test
|
|
||||||
function run_test(app, str, str_repeat)
|
|
||||||
{
|
|
||||||
// Cast to Uint32 in Javascript
|
|
||||||
let crc32_wasm = function(offset) {
|
|
||||||
// console.log('crc32_wasm', str.length);
|
|
||||||
return app.instance.exports.crc32(offset) >>> 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
let orig_str = str;
|
|
||||||
if( str_repeat ) {
|
|
||||||
str = str.repeat(str_repeat);
|
|
||||||
} else {
|
|
||||||
str_repeat = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = Uint8Array.from(str.split('').map(x => x.charCodeAt()));
|
|
||||||
|
|
||||||
offset = alloc_bytes(app, data);
|
|
||||||
|
|
||||||
let tweak = () => {
|
|
||||||
data[0] = data[0] + 1;
|
|
||||||
|
|
||||||
let i8arr = new Uint8Array(app.instance.exports.memory.buffer, offset + 4, data.length);
|
|
||||||
i8arr[0] = i8arr[0] + 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
let tweak_reset = () => {
|
|
||||||
data[0] = 'T'.charCodeAt(0);
|
|
||||||
|
|
||||||
let i8arr = new Uint8Array(app.instance.exports.memory.buffer, offset + 4, data.length);
|
|
||||||
i8arr[0] = 'T'.charCodeAt(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run once to get the result
|
|
||||||
// For some reason, the JS version takes 2ms on the first run
|
|
||||||
// let wasm_result = crc32_wasm(offset);
|
|
||||||
// let js_result = crc32_js(data);
|
|
||||||
|
|
||||||
let wasm_timing = run_times(100, () => crc32_wasm(offset));
|
|
||||||
let js_timing = run_times(100, () => crc32_js(data));
|
|
||||||
|
|
||||||
let wasm_time = wasm_timing.avg;
|
|
||||||
let js_time = js_timing.avg;
|
|
||||||
|
|
||||||
let check = wasm_timing.values.every(function(value, index) {
|
|
||||||
return value.result === js_timing.values[index].result;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Don't test speedup for small strings, it varies a lot
|
|
||||||
let speedup = (wasm_timing.min == 0 || js_timing.min == 0)
|
|
||||||
? 1
|
|
||||||
: js_time / wasm_time;
|
|
||||||
|
|
||||||
test_result(check && 0.999 < speedup, { // At least as fast as Javascript
|
|
||||||
'summary': 'crc32(' + (str
|
|
||||||
? (str.length < 64 ? '"' + str + '"' : '"' + str.substring(0, 64) + '..." (' + str.length + ')')
|
|
||||||
: '""') + ')',
|
|
||||||
'attributes': {
|
|
||||||
'str': orig_str,
|
|
||||||
'str_repeat': str_repeat,
|
|
||||||
'wasm_timing': wasm_timing,
|
|
||||||
'js_timing': js_timing,
|
|
||||||
'check': check,
|
|
||||||
'speedup': speedup,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load WebAssembly, and run all tests
|
|
||||||
WebAssembly.instantiateStreaming(fetch('crc32.wasm'), importObject)
|
|
||||||
.then(app => {
|
|
||||||
app.instance.exports.memory.grow(640);
|
|
||||||
|
|
||||||
run_test(app, "");
|
|
||||||
run_test(app, "a");
|
|
||||||
run_test(app, "Z");
|
|
||||||
run_test(app, "ab");
|
|
||||||
run_test(app, "abcdefghijklmnopqrstuvwxyz");
|
|
||||||
run_test(app, "The quick brown fox jumps over the lazy dog");
|
|
||||||
run_test(app, "The quick brown fox jumps over the lazy dog", 1024);
|
|
||||||
run_test(app, "Lynx c.q. vos prikt bh: dag zwemjuf!", 65536);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,55 +1,62 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Examples - Fibonacci</title>
|
<title>Examples - Fibonacci</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Fibonacci</h1>
|
<h1>Examples - Fibonacci</h1>
|
||||||
|
|
||||||
<a href="index.html">List</a> - <a href="fib.py.html">Source</a> - <a href="fib.wat.html">WebAssembly</a>
|
<div class="menu">
|
||||||
|
<a href="index.html">List</a> - <a href="fib.py.html">Source</a> - <a href="fib.wat.html">WebAssembly</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="white-space: pre;" id="results"></div>
|
<div class="description">
|
||||||
|
<p>
|
||||||
|
This example shows a recursive implementation of the <a href="https://en.wikipedia.org/wiki/Fibonacci_sequence">Fibonacci sequence</a>.
|
||||||
|
It makes uses of WebAssembly's support for <a href="https://en.wikipedia.org/wiki/Tail_call">tail calls</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Try it out!</h3>
|
||||||
|
<div class="example">
|
||||||
|
<input type="number" id="example-n" value="25" />
|
||||||
|
<button type="click" id="example-click" disabled>Calculate</button>
|
||||||
|
<input type="number" id="example-fib" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="./include.js"></script>
|
<div class="example-list">
|
||||||
<script type="text/javascript">
|
<ul>
|
||||||
let importObject = {};
|
<li><a href="#" data-n="5">fib(5)</a> = 5</li>
|
||||||
|
<li><a href="#" data-n="10">fib(10)</a> = 55</li>
|
||||||
|
<li><a href="#" data-n="25">fib(25)</a> = 75025</li>
|
||||||
|
<li><a href="#" data-n="50">fib(50)</a> = 12586269025</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
function run_test(app, number, expected)
|
<script>
|
||||||
{
|
let importObject = {};
|
||||||
let actual = app.instance.exports.fib(BigInt(number));
|
let exampleN = document.querySelector('#example-n');
|
||||||
console.log(actual);
|
let exampleClick = document.querySelector('#example-click');
|
||||||
|
let exampleFib = document.querySelector('#example-fib');
|
||||||
|
|
||||||
test_result(BigInt(expected) == actual, {
|
WebAssembly.instantiateStreaming(fetch('fib.wasm'), importObject)
|
||||||
'summary': 'fib(' + number + ')',
|
.then(app => {
|
||||||
'attributes': {
|
exampleClick.addEventListener('click', event => {
|
||||||
'expected': expected,
|
let in_put = exampleN.value;
|
||||||
'actual': actual
|
let result = app.instance.exports.fib(BigInt(in_put));
|
||||||
},
|
exampleFib.value = result;
|
||||||
});
|
});
|
||||||
}
|
exampleClick.removeAttribute('disabled');
|
||||||
|
});
|
||||||
|
|
||||||
WebAssembly.instantiateStreaming(fetch('fib.wasm'), importObject)
|
for(let exmpl of document.querySelectorAll('a[data-n]') ) {
|
||||||
.then(app => {
|
exmpl.addEventListener('click', event => {
|
||||||
// 92: 7540113804746346429
|
exampleN.value = exmpl.getAttribute('data-n');
|
||||||
// i64: 9223372036854775807
|
exampleClick.click();
|
||||||
// 93: 12200160415121876738
|
});
|
||||||
|
}
|
||||||
run_test(app, 1, '1');
|
|
||||||
run_test(app, 2, '1');
|
|
||||||
run_test(app, 3, '2');
|
|
||||||
run_test(app, 4, '3');
|
|
||||||
run_test(app, 10, '55');
|
|
||||||
run_test(app, 20, '6765');
|
|
||||||
run_test(app, 30, '832040');
|
|
||||||
run_test(app, 40, '102334155');
|
|
||||||
run_test(app, 50, '12586269025');
|
|
||||||
run_test(app, 60, '1548008755920');
|
|
||||||
run_test(app, 70, '190392490709135');
|
|
||||||
run_test(app, 80, '23416728348467685');
|
|
||||||
run_test(app, 90, '2880067194370816120');
|
|
||||||
run_test(app, 92, '7540113804746346429');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -13,7 +13,3 @@ def fib(n: u64) -> u64:
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
return helper(n - 1, 0, 1)
|
return helper(n - 1, 0, 1)
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> u64:
|
|
||||||
return fib(40)
|
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Examples - Fold</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Fold</h1>
|
|
||||||
|
|
||||||
<a href="index.html">List</a> - <a href="fold.py.html">Source</a> - <a href="fold.wat.html">WebAssembly</a>
|
|
||||||
|
|
||||||
<div style="white-space: pre;" id="results"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="./include.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
let importObject = {};
|
|
||||||
|
|
||||||
function run_test(app, data, expected)
|
|
||||||
{
|
|
||||||
let offset = alloc_bytes(app, data);
|
|
||||||
|
|
||||||
let actual = app.instance.exports.foldl_u8_or_1(offset);
|
|
||||||
|
|
||||||
test_result(expected == actual, {
|
|
||||||
'summary': 'foldl(or, 1, [' + data + ']) == ' + expected,
|
|
||||||
'attributes': {
|
|
||||||
'data': data,
|
|
||||||
'expected': expected,
|
|
||||||
'offset': offset,
|
|
||||||
'actual': actual,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WebAssembly.instantiateStreaming(fetch('fold.wasm'), importObject)
|
|
||||||
.then(app => {
|
|
||||||
run_test(app, [], 1);
|
|
||||||
run_test(app, [0x20], 0x21);
|
|
||||||
run_test(app, [0x20, 0x10], 0x31);
|
|
||||||
run_test(app, [0x20, 0x10, 0x08], 0x39);
|
|
||||||
run_test(app, [0x20, 0x10, 0x08, 0x04], 0x3D);
|
|
||||||
run_test(app, [0x20, 0x10, 0x08, 0x04, 0x02], 0x3F);
|
|
||||||
run_test(app, [0x20, 0x10, 0x08, 0x04, 0x02, 0x01], 0x3F);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
def u8_or(l: u8, r: u8) -> u8:
|
|
||||||
return l | r
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def foldl_u8_or_1(b: bytes) -> u8:
|
|
||||||
return foldl(u8_or, 1, b)
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Examples - Imported</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Imported</h1>
|
|
||||||
|
|
||||||
<a href="index.html">List</a> - <a href="imported.py.html">Source</a> - <a href="imported.wat.html">WebAssembly</a>
|
|
||||||
|
|
||||||
<div style="white-space: pre;" id="results"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="./include.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
let importObject = {
|
|
||||||
'imports': {
|
|
||||||
'log': log,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let log_result = [];
|
|
||||||
|
|
||||||
function log(inp)
|
|
||||||
{
|
|
||||||
log_result.push(inp);
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_test(app, a, b)
|
|
||||||
{
|
|
||||||
log_result = [];
|
|
||||||
|
|
||||||
let expected = a * b;
|
|
||||||
|
|
||||||
app.instance.exports.mult_and_log(a, b);
|
|
||||||
|
|
||||||
let actual = log_result[0];
|
|
||||||
|
|
||||||
test_result(expected == actual, {
|
|
||||||
'summary': 'mult_and_log(' + a + ', ' + b + ') == ' + expected,
|
|
||||||
'attributes': {
|
|
||||||
'a': a,
|
|
||||||
'b': b,
|
|
||||||
'expected': expected,
|
|
||||||
'actual': actual,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
WebAssembly.instantiateStreaming(fetch('imported.wasm'), importObject)
|
|
||||||
.then(app => {
|
|
||||||
run_test(app, 1, 1);
|
|
||||||
run_test(app, 3, 5);
|
|
||||||
run_test(app, 8, 19);
|
|
||||||
run_test(app, 12, 127);
|
|
||||||
run_test(app, 79, 193);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
@imported
|
|
||||||
def log(no: i32) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def mult_and_log(a: i32, b: i32) -> None:
|
|
||||||
return log(a * b)
|
|
||||||
@ -1,3 +1,6 @@
|
|||||||
|
/***
|
||||||
|
* Allocates the given string in the given application's memory
|
||||||
|
*/
|
||||||
function alloc_bytes(app, data)
|
function alloc_bytes(app, data)
|
||||||
{
|
{
|
||||||
let stdlib_types___alloc_bytes__ = app.instance.exports['stdlib.types.__alloc_bytes__']
|
let stdlib_types___alloc_bytes__ = app.instance.exports['stdlib.types.__alloc_bytes__']
|
||||||
@ -14,85 +17,12 @@ function alloc_bytes(app, data)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_times(times, callback, tweak)
|
/**
|
||||||
|
* WebAssembly's interface only gets you signed integers
|
||||||
|
*
|
||||||
|
* Getting unsigned values out requires some work.
|
||||||
|
*/
|
||||||
|
function i32_to_u32(n)
|
||||||
{
|
{
|
||||||
let sum = 0;
|
return n >>> 0;
|
||||||
let max = 0;
|
|
||||||
let min = 1000000000000000000;
|
|
||||||
let values = [];
|
|
||||||
for(let idx = 0; idx < times; idx += 1) {
|
|
||||||
if( tweak ) {
|
|
||||||
tweak();
|
|
||||||
}
|
|
||||||
|
|
||||||
const t0 = performance.now();
|
|
||||||
let result = callback();
|
|
||||||
const t1 = performance.now();
|
|
||||||
let time = t1 - t0;
|
|
||||||
sum += time;
|
|
||||||
values.push({'time': time, 'result': result});
|
|
||||||
max = max < time ? time : max;
|
|
||||||
min = min > time ? time : min;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
'min': min,
|
|
||||||
'avg': sum / times,
|
|
||||||
'max': max,
|
|
||||||
'sum': sum,
|
|
||||||
'values': values,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_result(is_pass, data)
|
|
||||||
{
|
|
||||||
data = data || {};
|
|
||||||
|
|
||||||
let result_details = document.createElement('details');
|
|
||||||
|
|
||||||
let result_summary = document.createElement('summary');
|
|
||||||
result_summary.textContent =
|
|
||||||
(is_pass ? 'Test passed: ' : 'Test failed: ')
|
|
||||||
+ (data.summary ?? '(no summary)')
|
|
||||||
;
|
|
||||||
result_summary.setAttribute('style', is_pass ? 'background: green' : 'background: red');
|
|
||||||
result_details.appendChild(result_summary);
|
|
||||||
|
|
||||||
if( data.attributes ) {
|
|
||||||
result_table(data, result_details);
|
|
||||||
}
|
|
||||||
|
|
||||||
let results = document.getElementById('results');
|
|
||||||
results.appendChild(result_details);
|
|
||||||
}
|
|
||||||
|
|
||||||
function result_table(attributes, parent)
|
|
||||||
{
|
|
||||||
let table = document.createElement('table');
|
|
||||||
|
|
||||||
Object.keys(attributes).forEach(idx => {
|
|
||||||
let td0 = document.createElement('td');
|
|
||||||
td0.setAttribute('style', 'vertical-align: top;');
|
|
||||||
td0.textContent = idx;
|
|
||||||
let td1 = document.createElement('td');
|
|
||||||
if( typeof(attributes[idx]) == 'object' ) {
|
|
||||||
let result_details = document.createElement('details');
|
|
||||||
|
|
||||||
let result_summary = document.createElement('summary');
|
|
||||||
result_summary.textContent = 'Show me';
|
|
||||||
result_details.appendChild(result_summary);
|
|
||||||
|
|
||||||
result_table(attributes[idx], result_details);
|
|
||||||
|
|
||||||
td1.appendChild(result_details);
|
|
||||||
} else {
|
|
||||||
td1.textContent = attributes[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
let tr = document.createElement('tr');
|
|
||||||
tr.appendChild(td0);
|
|
||||||
tr.appendChild(td1);
|
|
||||||
|
|
||||||
table.appendChild(tr);
|
|
||||||
});
|
|
||||||
parent.append(table);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Examples</title>
|
<title>Examples</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Examples</h1>
|
<h1>Examples</h1>
|
||||||
<h2>Standard</h2>
|
|
||||||
|
<h2>Functions</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="crc32.html">CRC32</a></li>
|
<li><a href="crc32.html">CRC32</a></li>
|
||||||
<li><a href="fib.html">Fibonacci</a></li>
|
<li><a href="fib.html">Fibonacci</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Technical</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="buffer.html">Buffer</a></li>
|
|
||||||
<li><a href="fold.html">Folding</a></li>
|
|
||||||
<li><a href="imported.html">Imported</a></li>
|
|
||||||
</ul>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
31
examples/main.css
Normal file
31
examples/main.css
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
:root {
|
||||||
|
/* CSS HEX */
|
||||||
|
--seasalt: #fcfafaff;
|
||||||
|
--silver: #c8d3d5ff;
|
||||||
|
--powder-blue: #a4b8c4ff;
|
||||||
|
--slate-gray: #6e8387ff;
|
||||||
|
--dark-pastel-green: #0cca4aff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: var(--seasalt);
|
||||||
|
color: var(--slate-gray);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--dark-pastel-green);
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
border: 1px solid var(--powder-blue);
|
||||||
|
border-width: 1px 0px;
|
||||||
|
padding: 0.2em;
|
||||||
|
margin: 0.2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
border-top: 1px solid var(--powder-blue);
|
||||||
|
padding-top: 0.3em;
|
||||||
|
}
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from ..helpers import Suite
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.slow_integration_test
|
|
||||||
def test_index():
|
|
||||||
with open('examples/buffer.py', 'r', encoding='ASCII') as fil:
|
|
||||||
code_py = "\n" + fil.read()
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code(b'Hello, world!', 5, func_name='index')
|
|
||||||
assert 44 == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.slow_integration_test
|
|
||||||
def test_length():
|
|
||||||
with open('examples/buffer.py', 'r', encoding='ASCII') as fil:
|
|
||||||
code_py = "\n" + fil.read()
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code(b'Hello, world!', func_name='length')
|
|
||||||
assert 13 == result.returned_value
|
|
||||||
@ -8,6 +8,6 @@ def test_fib():
|
|||||||
with open('./examples/fib.py', 'r', encoding='UTF-8') as fil:
|
with open('./examples/fib.py', 'r', encoding='UTF-8') as fil:
|
||||||
code_py = "\n" + fil.read()
|
code_py = "\n" + fil.read()
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
result = Suite(code_py).run_code(40, func_name='fib')
|
||||||
|
|
||||||
assert 102334155 == result.returned_value
|
assert 102334155 == result.returned_value
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user