mirror of
https://github.com/Noratrieb/crapderive.git
synced 2026-01-14 16:45:08 +01:00
resolve backwards labels
This commit is contained in:
parent
c5e0e50989
commit
86f7d33c13
1 changed files with 38 additions and 9 deletions
47
src/ir.rs
47
src/ir.rs
|
|
@ -1,4 +1,5 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use dbg_pls::DebugPls;
|
use dbg_pls::DebugPls;
|
||||||
use logos::Span;
|
use logos::Span;
|
||||||
|
|
@ -48,6 +49,9 @@ struct CompileCtx {
|
||||||
stmts: Vec<Stmt>,
|
stmts: Vec<Stmt>,
|
||||||
spans: Vec<Span>,
|
spans: Vec<Span>,
|
||||||
labels: HashMap<String, (Location, Span)>,
|
labels: HashMap<String, (Location, Span)>,
|
||||||
|
/// a vector of index and label name into `stmts` that contain references to labels that may
|
||||||
|
/// be declared after them
|
||||||
|
location_to_resolve: Vec<(usize, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompileCtx {
|
impl CompileCtx {
|
||||||
|
|
@ -55,6 +59,12 @@ impl CompileCtx {
|
||||||
for stmt in ast {
|
for stmt in ast {
|
||||||
self.compile_stmt(stmt)?;
|
self.compile_stmt(stmt)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let locations = mem::take(&mut self.location_to_resolve);
|
||||||
|
for (index, label) in locations {
|
||||||
|
self.resolve_location(index, &label)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,11 +96,11 @@ impl CompileCtx {
|
||||||
Stmt::Div { to, value }
|
Stmt::Div { to, value }
|
||||||
}
|
}
|
||||||
StmtKind::Jmp { to } => {
|
StmtKind::Jmp { to } => {
|
||||||
let to = self.compile_location(to)?;
|
let to = self.compile_location(to, self.stmts.len())?;
|
||||||
Stmt::Jmp { to }
|
Stmt::Jmp { to }
|
||||||
}
|
}
|
||||||
StmtKind::Je { to } => {
|
StmtKind::Je { to } => {
|
||||||
let to = self.compile_location(to)?;
|
let to = self.compile_location(to, self.stmts.len())?;
|
||||||
Stmt::Je { to }
|
Stmt::Je { to }
|
||||||
}
|
}
|
||||||
StmtKind::Cmp { lhs, rhs } => {
|
StmtKind::Cmp { lhs, rhs } => {
|
||||||
|
|
@ -143,16 +153,17 @@ impl CompileCtx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_label_position(&self, label: &str, span: Span) -> Result<Location> {
|
fn get_label_position(&mut self, label: String, index: usize) -> Location {
|
||||||
let location = self.labels.get(label);
|
let location = self.labels.get(&label);
|
||||||
location
|
location.map(|(location, _)| *location).unwrap_or_else(|| {
|
||||||
.map(|(location,_)| *location)
|
self.location_to_resolve.push((index, label));
|
||||||
.ok_or_else(|| CompilerError::simple(format!("label `{label}` not found"), span))
|
Location { index: usize::MAX }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_location(&mut self, expr: parser::Expr) -> Result<Location> {
|
fn compile_location(&mut self, expr: parser::Expr, index: usize) -> Result<Location> {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Symbol(sym) => Ok(self.get_label_position(&sym, expr.span)?),
|
ExprKind::Symbol(sym) => Ok(self.get_label_position(sym, index)),
|
||||||
ExprKind::Register(_) => Err(CompilerError::simple(
|
ExprKind::Register(_) => Err(CompilerError::simple(
|
||||||
"cannot jump to a register".to_string(),
|
"cannot jump to a register".to_string(),
|
||||||
expr.span,
|
expr.span,
|
||||||
|
|
@ -182,6 +193,23 @@ impl CompileCtx {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_location(&mut self, index: usize, label: &str) -> Result<()>{
|
||||||
|
let (location, _) = self.labels.get(label).ok_or_else(|| {
|
||||||
|
CompilerError::simple(
|
||||||
|
format!("label {label} not found"),
|
||||||
|
self.spans[index].clone(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let instr = &mut self.stmts[index];
|
||||||
|
match instr {
|
||||||
|
Stmt::Je { to } => *to = *location,
|
||||||
|
Stmt::Jmp { to } => *to = *location,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(ast: impl Iterator<Item = parser::Stmt>) -> Result<(Vec<Stmt>, Vec<Span>)> {
|
pub fn compile(ast: impl Iterator<Item = parser::Stmt>) -> Result<(Vec<Stmt>, Vec<Span>)> {
|
||||||
|
|
@ -189,6 +217,7 @@ pub fn compile(ast: impl Iterator<Item = parser::Stmt>) -> Result<(Vec<Stmt>, Ve
|
||||||
stmts: Vec::new(),
|
stmts: Vec::new(),
|
||||||
spans: Vec::new(),
|
spans: Vec::new(),
|
||||||
labels: HashMap::new(),
|
labels: HashMap::new(),
|
||||||
|
location_to_resolve: Vec::new(),
|
||||||
};
|
};
|
||||||
ctx.compile(ast)?;
|
ctx.compile(ast)?;
|
||||||
Ok((ctx.stmts, ctx.spans))
|
Ok((ctx.stmts, ctx.spans))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue