--- /dev/null
+package builtin
+
+read_line :: () -> str {
+ #persist buffer: [1024] u8;
+
+ (package core).__flush_stdio();
+
+ read_line_available :: () -> bool #foreign "host" "read_line_available" ---
+ read_line :: (buffer: [] u8) -> u32 #foreign "host" "read_line" ---
+
+ read_line_available();
+ length := read_line(~~buffer);
+
+ return str.{ ~~buffer, length };
+}
+
app.config.from_object("config.default")
+@app.after_request
+def require_coep(response):
+ response.headers['Cross-Origin-Embedder-Policy'] = "require-corp"
+ return response
+
@app.route("/")
def get_homepage():
- return flask.render_template("index.html")
+ response = flask.Response(flask.render_template("index.html"))
+ response.headers['Cross-Origin-Embedder-Policy'] = "require-corp"
+ response.headers['Cross-Origin-Opener-Policy'] = "same-origin"
+ return response
@app.route("/compile", methods=['POST'])
with os.fdopen(code_file_desc, "w+b") as code_file:
code_file.write(code.encode('utf-8'))
- compile_process = subprocess.run(f"timeout -s KILL 10s onyx -r js --no-file-contents --no-colors -o {wasm_file_name} {code_file_name}", shell=True, capture_output=True)
+ compile_process = subprocess.run(f"timeout -s KILL 10s onyx -r js --no-file-contents --no-colors -o {wasm_file_name} {code_file_name} ./read_line.onyx", shell=True, capture_output=True)
os.remove(code_file_name)
:root {
--menu-bar-height: 32px;
+ --input-bar-height: 32px;
--divider-size: 4px;
--left-half-width: 70%;
}
#code-result {
height: 100%;
- max-height: calc(100% - 24px); /* subtract the padding */
+ max-height: calc(100% - var(--menu-bar-height) - var(--input-bar-height)); /* subtract the padding */
background: #070707;
color: #fff;
font-size: 16px;
display: inline-block;
float: left;
}
+
+#input-bar {
+ background-color: #181818;
+ color: #fff;
+ outline: none;
+ border: none;
+
+ min-height: var(--input-bar-height);
+ width: 80%;
+ padding: 8px;
+ float: left;
+
+ font-size: 16px;
+ font-family: Monaco, Menlo, "Ubuntu Mono", Consolas, source-code-pro, monospace;
+}
+
+#input-submit {
+ background-color: #272727;
+ color: #fff;
+ outline: none;
+ border: none;
+
+ float: left;
+ width: 20%;
+ padding: 8px;
+ margin: 0;
+ min-height: var(--input-bar-height);
+
+ font-size: 16px;
+ font-family: Monaco, Menlo, "Ubuntu Mono", Consolas, source-code-pro, monospace;
+
+ transition: all 0.5s;
+}
+
+#input-submit:hover {
+ background: #444;
+ cursor: pointer;
+}
+
let editor_keybind_mode = "normal";
let editor_theme = "chrome";
+let input_shared_buffer = new SharedArrayBuffer(1024 * Uint8Array.BYTES_PER_ELEMENT);
+
async function clear_output() {
let elem = document.getElementById('code-result');
elem.className = ""; // NOTE: This clears all the classes, not just the "errored" one!
}
update_running_msg();
+ input_shared_buffer = new SharedArrayBuffer(1024 * Uint8Array.BYTES_PER_ELEMENT);
wasm_worker = new Worker(window.ROOT_ENDPOINT + '/static/src/worker.js');
wasm_worker.onmessage = (e) => {
update_running_msg();
break;
}
+
+ case 'input': {
+ let input_array = new Uint8Array(input_shared_buffer);
+ Atomics.store(input_array, 0, 0);
+ let msg = prompt("Line: ");
+ input_array.fill(0);
+
+ for (let i=0; i<msg.length && i<input_array.length - 1; i++) {
+ input_array[i + 1] = msg.charCodeAt(i);
+ }
+
+ Atomics.store(input_array, 0, 1);
+ break;
+ }
}
};
- wasm_worker.postMessage({ type: 'start', data: wasm_bytes });
+ wasm_worker.postMessage({ type: 'set_buffer', data: input_shared_buffer });
+ wasm_worker.postMessage({ type: 'start', data: wasm_bytes });
update_running_msg();
}
download_link.remove();
}
+function submit_input() {
+ let inputbar = document.getElementById("input-bar");
+ let input = inputbar.value;
+
+ write_output(input + "\n", false);
+
+ let input_array = new Uint8Array(input_shared_buffer);
+ Atomics.store(input_array, 0, 0);
+ input_array.fill(0);
+
+ for (let i=0; i<input.length && i<input_array.length - 1; i++) {
+ input_array[i + 1] = input.charCodeAt(i);
+ }
+
+ Atomics.store(input_array, 0, 1);
+ inputbar.value = "";
+}
+
window.onload = () => {
let editor = ace.edit('code-editor');
make_resizer("horizontal-divider", "--left-half-width", (e) => {
editor.resize(true);
});
+
+ document.getElementById("input-bar").addEventListener("keyup", (ev) => {
+ if (ev.keyCode === 13) {
+ submit_input();
+ }
+ });
};
+let input_shared_buffer = null;
let wasm_memory = null;
let import_obj = {
return Date.now();
},
+ read_line_available: async function() {
+ let input_array = new Uint8Array(input_shared_buffer);
+ while (Atomics.load(input_array, 0) == 0);
+ },
+
+ read_line(msgptr, msglen) { // Returns actual length
+ let data = new Uint8Array(wasm_memory.buffer, msgptr, msglen);
+ let input_array = new Uint8Array(input_shared_buffer);
+ console.log(Atomics.load(input_array, 0), " == 1");
+
+ let i;
+ for (i=0; input_array[i + 1] != 0 && i<msglen; i++) {
+ console.log(input_array[i + 1]);
+ data[i] = input_array[i + 1];
+ }
+
+ Atomics.store(input_array, 0, 0);
+
+ return i;
+ },
+
exit(code) {
self.postMessage({ type: 'terminated' });
self.close();
onmessage = function(m) {
switch (m.data.type) {
+ case 'set_buffer': {
+ input_shared_buffer = m.data.data;
+ break;
+ }
+
case 'start': {
WebAssembly.instantiate(m.data.data, import_obj)
.then(response => {
<div class="right-half">
<pre id="code-result">
</pre>
+ <input type="textbox" id="input-bar" />
+ <input type="button" id="input-submit" value="Enter" />
</div>
</body>
</html>