use std::{borrow::Borrow, ops::Deref};
use log::Log;
use melior::{Context, diagnostic::DiagnosticHandlerId, dialect::DialectRegistry};
use crate::{diagnostics::log_diagnostic, register_all_llzk_dialects};
pub struct LlzkContext {
ctx: Context,
diagnostics_handler: Option<DiagnosticHandlerId>,
_registry: DialectRegistry,
}
impl LlzkContext {
pub fn new() -> Self {
let mut llzk = Self::new_no_log();
llzk.log_diagnostics();
llzk
}
pub fn new_no_log() -> Self {
let ctx = Context::new();
let registry = DialectRegistry::new();
register_all_llzk_dialects(®istry);
ctx.append_dialect_registry(®istry);
ctx.load_all_available_dialects();
Self {
ctx,
diagnostics_handler: None,
_registry: registry,
}
}
pub fn log_diagnostics(&mut self) {
self.log_diagnostics_to_logger(log::logger());
}
pub fn log_diagnostics_to_logger(&mut self, logger: &dyn Log) {
self.stop_logging_diagnostics();
self.diagnostics_handler = Some(
self.ctx
.attach_diagnostic_handler(|diag| log_diagnostic(diag, logger)),
);
}
pub fn stop_logging_diagnostics(&mut self) {
if let Some(id) = self.diagnostics_handler.take() {
self.ctx.detach_diagnostic_handler(id);
}
}
}
impl Default for LlzkContext {
fn default() -> Self {
Self::new()
}
}
impl Deref for LlzkContext {
type Target = Context;
fn deref(&self) -> &Self::Target {
&self.ctx
}
}
impl Borrow<Context> for LlzkContext {
fn borrow(&self) -> &Context {
&self.ctx
}
}
impl AsRef<Context> for LlzkContext {
fn as_ref(&self) -> &Context {
&self.ctx
}
}
impl Drop for LlzkContext {
fn drop(&mut self) {
self.stop_logging_diagnostics();
}
}
impl std::fmt::Debug for LlzkContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LlzkContext")
.field("registered dialects", &self.registered_dialect_count())
.field("loaded dialects", &self.loaded_dialect_count())
.field("ctx", &self.ctx)
.field("registry", &self._registry)
.field("diagnostics_handler", &self.diagnostics_handler)
.finish()
}
}