Vm working. simple interface built
- still need stack view - still ned to work with devices
This commit is contained in:
@@ -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>
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
201
www/src/js/virtual_machine/index.js
Normal file
201
www/src/js/virtual_machine/index.js
Normal 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 }
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user