lemonlang 0.0.3

an experimental, modern, purely safe, programming language.
#![allow(unused_imports, dead_code, unused_variables)]
use std::mem;

use super::ir::{self};
use crate::{
	ast,
	checker::types::{self, TypeId},
	report::throw_ir_build_error,
};

use ircontext::IrContext;
mod build_assign_expr;
mod build_binary_expr;
mod build_block_stmt;
mod build_borrow_expr;
mod build_call_expr;
mod build_const_del_stmt;
mod build_const_fn_stmt;
mod build_deref_expr;
mod build_expr;
mod build_extern_fn;
mod build_fn_stmt;
mod build_for_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_init_expr;
mod build_type_def_stmt;
mod build_while_stmt;
pub mod ircontext;
pub struct Builder<'br> {
	pub type_store: &'br types::TypeStore,
	pub ir_ctx: IrContext,
	pub root: ir::Root,
}

impl<'br> Builder<'br> {
	pub fn new(type_store: &'br types::TypeStore) -> Self {
		let ir_ctx = IrContext::new();
		Self { ir_ctx, root: ir::Root::new(), type_store }
	}

	pub fn add_fn(&mut self, fn_ir: ir::Fn) {
		self.root.add_fn(fn_ir);
	}

	pub fn add_struct(&mut self, struct_ir: ir::StructInstr) {
		self.root.add_struct(struct_ir);
	}

	pub fn add_blocks(&mut self, blocks: Vec<ir::Block>) {
		self.root.add_blocks(blocks);
	}

	pub fn exit_fn_scope(&mut self) {}

	pub fn build(&mut self, program: &mut ast::Program) -> ir::Root {
		for stmt in program.stmts.iter_mut() {
			self.build_stmt(stmt);
		}
		mem::take(&mut self.root)
	}

	pub fn get_type_id(&self, id: Option<TypeId>) -> TypeId {
		match id {
			Some(id) => id,
			None => throw_ir_build_error("type_id not found"),
		}
	}

	fn end_fn_scope(&mut self) {
		let blocks = self.ir_ctx.reset_fn_scope();
		self.root.add_blocks(blocks);
		self.ir_ctx.exit_scope();
		self.ir_ctx.set_ret_type(None)
	}

	fn build_stmt(&mut self, stmt: &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, None),
			ast::Stmt::Block(block_stmt) => self.build_block_stmt(block_stmt),
			ast::Stmt::While(while_stmt) => self.build_while_stmt(while_stmt),
			ast::Stmt::For(for_stmt) => self.build_for_stmt(for_stmt),
			ast::Stmt::ConstDel(const_del) => self.build_const_del_stmt(const_del),
			ast::Stmt::ConstFn(const_fn) => self.build_const_fn_stmt(const_fn),
			ast::Stmt::Ret(ret_stmt) => self.build_ret_stmt(ret_stmt),
			ast::Stmt::ExternFn(extern_fn) => self.build_extern_fn(extern_fn),
			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) => {
				self.build_expr(expr);
			}
		}
	}
}