pub mod context;
use std::mem;
use crate::checker::types::TypeStore;
use crate::ir::{Instr, IR};
use crate::source::Source;
use crate::{ast, ir};
use context::Context;
mod build_assign_expr;
mod build_binary_expr;
mod build_borrow_expr;
mod build_call_expr;
mod build_deref_expr;
mod build_expr;
mod build_associate_expr;
mod build_block_stmt;
mod build_extern_fn_stmt;
mod build_fn_stmt;
mod build_ident_expr;
mod build_if_expr;
mod build_impl_stmt;
mod build_let_stmt;
mod build_literal;
mod build_member_expr;
mod build_ret_stmt;
mod build_struct_def_stmt;
mod build_struct_init_expr;
mod build_type;
mod build_type_def_stmt;
mod build_utils;
pub struct Builder<'br> {
ctx: Context,
ir: IR,
type_store: &'br TypeStore,
source: &'br Source,
}
impl<'br> Builder<'br> {
pub fn new(type_store: &'br TypeStore, source: &'br Source) -> Self {
Self { ctx: Context::new(), ir: IR::new(), source, type_store }
}
pub fn build(&mut self, program: &mut ast::Program) -> IR {
for stmt in program.stmts.iter_mut() {
self.build_stmt(stmt);
}
mem::take(&mut self.ir)
}
pub fn push_function_with_blocks(&mut self, mut function: ir::Function) {
let blocks = self.ctx.block.take_blocks();
function.extend_blocks(blocks);
self.ir.add_function(function);
}
pub fn drop_local_function_values(&mut self, ret_value: Option<&str>) {
for value in self.ctx.get_free_values() {
if ret_value.map(|ret_value| value.value.as_str() != ret_value).unwrap_or(true) {
self.ctx.block.add_instr(Instr::Drop(value));
}
}
}
fn build_stmt(&mut self, stmt: &mut ast::Stmt) {
match stmt {
ast::Stmt::Let(let_stmt) => self.build_let_stmt(let_stmt),
ast::Stmt::Fn(fn_stmt) => self.build_fn_stmt(fn_stmt),
ast::Stmt::ExternFn(extern_fn_stmt) => self.build_extern_fn_stmt(extern_fn_stmt),
ast::Stmt::Block(block_stmt) => self.build_block_stmt(block_stmt),
ast::Stmt::Ret(ret_stmt) => self.build_ret_stmt(ret_stmt),
ast::Stmt::TypeDef(type_def) => self.build_type_def_stmt(type_def),
ast::Stmt::Impl(impl_stmt) => self.build_impl_stmt(impl_stmt),
ast::Stmt::Expr(expr) => {
let _ = self.build_expr(expr);
}
_ => todo!("code {:#?}", stmt),
}
}
}