sway_core/
obs_engine.rs

1use std::fmt::{Debug, Formatter, Result};
2use std::sync::Mutex;
3
4use sway_ir::Type;
5
6use crate::decl_engine::DeclRefFunction;
7use crate::language::parsed::MethodName;
8use crate::semantic_analysis::TypeCheckContext;
9use crate::{Engines, TypeBinding, TypeId, TypeInfo};
10
11pub trait Observer {
12    fn on_trace(&self, _msg: &str) {}
13
14    fn on_before_method_resolution(
15        &self,
16        _ctx: &TypeCheckContext<'_>,
17        _method_name: &TypeBinding<MethodName>,
18        _args_types: &[TypeId],
19    ) {
20    }
21
22    fn on_after_method_resolution(
23        &self,
24        _ctx: &TypeCheckContext<'_>,
25        _method_name: &TypeBinding<MethodName>,
26        _args_types: &[TypeId],
27        _new_ref: DeclRefFunction,
28        _new_type_id: TypeId,
29    ) {
30    }
31
32    fn on_after_ir_type_resolution(
33        &self,
34        _engines: &Engines,
35        _ctx: &sway_ir::Context,
36        _type_info: &TypeInfo,
37        _ir_type: &Type,
38    ) {
39    }
40}
41
42#[derive(Default)]
43pub struct ObservabilityEngine {
44    observer: Mutex<Option<Box<dyn Observer>>>,
45    trace: Mutex<bool>,
46}
47
48unsafe impl Send for ObservabilityEngine {}
49unsafe impl Sync for ObservabilityEngine {}
50
51impl Debug for ObservabilityEngine {
52    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
53        f.debug_struct("ObservabilityEngine")
54            .field("trace", &self.trace)
55            .finish()
56    }
57}
58
59impl ObservabilityEngine {
60    pub fn set_observer(&self, observer: Box<dyn Observer>) {
61        let mut obs = self.observer.lock().unwrap();
62        *obs = Some(observer);
63    }
64
65    pub fn raise_on_before_method_resolution(
66        &self,
67        ctx: &TypeCheckContext,
68        method_name: &TypeBinding<MethodName>,
69        arguments_types: &[TypeId],
70    ) {
71        if let Some(obs) = self.observer.lock().unwrap().as_mut() {
72            obs.on_before_method_resolution(ctx, method_name, arguments_types);
73        }
74    }
75
76    pub fn raise_on_after_method_resolution(
77        &self,
78        ctx: &TypeCheckContext,
79        method_name: &TypeBinding<MethodName>,
80        arguments_types: &[TypeId],
81        ref_function: DeclRefFunction,
82        tid: TypeId,
83    ) {
84        if let Some(obs) = self.observer.lock().unwrap().as_mut() {
85            obs.on_after_method_resolution(ctx, method_name, arguments_types, ref_function, tid);
86        }
87    }
88
89    pub fn raise_on_after_ir_type_resolution(
90        &self,
91        engines: &Engines,
92        ctx: &sway_ir::Context,
93        type_info: &TypeInfo,
94        ir_type: &Type,
95    ) {
96        if let Some(obs) = self.observer.lock().unwrap().as_mut() {
97            obs.on_after_ir_type_resolution(engines, ctx, type_info, ir_type);
98        }
99    }
100
101    pub(crate) fn trace(&self, get_txt: impl FnOnce() -> String) {
102        let trace = self.trace.lock().unwrap();
103        if *trace {
104            if let Some(obs) = self.observer.lock().unwrap().as_mut() {
105                obs.on_trace(&get_txt());
106            }
107        }
108    }
109
110    pub fn enable_trace(&self, enable: bool) {
111        let mut trace = self.trace.lock().unwrap();
112        *trace = enable
113    }
114}