feat: add support for let statements
This commit is contained in:
+40
-8
@@ -83,8 +83,8 @@ struct FuncBuilder {
|
||||
/// Counter for generating unique `BlockId`s.
|
||||
next_block_id: usize,
|
||||
|
||||
/// Mapping from user-defined variable names to their corresponding `LocalId`.
|
||||
vars: HashMap<String, LocalId>,
|
||||
/// Scoped mapping from user-defined variable names to their corresponding `LocalId`.
|
||||
scopes: Vec<HashMap<String, LocalId>>,
|
||||
}
|
||||
|
||||
impl FuncBuilder {
|
||||
@@ -99,10 +99,18 @@ impl FuncBuilder {
|
||||
current_block: None,
|
||||
current_statements: Vec::new(),
|
||||
next_block_id: 0,
|
||||
vars: HashMap::new(),
|
||||
scopes: vec![HashMap::new()],
|
||||
}
|
||||
}
|
||||
|
||||
fn enter_scope(&mut self) {
|
||||
self.scopes.push(HashMap::new());
|
||||
}
|
||||
|
||||
fn leave_scope(&mut self) {
|
||||
self.scopes.pop();
|
||||
}
|
||||
|
||||
/// Registers a new user-defined local variable and returns its `LocalId`.
|
||||
fn new_local(&mut self, name: String, ty: Ty) -> LocalId {
|
||||
let id = LocalId(self.locals.len());
|
||||
@@ -112,7 +120,7 @@ impl FuncBuilder {
|
||||
mutable: false,
|
||||
name: Some(name.clone()),
|
||||
});
|
||||
self.vars.insert(name, id);
|
||||
self.scopes.last_mut().unwrap().insert(name, id);
|
||||
id
|
||||
}
|
||||
|
||||
@@ -128,6 +136,15 @@ impl FuncBuilder {
|
||||
id
|
||||
}
|
||||
|
||||
fn lookup(&self, name: &str) -> LocalId {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
if let Some(id) = scope.get(name) {
|
||||
return *id;
|
||||
}
|
||||
}
|
||||
panic!("undeclared variable `{}` in MIR lowering", name);
|
||||
}
|
||||
|
||||
/// Allocates a new, empty basic block and returns its `BlockId`.
|
||||
fn new_block(&mut self) -> BlockId {
|
||||
let id = BlockId(self.next_block_id);
|
||||
@@ -180,9 +197,11 @@ impl FuncBuilder {
|
||||
fn lower_stmt(&mut self, stmt: &TypedStmt) {
|
||||
match &stmt.kind {
|
||||
TypedStmtKind::Compound { inner } => {
|
||||
self.enter_scope();
|
||||
for s in inner {
|
||||
self.lower_stmt(s);
|
||||
}
|
||||
self.leave_scope();
|
||||
}
|
||||
TypedStmtKind::If {
|
||||
condition,
|
||||
@@ -237,6 +256,22 @@ impl FuncBuilder {
|
||||
span: stmt.span,
|
||||
});
|
||||
}
|
||||
TypedStmtKind::Let {
|
||||
name,
|
||||
name_span: _,
|
||||
ty,
|
||||
initializer,
|
||||
} => {
|
||||
let local_id = self.new_local(name.clone(), ty.clone());
|
||||
|
||||
if let Some(init_expr) = initializer {
|
||||
let val_op = self.lower_expr(init_expr);
|
||||
self.emit_stmt(Statement {
|
||||
kind: StatementKind::Assign(local_id, Rvalue::Use(val_op)),
|
||||
span: stmt.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,10 +279,7 @@ impl FuncBuilder {
|
||||
fn lower_expr(&mut self, expr: &TypedExpr) -> Operand {
|
||||
match &expr.kind {
|
||||
TypedExprKind::Identifier { name } => {
|
||||
let local = *self
|
||||
.vars
|
||||
.get(name)
|
||||
.expect("undeclared variable in MIR lowering");
|
||||
let local = self.lookup(name);
|
||||
Operand::Copy(local)
|
||||
}
|
||||
TypedExprKind::Integer { value } => {
|
||||
|
||||
Reference in New Issue
Block a user