lemonlang 0.0.3

an experimental, modern, purely safe, programming language.
use inkwell::{
	basic_block::BasicBlock,
	values::{BasicValueEnum, PointerValue},
};
use scope::Scope;

use crate::report::throw_llvm_error;
mod scope;

pub struct Env<'ll> {
	pub function_scope: Vec<Scope<'ll>>,
}

impl<'ll> Env<'ll> {
	pub fn new() -> Self {
		Self { function_scope: Vec::new() }
	}

	pub fn enter_function_scope(&mut self) {
		self.function_scope.push(Scope::new());
	}

	pub fn exit_function_scope(&mut self) {
		self.function_scope.pop();
	}

	pub fn get_current_scope(&mut self) -> &mut Scope<'ll> {
		self.function_scope.last_mut().expect("no function scope")
	}

	pub fn get_block(&mut self, name: &str) -> Option<&BasicBlock<'ll>> {
		self.get_current_scope().get_block(name)
	}

	pub fn set_block(&mut self, name: &str, block: BasicBlock<'ll>) {
		self.get_current_scope().set_block(name, block);
	}

	pub fn get_value(&mut self, name: &str) -> Option<&BasicValueEnum<'ll>> {
		self.get_current_scope().get_value(name)
	}

	pub fn set_value(&mut self, name: &str, value: BasicValueEnum<'ll>) {
		self.get_current_scope().set_value(name, value);
	}

	pub fn get_ptr_value(&mut self, name: &str) -> Option<PointerValue<'ll>> {
		self.get_current_scope().get_ptr_value(name)
	}

	pub fn get_ptr_value_unwrap(&mut self, name: &str) -> PointerValue<'ll> {
		if let Some(value) = self.get_ptr_value(name) {
			return value;
		};
		throw_llvm_error(format!("no ptr value named {}", name));
	}

	pub fn get_temp(&mut self) -> String {
		self.get_current_scope().get_temp()
	}
}