Skip to content

Commit 405a3f2

Browse files
committed
Turn fixups into a proper enum
This feels clearer and leaves room for implementing a different type of fixup required for function and subroutine calls.
1 parent cbb0a43 commit 405a3f2

1 file changed

Lines changed: 40 additions & 26 deletions

File tree

core/src/compiler/mod.rs

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -242,39 +242,33 @@ impl SymbolsTable {
242242
}
243243
}
244244

245-
/// Indicates the type of fixup required at the address.
246-
enum FixupType {
247-
Gosub,
248-
Goto,
249-
OnError,
250-
}
251-
252245
/// Describes a location in the code needs fixing up after all addresses have been laid out.
253-
struct Fixup {
254-
target: String,
255-
target_pos: LineCol,
256-
ftype: FixupType,
246+
#[allow(clippy::enum_variant_names)]
247+
enum Fixup {
248+
CallAddr(String, LineCol),
249+
GotoAddr(String, LineCol),
250+
OnErrorGotoAddr(String, LineCol),
257251
}
258252

259253
impl Fixup {
260254
/// Constructs a `Fixup` for an `EXIT` instruction.
261255
fn from_exit(target: String, span: ExitSpan) -> Self {
262-
Self { target, target_pos: span.pos, ftype: FixupType::Goto }
256+
Self::GotoAddr(target, span.pos)
263257
}
264258

265259
/// Constructs a `Fixup` for a `GOSUB` instruction.
266260
fn from_gosub(span: GotoSpan) -> Self {
267-
Self { target: span.target, target_pos: span.target_pos, ftype: FixupType::Gosub }
261+
Self::CallAddr(span.target, span.target_pos)
268262
}
269263

270264
/// Constructs a `Fixup` for a `GOTO` instruction.
271265
fn from_goto(span: GotoSpan) -> Self {
272-
Self { target: span.target, target_pos: span.target_pos, ftype: FixupType::Goto }
266+
Self::GotoAddr(span.target, span.target_pos)
273267
}
274268

275269
/// Constructs a `Fixup` for a `ON ERROR GOTO` instruction.
276270
fn from_on_error(span: GotoSpan) -> Self {
277-
Self { target: span.target, target_pos: span.target_pos, ftype: FixupType::OnError }
271+
Self::OnErrorGotoAddr(span.target, span.target_pos)
278272
}
279273
}
280274

@@ -1150,6 +1144,18 @@ impl Compiler {
11501144
Ok(())
11511145
}
11521146

1147+
/// Gets the address of a label.
1148+
fn get_label_addr(
1149+
labels: &HashMap<String, Address>,
1150+
label: String,
1151+
pos: LineCol,
1152+
) -> Result<usize> {
1153+
match labels.get(&label) {
1154+
Some(addr) => Ok(*addr),
1155+
None => Err(Error::UnknownLabel(pos, label.to_owned())),
1156+
}
1157+
}
1158+
11531159
/// Finishes compilation and returns the image representing the compiled program.
11541160
#[allow(clippy::wrong_self_convention)]
11551161
fn to_image(mut self) -> Result<(Image, SymbolsTable)> {
@@ -1158,20 +1164,28 @@ impl Compiler {
11581164
}
11591165

11601166
for (pc, fixup) in self.fixups {
1161-
let addr = match self.labels.get(&fixup.target) {
1162-
Some(addr) => *addr,
1163-
None => {
1164-
return Err(Error::UnknownLabel(fixup.target_pos, fixup.target));
1167+
let new_instr = match fixup {
1168+
Fixup::CallAddr(label, pos) => {
1169+
let addr = Self::get_label_addr(&self.labels, label, pos)?;
1170+
Instruction::Call(JumpISpan { addr })
11651171
}
1166-
};
11671172

1168-
match fixup.ftype {
1169-
FixupType::Gosub => self.instrs[pc] = Instruction::Call(JumpISpan { addr }),
1170-
FixupType::Goto => self.instrs[pc] = Instruction::Jump(JumpISpan { addr }),
1171-
FixupType::OnError => {
1172-
self.instrs[pc] = Instruction::SetErrorHandler(ErrorHandlerISpan::Jump(addr))
1173+
Fixup::GotoAddr(label, pos) => {
1174+
let addr = Self::get_label_addr(&self.labels, label, pos)?;
1175+
Instruction::Jump(JumpISpan { addr })
11731176
}
1174-
}
1177+
1178+
Fixup::OnErrorGotoAddr(label, pos) => {
1179+
let addr = Self::get_label_addr(&self.labels, label, pos)?;
1180+
Instruction::SetErrorHandler(ErrorHandlerISpan::Jump(addr))
1181+
}
1182+
};
1183+
debug_assert_eq!(
1184+
std::mem::discriminant(&Instruction::Nop),
1185+
std::mem::discriminant(&self.instrs[pc]),
1186+
"Fixup target address must contain a Nop instruction",
1187+
);
1188+
self.instrs[pc] = new_instr;
11751189
}
11761190
let image = Image { instrs: self.instrs, data: self.data };
11771191
Ok((image, self.symtable))

0 commit comments

Comments
 (0)