summaryrefslogtreecommitdiff
path: root/demo/demo.js
diff options
context:
space:
mode:
Diffstat (limited to 'demo/demo.js')
-rw-r--r--demo/demo.js205
1 files changed, 205 insertions, 0 deletions
diff --git a/demo/demo.js b/demo/demo.js
new file mode 100644
index 00000000..069927d7
--- /dev/null
+++ b/demo/demo.js
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var defaultIndent = ' ';
+var input = document.getElementById('input');
+var output = document.getElementById('output');
+var select = document.getElementById('select');
+
+function debounce(f, wait) {
+ var lastTime = 0;
+ var timeoutId = -1;
+ var wrapped = function() {
+ var time = +new Date();
+ if (time - lastTime < wait) {
+ if (timeoutId == -1)
+ timeoutId = setTimeout(wrapped, (lastTime + wait) - time);
+ return;
+ }
+ if (timeoutId != -1)
+ clearTimeout(timeoutId);
+ timeoutId = -1;
+ lastTime = time;
+ f.apply(null, arguments);
+ };
+ return wrapped;
+}
+
+function insertTextAtSelection(input, src) {
+ var selectionStart = input.selectionStart;
+ var selectionEnd = input.selectionEnd;
+ var oldValue = input.value;
+ input.value = oldValue.slice(0, selectionStart) + src +
+ oldValue.slice(selectionEnd);
+ input.selectionStart = input.selectionEnd = selectionStart + src.length;
+}
+
+function onInputKeyDown(e) {
+ if (e.keyCode == 9) { // tab
+ insertTextAtSelection(this, defaultIndent);
+ e.preventDefault();
+ } else if (e.keyCode == 13) { // newline
+ // count nesting depth
+ var parens = 0;
+ var lastOpen = -1;
+ var indent = '';
+ for (var i = this.selectionStart - 1; i >= 0; --i) {
+ var c = this.value[i];
+ if (c == '(') {
+ if (--parens < 0) {
+ if (lastOpen != -1)
+ i = lastOpen;
+ else
+ indent = defaultIndent;
+ break;
+ // find first sibling "(", if any
+ } else if (parens == 0 && lastOpen == -1) {
+ lastOpen = i;
+ }
+ } else if (c == ')') {
+ parens++;
+ }
+ }
+ // get column of current nesting
+ var col = 0;
+ for (; i > 0; --i) {
+ var c = this.value[i];
+ if (c == '\n') {
+ col--; // went back too far
+ break;
+ } else {
+ col++;
+ }
+ }
+ // write newline, plus indentation
+ insertTextAtSelection(this, '\n' + ' '.repeat(col) + indent);
+ e.preventDefault();
+ }
+}
+
+function onError(loc, error, sourceLine, sourceLineColumnOffset) {
+ var lines = [
+ loc.filename + ':' + loc.line + ':' + loc.firstColumn,
+ error
+ ];
+ if (sourceLine.length > 0) {
+ var numSpaces = loc.firstColumn - 1 - sourceLineColumnOffset;
+ var numCarets = loc.lastColumn - loc.firstColumn;
+ lines.push(sourceLine);
+ lines.push(' '.repeat(numSpaces) + '^'.repeat(numCarets));
+ }
+ output.textContent += lines.join('\n') + '\n';
+}
+
+var allocator = wasm.LibcAllocator;
+var eh = new wasm.SourceErrorHandler(onError, 80);
+
+function compile(text) {
+ output.textContent = '';
+ try {
+ var buf = wasm.Buffer.fromString(text);
+ var lexer = wasm.Lexer.fromBuffer(allocator, 'test.wast', buf);
+ var script = wasm.parse(lexer, eh);
+ wasm.checkAst(lexer, script, eh);
+ var memoryWriter = new wasm.MemoryWriter(allocator);
+ var jsWriter = new wasm.JSStringWriter();
+ var logStream = new wasm.Stream(jsWriter.writer);
+ var options = new wasm.WriteBinaryOptions({logStream: logStream});
+ wasm.writeBinaryScript(allocator, memoryWriter.base, script, options);
+ output.textContent = jsWriter.string;
+ } catch (e) {
+ output.textContent += e.toString();
+ } finally {
+ if (options)
+ options.$destroy();
+ if (logStream)
+ logStream.$destroy();
+ if (script)
+ script.$destroy();
+ if (jsWriter)
+ jsWriter.$destroy();
+ if (memoryWriter)
+ memoryWriter.$destroy();
+ if (lexer)
+ lexer.$destroy();
+ if (buf)
+ buf.$destroy();
+ }
+}
+
+var compileInput = debounce(function() { compile(input.value); }, 100);
+
+function onInputInput(e) {
+ compileInput();
+}
+
+var examples = [
+ {
+ name: 'empty',
+ contents: '(module)'
+ },
+
+ {
+ name: 'simple',
+ contents:
+ '(module\n' +
+ ' (func $addTwo (param i32 i32) (result i32)\n' +
+ ' (i32.add\n' +
+ ' (get_local 0)\n' +
+ ' (get_local 1)))\n' +
+ ' (export "addTwo" $addTwo))\n'
+ },
+
+ {
+ name: 'factorial',
+ contents:
+ '(module\n' +
+ ' (func $fac (param i64) (result i64)\n' +
+ ' (if (i64.lt_s (get_local 0) (i64.const 0))\n' +
+ ' (then (i64.const 1))\n' +
+ ' (else\n' +
+ ' (i64.mul\n' +
+ ' (get_local 0)\n' +
+ ' (call $fac\n' +
+ ' (i64.sub\n' +
+ ' (get_local 0)\n' +
+ ' (i64.const 1)))))))\n' +
+ ' (export "fac" $fac))\n'
+ }
+];
+
+function setExample(index) {
+ var contents = examples[index].contents;
+ input.value = contents;
+ compileInput();
+}
+
+function onSelectChanged(e) {
+ setExample(this.selectedIndex);
+}
+
+input.addEventListener('keydown', onInputKeyDown);
+input.addEventListener('input', onInputInput);
+select.addEventListener('change', onSelectChanged);
+
+for (var i = 0; i < examples.length; ++i) {
+ var example = examples[i];
+ var option = document.createElement('option');
+ option.textContent = example.name;
+ select.appendChild(option);
+}
+select.selectedIndex = 1;
+setExample(select.selectedIndex);