From 2b9f9bab44d58956fe5c2d5a3620e76087eb11b7 Mon Sep 17 00:00:00 2001 From: Rachel <508861+Ryex@users.noreply.github.com> Date: Thu, 28 Mar 2024 04:09:43 -0700 Subject: [PATCH] Fix deafult session Id, edit register values --- ic10emu/build.rs | 2 +- ic10emu/src/grammar.rs | 2 +- ic10emu/src/interpreter.rs | 16 +++-- ic10emu_wasm/src/lib.rs | 57 +++++++++++++++++- www/src/js/editor/index.js | 30 +++++++--- www/src/js/index.js | 4 +- www/src/js/virtual_machine/index.js | 90 ++++++++++++++++++++++++----- www/src/scss/dark.scss | 1 + 8 files changed, 170 insertions(+), 32 deletions(-) diff --git a/ic10emu/build.rs b/ic10emu/build.rs index 3c5a452..cbc70ee 100644 --- a/ic10emu/build.rs +++ b/ic10emu/build.rs @@ -355,7 +355,7 @@ fn write_instructions_enum() { write!( &mut writer, - "#[derive(PartialEq, Debug)]\n\ + "#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]\n\ pub enum InstructionOp {{\n\ " ) diff --git a/ic10emu/src/grammar.rs b/ic10emu/src/grammar.rs index 3e3e38e..f22d5c1 100644 --- a/ic10emu/src/grammar.rs +++ b/ic10emu/src/grammar.rs @@ -210,7 +210,7 @@ impl FromStr for Comment { } } -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] pub struct Instruction { pub instruction: InstructionOp, pub operands: Vec, diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index f8d871f..37e2b5a 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -156,7 +156,7 @@ pub struct IC { pub state: ICState, } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Program { pub instructions: Vec, pub labels: HashMap, @@ -169,12 +169,14 @@ impl Default for Program { } impl Program { + pub fn new() -> Self { Program { instructions: Vec::new(), labels: HashMap::new(), } } + pub fn try_from_code(code: &str) -> Result { let parse_tree = grammar::parse(&code)?; let mut labels_set = HashSet::new(); @@ -209,6 +211,7 @@ impl Program { labels, }) } + pub fn get_line(&self, line: u32) -> Result<&grammar::Instruction, ICError> { self.instructions .get(line as usize) @@ -217,6 +220,7 @@ impl Program { } impl IC { + pub fn new(id: u16, device: u16) -> Self { IC { device, @@ -319,7 +323,7 @@ impl IC { self.registers[17] = self.ip as f64 + 1.0; } - fn push(&mut self, val: f64) -> Result { + pub fn push(&mut self, val: f64) -> Result { let sp = (self.registers[16]) as i32; if sp < 0 { Err(ICError::StackUnderflow) @@ -333,7 +337,7 @@ impl IC { } } - fn pop(&mut self) -> Result { + pub fn pop(&mut self) -> Result { let sp = (self.registers[16]) as i32; if sp < 0 { Err(ICError::StackUnderflow) @@ -346,7 +350,7 @@ impl IC { } } - fn poke(&mut self, address: f64, val: f64) -> Result { + pub fn poke(&mut self, address: f64, val: f64) -> Result { let sp = address as i32; if sp < 0 || sp >= 512 { Err(ICError::StackIndexOutOfRange(address)) @@ -357,7 +361,7 @@ impl IC { } } - fn peek(&self) -> Result { + pub fn peek(&self) -> Result { let sp = (self.registers[16]) as i32; if sp < 0 { Err(ICError::StackUnderflow) @@ -369,7 +373,7 @@ impl IC { } } - fn peek_addr(&self, addr: f64) -> Result { + pub fn peek_addr(&self, addr: f64) -> Result { let sp = (addr) as i32; if sp < 0 { Err(ICError::StackUnderflow) diff --git a/ic10emu_wasm/src/lib.rs b/ic10emu_wasm/src/lib.rs index 0b74980..1993abc 100644 --- a/ic10emu_wasm/src/lib.rs +++ b/ic10emu_wasm/src/lib.rs @@ -205,8 +205,7 @@ impl DeviceRef { #[wasm_bindgen(getter, js_name = "state")] pub fn ic_state(&self) -> Option { - self - .device + self.device .borrow() .ic .as_ref() @@ -221,6 +220,26 @@ impl DeviceRef { .map(|state| state.to_string()) } + #[wasm_bindgen(getter, js_name = "program")] + pub fn ic_program(&self) -> JsValue { + serde_wasm_bindgen::to_value( + &self + .device + .borrow() + .ic + .as_ref() + .map(|ic| { + self.vm + .borrow() + .ics + .get(ic) + .map(|ic| ic.borrow().program.clone()) + }) + .flatten(), + ) + .unwrap() + } + #[wasm_bindgen(js_name = "step")] pub fn step_ic(&self) -> Result { let id = self.device.borrow().id; @@ -244,6 +263,40 @@ impl DeviceRef { let id = self.device.borrow().id; Ok(self.vm.borrow().set_code(id, code)?) } + + #[wasm_bindgen(js_name = "setRegister")] + pub fn ic_set_register(&self, index: u32, val: f64) -> Result { + let ic_id = *self + .device + .borrow() + .ic + .as_ref() + .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; + let vm_borrow = self.vm.borrow(); + let ic = vm_borrow + .ics + .get(&ic_id) + .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; + let result = ic.borrow_mut().set_register(0, index, val)?; + Ok(result) + } + + #[wasm_bindgen(js_name = "setStack")] + pub fn ic_set_stack(&mut self, address: f64, val: f64) -> Result { + let ic_id = *self + .device + .borrow() + .ic + .as_ref() + .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; + let vm_borrow = self.vm.borrow(); + let ic = vm_borrow + .ics + .get(&ic_id) + .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; + let result = ic.borrow_mut().poke(address, val)?; + Ok(result) + } } #[wasm_bindgen] diff --git a/www/src/js/editor/index.js b/www/src/js/editor/index.js index 4921973..a10f675 100644 --- a/www/src/js/editor/index.js +++ b/www/src/js/editor/index.js @@ -43,6 +43,7 @@ class IC10Editor { customScrollbar: false, firstLineNumber: 0, printMarginColumn: 52, + placeholder: "Your code goes here ...", }); this.sessions = {}; @@ -80,16 +81,17 @@ class IC10Editor { 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) + const session = self.sessions[id]; + if (session) { + self.active_line_markers[id] = session.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) + } } } } - }) } @@ -105,8 +107,20 @@ class IC10Editor { if (this.sessions.hasOwnProperty(session_id)) { return false; } - this.sessions[session_id] = ace.createEditSession("", this.mode); - this.bindSession(session_id, this.sessions[session_id]); + const session = ace.createEditSession("", this.mode); + session.setOptions({ + enableBasicAutocompletion: true, + enableLiveAutocompletion: true, + enableSnippets: true, + theme: "ace/theme/one_dark", + fontSize: "16px", + customScrollbar: false, + firstLineNumber: 0, + printMarginColumn: 52, + placeholder: "Your code goes here ...", + }) + this.sessions[session_id] = session; + this.bindSession(session_id, session); } setupLsp(lsp_worker) { diff --git a/www/src/js/index.js b/www/src/js/index.js index 5318f1f..6128293 100644 --- a/www/src/js/index.js +++ b/www/src/js/index.js @@ -24,7 +24,9 @@ docReady(() => { App.vm = new VirtualMachine(); - App.editor = new IC10Editor(); + const init_session_id = App.vm.devices[0]; + + App.editor = new IC10Editor(init_session_id); setupLspWorker().then((worker) => { App.editor.setupLsp(worker); diff --git a/www/src/js/virtual_machine/index.js b/www/src/js/virtual_machine/index.js index 5cbf474..07d9a06 100644 --- a/www/src/js/virtual_machine/index.js +++ b/www/src/js/virtual_machine/index.js @@ -21,6 +21,10 @@ class VirtualMachine { } + get devices () { + return this.ic10vm.devices; + } + updateCode() { const progs = window.App.session.programs; for (const id of Object.keys(progs)) { @@ -28,7 +32,11 @@ class VirtualMachine { const prog = progs[id]; if (ic && prog) { console.time(`CompileProgram_${id}`); - this.ics[id].setCode(progs[id]); + try { + this.ics[id].setCode(progs[id]); + } catch (e) { + console.log(e); + } console.timeEnd(`CompileProgram_${id}`); } } @@ -72,14 +80,23 @@ class VirtualMachine { window.App.session.setActiveLine(window.App.session.activeSession, ic.ip); this.ui.update(ic); } + + setRegister(index, val) { + const ic = this.ics[window.App.session.activeSession]; + try { + ic.setRegister(index, val); + } catch (e) { + console.log(e); + } + } } class VirtualMachineUI { constructor(vm) { this.vm = vm - this.state = new VMStateUI(); - this.registers = new VMRegistersUI(); + this.state = new VMStateUI(this); + this.registers = new VMRegistersUI(this); this.buildStackDisplay(); const self = this; @@ -109,7 +126,8 @@ class VirtualMachineUI { } class VMStateUI { - constructor() { + constructor(ui) { + this.ui = ui; const stateDom = document.getElementById("vmActiveICState"); this.tbl = document.createElement("table"); @@ -143,7 +161,8 @@ class VMStateUI { } class VMRegistersUI { - constructor() { + constructor(ui) { + this.ui = ui; 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"); @@ -161,18 +180,12 @@ class VMRegistersUI { const input = document.createElement("input"); input.type = "text" input.value = 0; - // input.size = 3; - // input.style.width = 40; + input.dataset.index = i; 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, @@ -182,18 +195,69 @@ class VMRegistersUI { container.appendChild(cell); this.tbl.appendChild(container); } + this.regCels.forEach(cell => { + cell.input.addEventListener('change', this.onCellUpdate); + }); + this.default_aliases = { "sp": 16, "ra": 17 } + this.ic_aliases = {} regDom.appendChild(this.tbl); } + + + onCellUpdate(e) { + let index; + let val; + try { + index = parseInt(e.target.dataset.index); + val = parseFloat(e.target.value); + } catch (e) { + // reset the edit + console.log(e); + VM.update(); + return; + } + VM.setRegister(index, val); + } + update(ic) { + const self = this; 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]; } } + const aliases = ic.aliases; + if (aliases) { + this.ic_aliases = {} + aliases.keys().forEach(alias => { + const target = aliases.get(alias); + if (target.RegisterSpec && target.RegisterSpec.indirection == 0) { + const index = target.RegisterSpec.target; + this.ic_aliases[alias] = index; + } + }) + } + console.log(aliases); + } + this.updateAliases(); + } + + updateAliases () { + const aliases = Object.assign({}, this.default_aliases, this.ic_aliases); + const labels = {} + for (const [alias, target] of Object.entries(aliases)) { + if (labels.hasOwnProperty(target)) { + labels[target].push(alias) + } else { + labels[target] = [alias] + } + } + + for(const [index, label] of Object.entries(labels)) { + this.regCels[index].aliasesLabel.innerText = label.join(", ") } } } diff --git a/www/src/scss/dark.scss b/www/src/scss/dark.scss index 611114d..ab07df9 100644 --- a/www/src/scss/dark.scss +++ b/www/src/scss/dark.scss @@ -438,4 +438,5 @@ code { .vm_reg_cel input { width: 6rem; + background-color: var(--bs-body-bg); }