Code polishing, actual production ready version

This commit is contained in:
Raphael Jacobs 2022-10-13 15:15:45 +02:00
parent 2851e78e7e
commit 290f5bb6f8
8 changed files with 197 additions and 83 deletions

View File

@ -1,4 +1,10 @@
.ioboxes {
background-color: #e0e0e0;
border: 2px solid grey;
}
mark.goodcode {
background-color: #deffff
}

View File

@ -9,9 +9,11 @@
</head>
<body>
<div class="centred">
<h3>L'incredibile interprete di RJ</h3>
<div style="text-align: center">
<h3>L'incredibile interprete di RJ</h3>
</div>
<div class="vertical centred">
<div class="vertical">
<div class="interpreter spaced horizontal">
<div class="vertical">
<div class="container">
@ -33,13 +35,18 @@ HALT
<div class="right-container vertical">
<div class="inputcontainter">
<h3>INPUT:</h3>
<input type="text" id="inputqueue" value="" />
<input
type="text"
id="inputqueue"
pattern="[0-9| ]+"
value="1 2 3"
/>
</div>
<div class="outputcontainer">
<h3>OUTPUT:</h3>
<div class="outputbox">
<p id="outputqueue"></p>
</div>
<div class="ioboxes outputbox">
<p id="outputqueue"></p>
</div>
<!-- <input type="text" name="inputqueue" value="" /> -->
</div>
<h3>MEMORY:</h3>
@ -69,7 +76,12 @@ HALT
<td>0</td>
</tr>
</table>
<p id="errormessage"></p>
<p id="messagebox"></p>
</div>
<div>
<h3>currently loaded program:</h3>
<div class="ioboxes" id="progbox"></div>
</div>
</div>
@ -77,9 +89,17 @@ HALT
<button id="load" type="button">Load</button>
<button id="run" type="button">Run</button>
<button id="run1" type="button">Run single step</button>
<button id="reset" type="button">Reset memory</button>
<button id="reset" type="button">Reset</button>
<!-- <button id="run1" type="button">Reset </button> -->
</div>
<details>
<summary>What is this??</summary>
<p>This is a register architecture machine emulator. The full specification can be found <a href="https://git.dekedin.me/raphy/RAM-emu/src/branch/master/ISA.md">here</a>.</p>
<h3>I found a bug. What do I do?</h3>
<p>Contact info can be found on <a href="https://dekedin.me/about">this page.</a></p>
<h3>This website looks very ugly!! I am a web developer and I think I can do better.</h3>
<p>I'm VERY GLAD! contact me (link above) or open a pull request<a href="https://git.dekedin.me/raphy/RAM-emu">here</a>.</p>
</details>
</div>
</div>
</body>

View File

@ -72,12 +72,13 @@ impl Default for CPU {
impl CPU {
/// Exposes the state of the CPU:
/// Returns a triplet of vectors, corresponding to:
/// (entire memory, input queue, output queue)
pub fn exposestate(&self) -> (Vec<u32>, Vec<u32>, Vec<u32>) {
/// (entire memory, input queue, output queue, current_program)
pub fn exposestate(&self) -> (Vec<u32>, Vec<u32>, Vec<u32>, Vec<Instruction>) {
return (
self.regmemory.clone(),
self.input_filo.clone().into(),
self.output_filo.clone().into(),
self.program.clone(),
);
}
@ -250,7 +251,7 @@ impl CPU {
if accval == 0 {
self.writememory(pc, u - 1)?;
return Ok(());
}
}
}
JGTZ(u) => {
@ -259,7 +260,7 @@ impl CPU {
if accval > 0 {
self.writememory(pc, u - 1)?;
return Ok(());
}
}
}
// NON DOCUMENTED!
@ -270,8 +271,13 @@ impl CPU {
return Ok(());
}
HALT => {self.stopped = true; return Ok(())}
HALT => {
self.stopped = true;
self.writememory(pc, pc_val + 1)?;
return Ok(());
} // manually increase pc, without checking.
};
self.pc_increase()?;
return Ok(());
}
@ -281,7 +287,7 @@ impl CPU {
pub fn exec(&mut self) -> Result<(), CpuError> {
while !self.stopped {
self.execone()?;
self.steps+=1;
self.steps += 1;
}
return Ok(());

View File

@ -1,5 +1,5 @@
use crate::parser::{parse_line, parse_program, ParseError};
use js_sys::Uint32Array;
use js_sys::{Uint32Array, Array};
use wasm_bindgen::prelude::*;
use super::cpu::*;
@ -33,31 +33,51 @@ impl WrapCpu {
};
}
pub fn reset(&mut self) {
self.cpu = CPU::default();
}
// view
pub fn showmem(&self) -> Uint32Array {
let (k, _, _) = self.cpu.exposestate();
let (k, _, _, _) = self.cpu.exposestate();
return Uint32Array::from(&k[..]);
}
pub fn showinput(&self) -> Uint32Array {
let (_, k, _) = self.cpu.exposestate();
let (_, k, _, _) = self.cpu.exposestate();
return Uint32Array::from(&k[..]);
}
pub fn showoutput(&self) -> Uint32Array {
let (_, _, k) = self.cpu.exposestate();
let (_, _, k, _) = self.cpu.exposestate();
return Uint32Array::from(&k[..]);
}
pub fn showprogram(&self) -> Array {
let (_, _, _, k) = self.cpu.exposestate();
let arr = Array::new_with_length(k.len() as u32);
for i in 0..arr.length() {
let s = JsValue::from_str(&format!("{:?}", k[i as usize]));
arr.set(i, s);
}
return arr;
}
pub fn add_input(&mut self, x: u32) {
self.cpu.add_input(x)
}
pub fn one_step(&mut self) {
match self.cpu.execone() {
Ok(()) => {}
Err(k) => cpuErrDispatch(k),
};
if !self.cpu.stopped {
match self.cpu.execone() {
Ok(()) => {}
Err(k) => cpuErrDispatch(k),
};
} else {
signalerror("The program reached halt. All good!", None);
}
}

View File

@ -81,7 +81,7 @@ pub fn main() {
fn showmem(cpu: &CPU) {
print!("Memory: ");
let (k, _, _) = cpu.exposestate();
let (k, _, _, _) = cpu.exposestate();
for i in 0..k.len() - 1 {
print!(" {} |", k[i])
}
@ -90,7 +90,7 @@ fn showmem(cpu: &CPU) {
fn showinput(cpu: &CPU) {
print!("Input: ");
let (_, k, _) = cpu.exposestate();
let (_, k, _, _) = cpu.exposestate();
for i in 0..k.len() {
print!(" {} ", k[i])
}
@ -99,7 +99,7 @@ fn showinput(cpu: &CPU) {
fn showoutput(cpu: &CPU) {
print!("Output: ");
let (_, _, k) = cpu.exposestate();
let (_, _, k, _) = cpu.exposestate();
for i in 0..k.len() {
print!(" {} ", k[i])
}

View File

@ -82,22 +82,22 @@ pub fn parse_line(line: &str) -> Option<Instruction> {
// COULD BE BETTER!!!!!!!!!
let patternspairs = [
(FnWrap::new(|x| READ(x.parse().unwrap())), r"READ\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| WRITE(x.parse().unwrap())), r"WRITE\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| LOAD(x.parse().unwrap())), r"LOAD\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| READ(x.parse().unwrap())), r"^READ\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| WRITE(x.parse().unwrap())), r"^WRITE\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| LOAD(x.parse().unwrap())), r"^LOAD\s+(\d+)\s*(?:#.*)?$"),
(
FnWrap::new(|x| LOADI(x.parse().unwrap())),
r"LOAD\s+=\s*(\d+)\s*#?.*",
r"^LOAD\s+=\s*(\d+)\s*(?:#.*)?$",
),
(FnWrap::new(|x| STORE(x.parse().unwrap())), r"STORE\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| ADD(x.parse().unwrap())), r"ADD\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| ADDI(x.parse().unwrap())), r"ADD\s=\s*(\d+)\s*#?.*"),
(FnWrap::new(|x| SUB(x.parse().unwrap())), r"SUB\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| SUBI(x.parse().unwrap())), r"SUB\s=\s*(\d+)\s*#?.*"),
(FnWrap::new(|x| JUMP(x.parse().unwrap())), r"JUMP\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| JZERO(x.parse().unwrap())), r"JZERO\s+(\d+)\s*#?.*"),
(FnWrap::new(|x| JGTZ(x.parse().unwrap())), r"JGTZ\s+(\d+)\s*#?.*"),
(FnWrap::new(|_| HALT), r"HALT"),
(FnWrap::new(|x| STORE(x.parse().unwrap())), r"^STORE\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| ADD(x.parse().unwrap())), r"^ADD\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| ADDI(x.parse().unwrap())), r"^ADD\s=\s*(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| SUB(x.parse().unwrap())), r"^SUB\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| SUBI(x.parse().unwrap())), r"^SUB\s=\s*(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| JUMP(x.parse().unwrap())), r"^JUMP\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| JZERO(x.parse().unwrap())), r"^JZERO\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|x| JGTZ(x.parse().unwrap())), r"^JGTZ\s+(\d+)\s*(?:#.*)?$"),
(FnWrap::new(|_| HALT), r"^HALT\s*(?:#.*)?$"),
];
// Compile a set matching any of our patterns.

View File

@ -10,25 +10,26 @@ function $(x: string) {
// error signaling:
export function signalerror(msg: string, _l: number | null) {
let errbox = $("errormessage");
export function signalerror(msg: string, l: number | null) {
let errbox = $("messagebox");
if (errbox) {
errbox.innerHTML = msg;
}
if (l) {
highlightError(l, "progbox")
}
}
export function signalparseerr(x: number) {
console.log("hey!", x);
// $("#errormessage").val("Parser error at line " + x.toString() + "!");
let errmsg = $("errormessage");
let errmsg = $("messagebox");
if (errmsg) {
errmsg.innerHTML = "Parser error at line " + x.toString() + "!";
}
highlightError(x);
highlightError(x, "highlighting");
}
function highlightError(x: number) {
let highlights = $("highlighting");
function highlightError(x: number, box: string) {
let highlights = $(box);
let text = highlights?.innerHTML;
if (text != null && highlights != null) {
let lines = text.toString().split("\n");

View File

@ -10,6 +10,8 @@ let highlights = $("#highlighting");
textarea.on({
input: handleInput,
keyup: handleInput,
onchange: handleInput,
scroll: handleScroll,
});
@ -17,7 +19,7 @@ handleInput(); // immediately calling this the first time to highlight the sampl
function handleInput() {
var text = textarea.val();
if (text) {
if (text != undefined) {
var highlightedText = applyHighlights(text.toString());
highlights.html(highlightedText);
}
@ -25,22 +27,21 @@ function handleInput() {
function applyHighlights(text: string) {
let res = text
.replace(/(READ\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(WRITE\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(LOAD\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(LOAD\s+=\s*\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(STORE\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(ADD\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(ADD\s=\s*\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(SUB\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(SUB\s=\s*\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(JUMP\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(JZERO\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(JGTZ\s+\d+)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(HALT)/gi, '<mark class="goodcode">$1</mark>')
.replace(/(#.*\n?\$?)/gi, '<mark class="comment">$1</mark>');
return res;
.replace(/^(READ\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(WRITE\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(LOAD\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(LOAD\s+=\s*\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(STORE\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(ADD\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(ADD\s=\s*\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(SUB\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(SUB\s=\s*\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(JUMP\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(JZERO\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(JGTZ\s+\d+)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/^(HALT)(\s*(#.*)?)?$/mg, '<mark class="goodcode">$1</mark>$2')
.replace(/(#.*\n?\$?)/mg, '<mark class="comment">$1</mark>$2');
return res + "\n";
}
function handleScroll() {
@ -52,38 +53,78 @@ function handleScroll() {
}
}
// setting up input box:
$("#inputqueue").on({
input: restrictNumeric,
paste: restrictNumeric,
})
function restrictNumeric() {
var text = $("#inputqueue").val();
if (typeof(text) == 'string') {
let newtext = text.replaceAll(/[^0-9 ]/g, '');
$("#inputqueue").val(newtext)
}
}
// setting up buttons.
let load = $("#load");
let run = $("#run");
let run1 = $("#run1");
load.on({
$("#load").on({
click: function () {
$("#messagebox").html("Program loaded!");
handleInput(); // immediately calling this the first time to highlight the sample code.
cpu.reset();
loadPrg();
loadInput();
writeMem();
writeProgram();
writeInput();
writeOutput();
highlightCurrent();
},
});
run.on({
$("#run").on({
click: function () {
$("#messagebox").html("Running the whole program!");
cpu.run();
writeMem();
writeOutput();
writeInput();
highlightCurrent();
},
});
run1.on({
$("#run1").on({
click: function () {
$("#messagebox").html("Running a single step!");
cpu.one_step();
writeMem();
writeOutput();
writeInput();
highlightCurrent();
},
});
$("#reset").on({
click: function () {
$("#messagebox").html("Resetting the whole machine!");
cpu.reset();
writeMem();
writeInput();
writeOutput();
writeProgram();
highlightCurrent();
}
})
function writeMem() {
let mem = cpu.showmem();
@ -95,35 +136,41 @@ function writeMem() {
}
function writeOutput() {
let out = cpu.showoutput();
// console.log(out);
let out = cpu.showoutput().join(" ");
let outputbox = $("#outputqueue");
for (let index = 0; index < out.length; index++) {
outputbox.html(outputbox.html() + " " + out[index].toString());
}
outputbox.html(out);
}
function writeInput() {
let input = cpu.showinput();
let input = cpu.showinput().reverse().join(" ");
let inputbox = $("#inputqueue");
for (let index = 0; index < input.length; index++) {
inputbox.val(inputbox.val() + " " + input[index].toString());
}
inputbox.val(input);
}
function writeProgram() {
let prog = cpu.showprogram().join("<br>");
let progbox = $("#progbox");
progbox.html(prog);
// for (let index = 0; index < prog.length; index++) {
// progbox.val(progbox.val() + " " + prog[index]);
// }
}
function loadInput() {
// let input = cpu.showinput();
let inputbox = $("#inputqueue");
let inputboxtext = $("#inputqueue").val();
if (typeof inputboxtext == "string") {
// let inputqueue = inputboxtext.split(" ").filter(function (x) {
// x != " ";
let inputqueue = inputboxtext.split(" ");
let inputqueue = inputboxtext.split(" ").reverse();
console.log(inputqueue);
@ -140,3 +187,17 @@ function loadPrg() {
cpu.load_program(prg);
}
}
function highlightCurrent() {
let current = cpu.showmem()[9];
writeProgram();
let progbox = $("#progbox");
let text = progbox.html();
if (progbox != null && text != null && current > 0) {
let lines = text.toString().split("<br>");
lines[current - 1] = '<mark class="goodcode">' + lines[current - 1] + '</mark>';
var newtext = lines.join("<br>");
progbox.html(newtext);
}
}