Vm working. simple interface built

- still need stack view
- still ned to work with devices
This commit is contained in:
Rachel
2024-03-28 01:31:09 -07:00
parent 3047f774c5
commit baf67b2c6a
25 changed files with 2295 additions and 586 deletions

View File

@@ -35,7 +35,7 @@
<body class="">
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
<div class="App" >
<div class="App">
<div id="modelShareLink" class="modal fade" tabindex="-1" aria-hidden="true" data-bs-theme="dark">
<div class="modal-dialog">
<div class="modal-content">
@@ -153,62 +153,78 @@
<ul class="nav navbar-nav navbar-right flex-row d-sm-none d-none d-md-flex">
<p class="navbar-text mt-auto mb-auto align-self-center" style="">Official Stationeers:</p>
<li role="presentation" class="">
<a href="https://store.steampowered.com/app/544550/Stationeers/"><svg aria-hidden="true" focusable="false"
data-prefix="fab" data-icon="steam" class="svg-inline--fa fa-steam fa-w-16 " role="img"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512">
<path fill="currentColor"
d="M496 256c0 137-111.2 248-248.4 248-113.8 0-209.6-76.3-239-180.4l95.2 39.3c6.4 32.1 34.9 56.4 68.9 56.4 39.2 0 71.9-32.4 70.2-73.5l84.5-60.2c52.1 1.3 95.8-40.9 95.8-93.5 0-51.6-42-93.5-93.7-93.5s-93.7 42-93.7 93.5v1.2L176.6 279c-15.5-.9-30.7 3.4-43.5 12.1L0 236.1C10.2 108.4 117.1 8 247.6 8 384.8 8 496 119 496 256zM155.7 384.3l-30.5-12.6a52.79 52.79 0 0 0 27.2 25.8c26.9 11.2 57.8-1.6 69-28.4 5.4-13 5.5-27.3.1-40.3-5.4-13-15.5-23.2-28.5-28.6-12.9-5.4-26.7-5.2-38.9-.6l31.5 13c19.8 8.2 29.2 30.9 20.9 50.7-8.3 19.9-31 29.2-50.8 21zm173.8-129.9c-34.4 0-62.4-28-62.4-62.3s28-62.3 62.4-62.3 62.4 28 62.4 62.3-27.9 62.3-62.4 62.3zm.1-15.6c25.9 0 46.9-21 46.9-46.8 0-25.9-21-46.8-46.9-46.8s-46.9 21-46.9 46.8c.1 25.8 21.1 46.8 46.9 46.8z">
</path>
</svg>
<a href="https://store.steampowered.com/app/544550/Stationeers/">
<i class="fa-brands fa-steam fa-w-16"></i>
</a>
</li>
<li role="presentation" class="">
<a href="https://stationeers.com/">
<svg aria-hidden="true" focusable="false" data-prefix="fa" data-icon="globe"
class="svg-inline--fa fa-globe fa-w-16 " role="img" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 496 512">
<path fill="currentColor"
d="M336.5 160C322 70.7 287.8 8 248 8s-74 62.7-88.5 152h177zM152 256c0 22.2 1.2 43.5 3.3 64h185.3c2.1-20.5 3.3-41.8 3.3-64s-1.2-43.5-3.3-64H155.3c-2.1 20.5-3.3 41.8-3.3 64zm324.7-96c-28.6-67.9-86.5-120.4-158-141.6 24.4 33.8 41.2 84.7 50 141.6h108zM177.2 18.4C105.8 39.6 47.8 92.1 19.3 160h108c8.7-56.9 25.5-107.8 49.9-141.6zM487.4 192H372.7c2.1 21 3.3 42.5 3.3 64s-1.2 43-3.3 64h114.6c5.5-20.5 8.6-41.8 8.6-64s-3.1-43.5-8.5-64zM120 256c0-21.5 1.2-43 3.3-64H8.6C3.2 212.5 0 233.8 0 256s3.2 43.5 8.6 64h114.6c-2-21-3.2-42.5-3.2-64zm39.5 96c14.5 89.3 48.7 152 88.5 152s74-62.7 88.5-152h-177zm159.3 141.6c71.4-21.2 129.4-73.7 158-141.6h-108c-8.8 56.9-25.6 107.8-50 141.6zM19.3 352c28.6 67.9 86.5 120.4 158 141.6-24.4-33.8-41.2-84.7-50-141.6h-108z">
</path>
</svg>
<i class="fa-solid fa-globe fa-w-16"></i>
</a>
</li>
<li role="presentation" class="">
<a href="https://twitter.com/stationeers">
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="twitter"
class="svg-inline--fa fa-twitter fa-w-16 " role="img" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path fill="currentColor"
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z">
</path>
</svg>
<i class="fa-brands fa-x-twitter"></i>
</a>
</li>
<li role="presentation" class="">
<a href="https://discordapp.com/invite/CxR3mRy">
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="discord"
class="svg-inline--fa fa-discord fa-w-14 " role="img" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path fill="currentColor"
d="M297.216 243.2c0 15.616-11.52 28.416-26.112 28.416-14.336 0-26.112-12.8-26.112-28.416s11.52-28.416 26.112-28.416c14.592 0 26.112 12.8 26.112 28.416zm-119.552-28.416c-14.592 0-26.112 12.8-26.112 28.416s11.776 28.416 26.112 28.416c14.592 0 26.112-12.8 26.112-28.416.256-15.616-11.52-28.416-26.112-28.416zM448 52.736V512c-64.494-56.994-43.868-38.128-118.784-107.776l13.568 47.36H52.48C23.552 451.584 0 428.032 0 398.848V52.736C0 23.552 23.552 0 52.48 0h343.04C424.448 0 448 23.552 448 52.736zm-72.96 242.688c0-82.432-36.864-149.248-36.864-149.248-36.864-27.648-71.936-26.88-71.936-26.88l-3.584 4.096c43.52 13.312 63.744 32.512 63.744 32.512-60.811-33.329-132.244-33.335-191.232-7.424-9.472 4.352-15.104 7.424-15.104 7.424s21.248-20.224 67.328-33.536l-2.56-3.072s-35.072-.768-71.936 26.88c0 0-36.864 66.816-36.864 149.248 0 0 21.504 37.12 78.08 38.912 0 0 9.472-11.52 17.152-21.248-32.512-9.728-44.8-30.208-44.8-30.208 3.766 2.636 9.976 6.053 10.496 6.4 43.21 24.198 104.588 32.126 159.744 8.96 8.96-3.328 18.944-8.192 29.44-15.104 0 0-12.8 20.992-46.336 30.464 7.68 9.728 16.896 20.736 16.896 20.736 56.576-1.792 78.336-38.912 78.336-38.912z">
</path>
</svg>
<i class="fa-brands fa-discord"></i>
</a>
</li>
</ul>
</nav>
<div class="d-flex flex-column">
<div id="editorContainer" class="p-1 h-100">
<div id="editor" class="w-100"></div>
<div class="d-flex flex-row">
<div class="d-flex flex-column w-100">
<div id="editorContainer" class="p-1 h-100">
<div id="editor" class="w-100"></div>
</div>
<div id="statusBarContainer" class="p-1 mt-auto">
<div id="statusBar" class="w-100 text-body">IC10 editor!</div>
</div>
</div>
<div id="statusBarContainer" class="p-1 mt-auto">
<div id="statusBar" class="w-100 text-body">IC10 editor!</div>
<div class="d-flex flex-column flex-shrink-1">
<div id="virtualMachine" >
<div id="vmActiveIC">
<div class="p-2 d-flex flex-row justify-content-center">
<div class="d-flex flex-column">
<div id="vmControls" class="btn-group-vertical btn-group-sm " role="group"
aria-label="Virtual Machine Controls">
<button id="vmControlRun" type="button" class="btn btn-primary">Run</button>
<button id="vmControlStep" type="button" class="btn btn-secondary">Step</button>
<button id="vmControlReset" type="button" class="btn btn-warning">Reset</button>
</div>
</div>
<div class="card ms-2">
<div class="card-header">State</div>
<div id="vmActiveICState" class="card-body">
</div>
</div>
</div>
<div class="p-2 ms-2 d-flex flex-row">
<div class="card ms-2">
<div class="card-header">Registers</div>
<div id="vmActiveRegisters" class="vm_reg">
</div>
</div>
<div id="vmActiveStack">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/ace.js" type="text/javascript" charset="utf-8"></script> -->
<script>
</script>
</body>
</html>
</html>

View File

@@ -36,6 +36,8 @@ ace.config.setModuleLoader('ace/keyboard/sublime', () => import('ace-code/src/ke
ace.config.setModuleLoader('ace/keyboard/vim', () => import('ace-code/src/keyboard/vim.js'));
ace.config.setModuleLoader('ace/keyboard/vscode', () => import('ace-code/src/keyboard/vscode.js'));
ace.config.setModuleLoader('ace/range', () => import('ace-code/src/range'));
console.log("ace module loaders patched");
export { ace };

View File

@@ -3,7 +3,7 @@ import { Mode as IC10Mode } from "./ic10_mode.js";
import * as one_dark from "ace-code/src/theme/one_dark";
import { AceLanguageClient } from "ace-linters/build/ace-language-client";
import { IC10EditorUI } from './ui.js';
import { Range } from 'ace-code/src/range.js';
// to make sure language tools are loaded
import _ace_ext_langue_tools from "ace-code/src/ext/language_tools";
@@ -21,139 +21,173 @@ async function setupLspWorker() {
}
function IC10Editor(session_id) {
this.mode = new IC10Mode()
class IC10Editor {
constructor(session_id) {
window.Editor = this;
this.mode = new IC10Mode();
this.settings = {
keyboard: "ace",
cursor: "ace",
fontSize: 16,
relativeLineNumbers: false,
};
this.settings = {
keyboard: "ace",
cursor: "ace",
fontSize: 16,
relativeLineNumbers: false,
};
this.editor = ace.edit('editor', {
mode: this.mode,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
theme: "ace/theme/one_dark",
fontSize: "16px",
customScrollbar: true,
firstLineNumber: 0,
printMarginColumn: 52,
});
this.aceEditor = ace.edit('editor', {
mode: this.mode,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
theme: "ace/theme/one_dark",
fontSize: "16px",
customScrollbar: false,
firstLineNumber: 0,
printMarginColumn: 52,
});
this.sessions = {};
this.sessions[session_id] = this.editor.getSession();
this.active_session = session_id;
this.bindSession(session_id, this.sessions[session_id]);
this.sessions = {};
this.sessions[session_id] = this.aceEditor.getSession();
this.active_session = session_id;
this.bindSession(session_id, this.sessions[session_id]);
this.active_line_markers = {};
this.active_line_markers[session_id] = null;
this.languageProvider = null;
this.languageProvider = null;
this.ui = new IC10EditorUI(this);
this.ui = new IC10EditorUI(this);
const self = this;
const self = this;
App.session.onLoad((session) => {
const updated_ids = [];
for (const id in session.programs) {
updated_ids.push(id);
self.createOrSetSession(id, session.programs[id]);
App.session.onLoad((session) => {
const updated_ids = [];
for (const id in session.programs) {
updated_ids.push(id);
self.createOrSetSession(id, session.programs[id]);
}
for (const id in self.sessions) {
if (!updated_ids.includes(id)) {
self.destroySession(id);
}
}
});
App.session.loadFromFragment();
App.session.onActiveLine(session => {
for (const id in Object.keys(session.programs)) {
const active_line = session.getActiveLine(id);
if (typeof active_line !== "undefined") {
const marker = self.active_line_markers[id];
if (marker) {
self.sessions[id].removeMarker(marker);
self.active_line_markers[id] = null;
}
self.active_line_markers[id] = self.sessions[id].addMarker(new Range(active_line, 0, active_line, 1), "vm_ic_active_line", "fullLine", true);
if (self.active_session == id) {
// editor.resize(true);
self.aceEditor.scrollToLine(active_line, true, true)
}
}
}
})
}
createOrSetSession(session_id, content) {
if (!this.sessions.hasOwnProperty(session_id)) {
this.newSession(session_id);
}
for (const id in self.sessions) {
if (!updated_ids.includes(id)) {
self.destroySession(id);
this.sessions[session_id].setValue(content);
}
newSession(session_id) {
if (this.sessions.hasOwnProperty(session_id)) {
return false;
}
this.sessions[session_id] = ace.createEditSession("", this.mode);
this.bindSession(session_id, this.sessions[session_id]);
}
setupLsp(lsp_worker) {
const serverData = {
module: () => import("ace-linters/build/language-client"),
modes: "ic10",
type: "webworker",
worker: lsp_worker,
};
// Create a language provider for web worker
this.languageProvider = AceLanguageClient.for(serverData);
this.languageProvider.registerEditor(this.aceEditor);
for (const session_id in this.sessions) {
let options = this.mode.options ?? {};
this.languageProvider.setSessionOptions(this.sessions[session_id], options);
}
}
activateSession(session_id) {
if (!this.sessions.hasOwnProperty(session_id)) {
return false;
}
this.aceEditor.setSession(this.sessions[session_id]);
this.active_session = session_id;
let options = this.mode.options ?? {};
if (this.languageProvider !== null) {
this.languageProvider.setSessionOptions(this.sessions[session_id], options);
}
return true;
}
loadEditorSettings() {
const saved_settings = window.localStorage.getItem("editorSettings");
if (saved_settings !== null && saved_settings.length > 0) {
try {
const saved = JSON.parse(saved_settings);
const temp = Object.assign({}, this.settings, saved);
Object.assign(this.settings, temp);
} catch (e) {
console.log("error loading editor settings", e);
}
}
})
App.session.loadFromFragment();
}
IC10Editor.prototype.createOrSetSession = function(session_id, content) {
if (!this.sessions.hasOwnProperty(session_id)) {
this.newSession(session_id);
}
this.sessions[session_id].setValue(content);
}
IC10Editor.prototype.newSession = function(session_id) {
if (this.sessions.hasOwnProperty(session_id)) {
return false;
}
this.sessions[session_id] = ace.createEditSession("", this.mode);
this.bindSession(session_id, this.sessions[session_id]);
}
IC10Editor.prototype.setupLsp = function(lsp_worker) {
const serverData = {
module: () => import("ace-linters/build/language-client"),
modes: "ic10",
type: "webworker",
worker: lsp_worker,
};
// Create a language provider for web worker
this.languageProvider = AceLanguageClient.for(serverData);
this.languageProvider.registerEditor(this.editor);
for (const session_id in this.sessions) {
let options = this.mode.options ?? {};
this.languageProvider.setSessionOptions(this.sessions[session_id], options);
}
}
IC10Editor.prototype.activateSession = function(session_id) {
if (!this.sessions.hasOwnProperty(session_id)) {
return false;
saveEditorSettings() {
const toSave = JSON.stringify(this.settings);
window.localStorage.setItem("editorSettings", toSave);
}
this.editor.setSession(this.sessions[session_id]);
let options = this.mode.options ?? {};
if (this.languageProvider !== null) {
this.languageProvider.setSessionOptions(this.sessions[session_id], options);
}
return true;
}
IC10Editor.prototype.loadEditorSettings = function() {
const saved_settings = window.localStorage.getItem("editorSettings");
if (saved_settings !== null && saved_settings.length > 0) {
try {
const saved = JSON.parse(saved_settings);
const temp = Object.assign({}, this.settings, saved);
Object.assign(this.settings, temp);
} catch (e) {
console.log("error loading editor settings", e);
destroySession(session_id) {
if (!this.sessions.hasOwnProperty(session_id)) {
return false;
}
if (!(Object.keys(this.sessions).length > 1)) {
return false;
}
const session = this.sessions[session_id];
delete this.sessions[session_id];
if (this.active_session = session_id) {
this.activateSession(Object.keys(this.sessions)[0]);
}
session.destroy();
return true;
}
bindSession(session_id, session) {
session.on('change', () => {
var val = session.getValue();
window.App.session.setProgramCode(session_id, val);
});
}
}
IC10Editor.prototype.saveEditorSettings = function() {
const toSave = JSON.stringify(this.settings);
window.localStorage.setItem("editorSettings", toSave);
}
IC10Editor.prototype.destroySession = function(session_id) {
if (!this.sessions.hasOwnProperty(session_id)) {
return false;
}
if (!(Object.keys(this.sessions).length > 1)) {
return false;
}
const session = this.sessions[session_id];
delete this.sessions[session_id];
if (this.active_session = session_id) {
this.activateSession(Object.keys(this.sessions)[0]);
}
session.destroy();
return true;
}
IC10Editor.prototype.bindSession = function(session_id, session) {
session.on('change', () => {
var val = session.getValue();
window.App.session.setProgramCode(session_id, val);
});
}
export { IC10Editor, setupLspWorker };

View File

@@ -107,9 +107,9 @@ export class AsyncStreamQueue {
async next() {
const done = false;
console.log(`AsyncStream(${this.tag}) waiting for message`)
// console.log(`AsyncStream(${this.tag}) waiting for message`)
const value = await this.dequeue();
console.log(`AsyncStream(${this.tag}) got message`, decoder.decode(value))
// console.log(`AsyncStream(${this.tag}) got message`, decoder.decode(value))
return { done, value };
}

View File

@@ -1,104 +1,111 @@
import { ace } from "./ace";
import { Offcanvas } from 'bootstrap';
function IC10EditorUI(ic10editor) {
class IC10EditorUI {
const self = this;
constructor(ic10editor) {
self.ic10editor = ic10editor;
const self = this;
self.ic10editor.editor.commands.addCommand({
name: "showSettingsMenu",
description: "Show settings menu",
bindKey: { win: "Ctrl-,", mac: "Command-," },
exec: (_editor) => {
const offCanvas = new Offcanvas(document.getElementById("editorSettings"));
offCanvas.toggle();
}
});
self.ic10editor = ic10editor;
ace.config.loadModule("ace/ext/keyboard_menu", function(module) {
console.log("keybinding_menu loaded");
module.init(self.ic10editor.editor);
})
self.ic10editor.aceEditor.commands.addCommand({
name: "showSettingsMenu",
description: "Show settings menu",
bindKey: { win: "Ctrl-,", mac: "Command-," },
exec: (_editor) => {
const offCanvas = new Offcanvas(document.getElementById("editorSettings"));
offCanvas.toggle();
}
});
self.ic10editor.loadEditorSettings();
self.displayEditorSettings();
self.updateEditorSettings();
self.reCalcEditorSize();
window.addEventListener('resize', (e) => { self.reCalcEditorSize() });
ace.config.loadModule("ace/ext/keyboard_menu", function (module) {
console.log("keybinding_menu loaded");
module.init(self.ic10editor.aceEditor);
});
document.getElementsByName("editorKeybindRadio").forEach((el) => {
el.addEventListener('change', (e) => {
self.ic10editor.settings.keyboard = e.target.value;
self.ic10editor.loadEditorSettings();
self.displayEditorSettings();
self.updateEditorSettings();
self.reCalcEditorSize();
window.addEventListener('resize', (e) => { self.reCalcEditorSize(); });
document.getElementsByName("editorKeybindRadio").forEach((el) => {
el.addEventListener('change', (e) => {
self.ic10editor.settings.keyboard = e.target.value;
self.ic10editor.saveEditorSettings();
self.updateEditorSettings();
});
});
document.getElementsByName("editorCursorRadio").forEach((el) => {
el.addEventListener('change', (e) => {
self.ic10editor.settings.cursor = e.target.value;
self.ic10editor.saveEditorSettings();
self.updateEditorSettings();
});
});
document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => {
window.App.editorSettings.fontSize = e.target.value;
self.ic10editor.saveEditorSettings();
self.updateEditorSettings();
})
});
document.getElementsByName("editorCursorRadio").forEach((el) => {
el.addEventListener('change', (e) => {
self.ic10editor.settings.cursor = e.target.value;
});
document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => {
window.App.editorSettings.relativeLineNumbers = e.target.checked;
self.ic10editor.saveEditorSettings();
self.updateEditorSettings();
})
});
document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => {
window.App.editorSettings.fontSize = e.target.value;
self.ic10editor.saveEditorSettings();
self.updateEditorSettings();
});
document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => {
window.App.editorSettings.relativeLineNumbers = e.target.checked;
self.ic10editor.saveEditorSettings();
self.updateEditorSettings();
})
});
console.log(self.ic10editor.editor.getOption('keyboardHandler'));
console.log(self.ic10editor.aceEditor.getOption('keyboardHandler'));
self.ic10editor.editor.setTheme("ace/theme/one_dark");
ace.config.loadModule("ace/ext/statusbar", function(module) {
const statusBar = new module.StatusBar(self.ic10editor.editor, document.getElementById("statusBar"));
statusBar.updateStatus(self.ic10editor.editor);
})
self.ic10editor.aceEditor.setTheme("ace/theme/one_dark");
ace.config.loadModule("ace/ext/statusbar", function (module) {
const statusBar = new module.StatusBar(self.ic10editor.aceEditor, document.getElementById("statusBar"));
statusBar.updateStatus(self.ic10editor.aceEditor);
});
self.ic10editor.editor.setAutoScrollEditorIntoView(true);
}
self.ic10editor.aceEditor.setAutoScrollEditorIntoView(true);
IC10EditorUI.prototype.updateEditorSettings = function() {
const settings = this.ic10editor.settings;
const editor = this.ic10editor.editor;
if (settings.keyboard === 'ace') {
editor.setOption('keyboardHandler', null);
} else {
editor.setOption('keyboardHandler', `ace/keyboard/${settings.keyboard}`);
}
editor.setOption('cursorStyle', settings.cursor);
editor.setOption('fontSize', `${settings.fontSize}px`);
editor.setOption('relativeLineNumbers', settings.relativeLineNumbers);
updateEditorSettings() {
const settings = this.ic10editor.settings;
const editor = this.ic10editor.aceEditor;
if (settings.keyboard === 'ace') {
editor.setOption('keyboardHandler', null);
} else {
editor.setOption('keyboardHandler', `ace/keyboard/${settings.keyboard}`);
}
editor.setOption('cursorStyle', settings.cursor);
editor.setOption('fontSize', `${settings.fontSize}px`);
editor.setOption('relativeLineNumbers', settings.relativeLineNumbers);
}
displayEditorSettings() {
const settings = this.ic10editor.settings;
document.getElementsByName("editorKeybindRadio").forEach((el) => {
el.checked = el.value === settings.keyboard;
});
document.getElementsByName("editorCursorRadio").forEach((el) => {
el.checked = el.value === settings.cursor;
});
document.getElementById("editorSettingsFontSize").value = settings.fontSize;
document.getElementById("editorSettingsRelativeLineNumbers").checked = settings.relativeLineNumbers;
}
reCalcEditorSize() {
const editor = this.ic10editor.aceEditor;
const navBar = document.getElementById("navBar");
const statusBarContainer = document.getElementById("statusBarContainer");
const correction = navBar.offsetHeight + statusBarContainer.offsetHeight;
const editorContainer = document.getElementById("editor");
editorContainer.style.height = `calc( 100vh - ${correction}px - 0.5rem)`;
editor.resize(true);
}
}
IC10EditorUI.prototype.displayEditorSettings = function() {
const settings = this.ic10editor.settings;
document.getElementsByName("editorKeybindRadio").forEach((el) => {
el.checked = el.value === settings.keyboard;
});
document.getElementsByName("editorCursorRadio").forEach((el) => {
el.checked = el.value === settings.cursor;
});
document.getElementById("editorSettingsFontSize").value = settings.fontSize;
document.getElementById("editorSettingsRelativeLineNumbers").checked = settings.relativeLineNumbers;
}
IC10EditorUI.prototype.reCalcEditorSize = function() {
const editor = this.ic10editor.editor;
const navBar = document.getElementById("navBar");
const statusBarContainer = document.getElementById("statusBarContainer");
const correction = navBar.offsetHeight + statusBarContainer.offsetHeight;
const editorContainer = document.getElementById("editor");
editorContainer.style.height = `calc( 100vh - ${correction}px - 0.5rem)`;
editor.resize(true);
}
export { IC10EditorUI };

View File

@@ -1,10 +1,10 @@
import { init } from "ic10emu_wasm";
import { IC10Editor, setupLspWorker } from "./editor";
import { Session } from './session';
import { VirtualMachine } from "./virtual_machine";
const App = {
editor: null,
vm: null,
session: new Session()
};
@@ -20,10 +20,10 @@ function docReady(fn) {
}
}
init();
docReady(() => {
App.vm = new VirtualMachine();
App.editor = new IC10Editor();
setupLspWorker().then((worker) => {

View File

@@ -37,7 +37,7 @@ move r2 100000.001
# to get their documentation
# vvvvvvvvvvvvvvv
move r0 HASH("AccessCardBlack")
beqz r1 test
beqzal r1 test
# -2045627372 is the crc32 hash of a SolarPanel,
# hover it to see the documentation!
@@ -45,7 +45,7 @@ beqz r1 test
move r1 -2045627372
jal test
move r1 $FF
beqz 0 test
beqzal 0 test
move r1 %1000
yield
j main
@@ -61,6 +61,9 @@ class Session {
this._programs = {};
this._save_timeout = 0;
this._onLoadCallbacks = [];
this._activeSession = 0;
this._activeLines = {};
this._onActiveLineCallbacks = [];
this.loadFromFragment();
const self = this;
@@ -77,6 +80,23 @@ class Session {
Object.assign(this._programs, programs);
}
get activeSession() {
return this._activeSession;
}
getActiveLine(id) {
return this._activeLines[id];
}
setActiveLine(id, line) {
this._activeLines[id] = line;
this._fireOnActiveLine();
}
set activeLine(line) {
this._activeLine = line;
}
setProgramCode(id, code) {
this._programs[id] = code;
this.save();
@@ -93,10 +113,25 @@ class Session {
}
}
onActiveLine(callback) {
this._onActiveLineCallbacks.push(callback);
}
_fireOnActiveLine() {
for (const i in this._onActiveLineCallbacks) {
const callback = this._onActiveLineCallbacks[i];
callback(this);
}
}
save() {
if (this._save_timeout) clearTimeout(this._save_timeout);
this._save_timeout = setTimeout(() => {
this.saveToFragment();
if (window.App.vm) {
window.App.vm.updateCode();
}
}, 1000);
}

View File

@@ -0,0 +1,201 @@
import { init } from "ic10emu_wasm";
// import { Card } from 'bootstrap';
class VirtualMachine {
constructor() {
const vm = init();
window.VM = this;
this.ic10vm = vm;
this.ui = new VirtualMachineUI(this);
this.ics = {}
const ics = this.ic10vm.ics;
for (const id of Object.keys(ics)) {
this.ics[id] = this.ic10vm.getDevice(parseInt(id));
}
this.updateCode()
}
updateCode() {
const progs = window.App.session.programs;
for (const id of Object.keys(progs)) {
const ic = this.ics[id];
const prog = progs[id];
if (ic && prog) {
console.time(`CompileProgram_${id}`);
this.ics[id].setCode(progs[id]);
console.timeEnd(`CompileProgram_${id}`);
}
}
this.update();
}
step() {
const ic = this.ics[window.App.session.activeSession];
if (ic) {
try {
ic.step();
} catch (e) {
console.log(e);
}
this.update();
}
}
run() {
const ic = this.ics[window.App.session.activeSession];
if (ic) {
try {
ic.run(false);
} catch (e) {
console.log(e);
}
this.update();
}
}
reset() {
const ic = this.ics[window.App.session.activeSession];
if (ic) {
ic.reset();
this.update();
}
}
update() {
const ic = this.ics[window.App.session.activeSession];
window.App.session.setActiveLine(window.App.session.activeSession, ic.ip);
this.ui.update(ic);
}
}
class VirtualMachineUI {
constructor(vm) {
this.vm = vm
this.state = new VMStateUI();
this.registers = new VMRegistersUI();
this.buildStackDisplay();
const self = this;
document.getElementById("vmControlRun").addEventListener('click', (_event) => {
self.vm.run();
}, { capture: true });
document.getElementById("vmControlStep").addEventListener('click', (_event) => {
self.vm.step();
}, { capture: true });
document.getElementById("vmControlReset").addEventListener('click', (_event) => {
self.vm.reset();
}, { capture: true });
}
update(ic) {
this.state.update(ic);
this.registers.update(ic);
}
buildStackDisplay() {
}
}
class VMStateUI {
constructor() {
const stateDom = document.getElementById("vmActiveICState");
this.tbl = document.createElement("table");
this.tbl.classList.add("table");
this.ipRow = this.tbl.insertRow();
this.counterRow = this.tbl.insertRow()
this.stateRow = this.tbl.insertRow()
const ipTh = document.createElement("th");
ipTh.appendChild(document.createTextNode("Instruction Pointer"));
this.ipRow.appendChild(ipTh);
this.instructionPointer = this.ipRow.insertCell();
const conuterTh = document.createElement("th");
conuterTh.appendChild(document.createTextNode("Last Run Operations"));
this.counterRow.appendChild(conuterTh);
this.instructionCounter = this.counterRow.insertCell();
const stateTh = document.createElement("th");
stateTh.appendChild(document.createTextNode("Last State"));
this.stateRow.appendChild(stateTh);
this.lastState = this.stateRow.insertCell();
stateDom.appendChild(this.tbl);
}
update(ic) {
if (ic) {
this.instructionPointer.innerText = ic.ip.toString();
this.instructionCounter.innerText = ic.instructionCount.toString();
this.lastState.innerText = ic.state.toString();
}
}
}
class VMRegistersUI {
constructor() {
const regDom = document.getElementById("vmActiveRegisters");
this.tbl = document.createElement("div");
this.tbl.classList.add("d-flex", "flex-wrap", "justify-content-start", "align-items-start", "align-self-center");
this.regCels = [];
for (var i = 0; i < 18; i++) {
const container = document.createElement("div");
container.classList.add("vm_reg_cel");
const cell = document.createElement("div");
cell.classList.add("input-group", "input-group-sm")
// cell.style.width = "30%";
const nameLabel = document.createElement("span");
nameLabel.innerText = `r${i}`;
nameLabel.classList.add("input-group-text")
cell.appendChild(nameLabel);
const input = document.createElement("input");
input.type = "text"
input.value = 0;
// input.size = 3;
// input.style.width = 40;
cell.appendChild(input);
const aliasesLabel = document.createElement("span");
aliasesLabel.classList.add("input-group-text")
aliasesLabel.innerText = "\xa0";
cell.appendChild(aliasesLabel);
if (i == 16 ) {
aliasesLabel.innerText = "sp";
} else if (i == 17) {
aliasesLabel.innerText = "ra";
}
this.regCels.push({
cell,
nameLabel,
aliasesLabel,
input,
});
container.appendChild(cell);
this.tbl.appendChild(container);
}
regDom.appendChild(this.tbl);
}
update(ic) {
if (ic) {
const registers = ic.registers;
if (registers) {
console.log(registers)
for (var i = 0; i < registers.length; i++) {
this.regCels[i].input.value = registers[i];
}
}
}
}
}
export { VirtualMachine }

View File

@@ -409,3 +409,33 @@ code {
border: 1px solid rgba(8, 121, 144, 0.5);
background: rgba(76, 87, 103, .19);
}
.vm_ic_active_line {
position: absolute;
background: rgba(121, 82, 179, 0.4);
z-index: 20;
}
.vm_reg {
overflow-x: auto;
overflow-y: auto;
max-width: 1200px;
max-height: 400px;
}
// .vm_unset_reg .input-group {
// width: inherit;
// }
.vm_reg_cel {
max-width: 300px;
height: 32px;
}
.vm_reg_cel span {
min-width: 2.5rem;
}
.vm_reg_cel input {
width: 6rem;
}

View File

@@ -12,7 +12,7 @@ $offcanvas-box-shadow: 0 1rem 3rem rgba(0, 0, 0, .175);
$body-color: #333;
$body-bg: #fff;
$border-radius: .4rem;
$success: #7952b3;
$success: rgb(121, 82, 179);
// Required
@import "bootstrap/scss/variables";