Fix deafult session Id, edit register values

This commit is contained in:
Rachel
2024-03-28 04:09:43 -07:00
parent baf67b2c6a
commit 2b9f9bab44
8 changed files with 170 additions and 32 deletions

View File

@@ -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\
"
)

View File

@@ -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<Operand>,

View File

@@ -156,7 +156,7 @@ pub struct IC {
pub state: ICState,
}
#[derive(Debug)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Program {
pub instructions: Vec<grammar::Instruction>,
pub labels: HashMap<String, u32>,
@@ -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<Self, ICError> {
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<f64, ICError> {
pub fn push(&mut self, val: f64) -> Result<f64, ICError> {
let sp = (self.registers[16]) as i32;
if sp < 0 {
Err(ICError::StackUnderflow)
@@ -333,7 +337,7 @@ impl IC {
}
}
fn pop(&mut self) -> Result<f64, ICError> {
pub fn pop(&mut self) -> Result<f64, ICError> {
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<f64, ICError> {
pub fn poke(&mut self, address: f64, val: f64) -> Result<f64, ICError> {
let sp = address as i32;
if sp < 0 || sp >= 512 {
Err(ICError::StackIndexOutOfRange(address))
@@ -357,7 +361,7 @@ impl IC {
}
}
fn peek(&self) -> Result<f64, ICError> {
pub fn peek(&self) -> Result<f64, ICError> {
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<f64, ICError> {
pub fn peek_addr(&self, addr: f64) -> Result<f64, ICError> {
let sp = (addr) as i32;
if sp < 0 {
Err(ICError::StackUnderflow)

View File

@@ -205,8 +205,7 @@ impl DeviceRef {
#[wasm_bindgen(getter, js_name = "state")]
pub fn ic_state(&self) -> Option<String> {
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<bool, JsError> {
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<f64, JsError> {
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<f64, JsError> {
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]

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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(", ")
}
}
}

View File

@@ -438,4 +438,5 @@ code {
.vm_reg_cel input {
width: 6rem;
background-color: var(--bs-body-bg);
}