Skip to content

Commit b1e98d5

Browse files
committed
fix(lib): fixes rust-lang/rfcs#3535
- identify instructions with integer enum instead of function pointer - impl `IntoIterator` for `Memory` - output runtime errors even when `Source` is blank
1 parent e1697a0 commit b1e98d5

File tree

12 files changed

+197
-69
lines changed

12 files changed

+197
-69
lines changed

lib/examples/showoff.pasm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ ldm r0, #206
66
ldm r1, #5
77
call read
88
mov acc, 206
9+
ldm r0, #206
10+
ldm r1, #5
11+
call print
912
end
1013

1114
// procedure to print from linear memory

lib/src/compile.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ use bincode::{Decode, Encode};
2020
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
2121
#[derive(Debug)]
2222
struct CompiledInst {
23+
pub id: u64,
2324
pub inst: String,
2425
pub op: Op,
2526
}
2627

2728
impl CompiledInst {
28-
pub fn new(inst: String, op: Op) -> Self {
29-
Self { inst, op }
29+
pub fn new(id: u64, inst: String, op: Op) -> Self {
30+
Self { id, inst, op }
3031
}
3132
}
3233

@@ -60,10 +61,11 @@ impl CompiledProg {
6061
let prog = self
6162
.prog
6263
.into_iter()
63-
.map(|(addr, CompiledInst { inst, op })| {
64+
.map(|(addr, CompiledInst { inst, op, id })| {
6465
(
6566
addr,
6667
ExecInst::new(
68+
id,
6769
inst.parse::<T>()
6870
.unwrap_or_else(|s| panic!("{s}"))
6971
.as_func_ptr(),
@@ -92,14 +94,14 @@ where
9294

9395
let prog = prog
9496
.into_iter()
95-
.map(|(addr, ExecInst { func, op })| {
96-
let str_inst = match T::from_func_ptr(func) {
97+
.map(|(addr, ExecInst { op, id, .. })| {
98+
let str_inst = match T::from_id(id) {
9799
Ok(inst) => inst,
98100
Err(e) => panic!("{e}"),
99101
}
100102
.to_string();
101103

102-
(addr, CompiledInst::new(str_inst, op))
104+
(addr, CompiledInst::new(id, str_inst, op))
103105
})
104106
.collect();
105107

lib/src/exec/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ impl Source {
6565
writeln!(write, "Runtime Error:")?;
6666
writeln!(write)?;
6767

68+
if self.0.is_empty() {
69+
writeln!(write, "(source empty, error at position {pos})")?;
70+
return writeln!(write, "message: {err}");
71+
}
72+
6873
for (i, s) in self.0.iter().enumerate() {
6974
if pos == i {
7075
if let Some(prev) = self.0.get(i - 1) {

lib/src/exec/inst.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ pub type ExecFunc = fn(&mut Context, &Op) -> RtResult;
1414
/// Runtime representation of an instruction
1515
#[derive(Clone)]
1616
pub struct ExecInst {
17+
/// Identifies the instruction with an integer, fixes rust-lang/rfcs#3535
18+
pub id: u64,
1719
pub func: ExecFunc,
1820
pub op: Op,
1921
}
2022

2123
impl ExecInst {
22-
pub fn new(inst: ExecFunc, op: Op) -> Self {
23-
Self { func: inst, op }
24+
pub fn new(id: u64, inst: ExecFunc, op: Op) -> Self {
25+
Self { func: inst, op, id }
2426
}
2527
}
2628

lib/src/exec/memory.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ impl Memory {
4444
}
4545
}
4646

47+
impl<'a> IntoIterator for &'a Memory {
48+
type IntoIter = std::collections::btree_map::Iter<'a, usize, usize>;
49+
type Item = (&'a usize, &'a usize);
50+
fn into_iter(self) -> Self::IntoIter {
51+
self.iter()
52+
}
53+
}
54+
4755
impl<T> From<T> for Memory
4856
where
4957
T: Into<BTreeMap<usize, usize>>,

lib/src/exec/mod.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ impl Display for Context {
262262

263263
writeln!(f, "{:>6}: Memory {{", "mem")?;
264264

265-
for (addr, entry) in self.mem.iter() {
265+
for (addr, entry) in &self.mem {
266266
writeln!(f, "{addr:>8}: {entry},")?;
267267
}
268268

@@ -334,7 +334,7 @@ impl Executor {
334334

335335
trace!(
336336
"Executing instruction {} {}",
337-
T::from_func_ptr(inst.func).unwrap_or_else(|msg| panic!("{msg}")),
337+
T::from_id(inst.id).unwrap_or_else(|msg| panic!("{msg}")),
338338
inst.op
339339
);
340340

@@ -375,7 +375,7 @@ impl Executor {
375375
}
376376
}
377377

378-
pub fn display<T>(&self) -> Result<String, <T as FromStr>::Err>
378+
pub fn display_with_opcodes<T>(&self) -> Result<String, <T as FromStr>::Err>
379379
where
380380
T: InstSet,
381381
<T as FromStr>::Err: Display,
@@ -388,8 +388,8 @@ impl Executor {
388388

389389
writeln!(s, "Executor {{").unwrap();
390390

391-
for (addr, ExecInst { op, func }) in &self.prog {
392-
writeln!(s, "{addr:>6}: {func} {op}", func = T::from_func_ptr(*func)?).unwrap();
391+
for (addr, ExecInst { id, op, .. }) in &self.prog {
392+
writeln!(s, "{addr:>6}: {func} {op}", func = T::from_id(*id)?).unwrap();
393393
}
394394

395395
s.push('}');
@@ -435,12 +435,12 @@ fn exec() {
435435
let prog: BTreeMap<usize, ExecInst> = BTreeMap::from(
436436
// Division algorithm from examples/division.pasm
437437
[
438-
(0, ExecInst::new(arith::inc, "202".into())),
439-
(1, ExecInst::new(arith::add, "203,201".into())),
440-
(2, ExecInst::new(cmp::cmp, "203,204".into())),
441-
(3, ExecInst::new(cmp::jpn, "0".into())),
442-
(4, ExecInst::new(mov::ldd, "202".into())),
443-
(5, ExecInst::new(io::end, "".into())),
438+
(0, ExecInst::new(0, arith::inc, "202".into())),
439+
(1, ExecInst::new(0, arith::add, "203,201".into())),
440+
(2, ExecInst::new(0, cmp::cmp, "203,204".into())),
441+
(3, ExecInst::new(0, cmp::jpn, "0".into())),
442+
(4, ExecInst::new(0, mov::ldd, "202".into())),
443+
(5, ExecInst::new(0, io::end, "".into())),
444444
],
445445
);
446446

0 commit comments

Comments
 (0)