Skip to main content

zen_engine/workspace/graph/
function.rs

1use std::hash::{Hash, Hasher};
2use std::sync::Arc;
3
4use zen_expression::variable::VariableType;
5
6use crate::workspace::db::Db;
7use crate::workspace::graph::ts_type::TsTypeParser;
8
9pub type FunctionTypeResolver = dyn Fn(&str, &VariableType) -> Option<String>;
10
11pub(crate) type FunctionKey = (u64, u64);
12
13#[derive(Debug, Clone)]
14pub struct FunctionResolutionRequest {
15    pub source: Arc<str>,
16    pub input: VariableType,
17}
18
19#[derive(Debug, Clone)]
20pub(crate) enum ResolvedFunction {
21    Type(VariableType),
22    Unresolved,
23}
24
25pub(crate) enum FunctionTypeOutcome {
26    Typed(VariableType),
27    Unresolved,
28    Unknown,
29}
30
31impl Db {
32    pub(crate) fn function_output_type(
33        &self,
34        source: &Arc<str>,
35        input: &VariableType,
36    ) -> FunctionTypeOutcome {
37        let key = Self::function_key(source, input);
38        let outcome = self.function_outcome(key, source, input);
39        self.graph_fn_record(key, self.function_state(key));
40        outcome
41    }
42
43    fn function_outcome(
44        &self,
45        key: FunctionKey,
46        source: &Arc<str>,
47        input: &VariableType,
48    ) -> FunctionTypeOutcome {
49        if let Some(entry) = self.function_types().borrow().get(&key) {
50            return match entry {
51                ResolvedFunction::Type(t) => FunctionTypeOutcome::Typed(t.shallow_clone()),
52                ResolvedFunction::Unresolved => FunctionTypeOutcome::Unresolved,
53            };
54        }
55
56        if let Some(resolver) = self.function_resolver().borrow().as_ref() {
57            let entry = match resolver(source.as_ref(), input) {
58                Some(ts) => match TsTypeParser::variable_type(&ts) {
59                    Some(resolved) => ResolvedFunction::Type(resolved),
60                    None => ResolvedFunction::Unresolved,
61                },
62                None => ResolvedFunction::Unresolved,
63            };
64            self.function_types()
65                .borrow_mut()
66                .insert(key, entry.clone());
67            return match entry {
68                ResolvedFunction::Type(t) => FunctionTypeOutcome::Typed(t),
69                ResolvedFunction::Unresolved => FunctionTypeOutcome::Unresolved,
70            };
71        }
72
73        if self.function_requested().borrow_mut().insert(key) {
74            self.function_requests()
75                .borrow_mut()
76                .push(FunctionResolutionRequest {
77                    source: source.clone(),
78                    input: input.shallow_clone(),
79                });
80        }
81        FunctionTypeOutcome::Unknown
82    }
83
84    pub fn function_resolution_requests(&self) -> Vec<FunctionResolutionRequest> {
85        let snap = self.snapshot();
86        let mut paths: Vec<Arc<str>> = snap.graphs.keys().cloned().collect();
87        paths.sort();
88        for path in &paths {
89            let _ = self.graph_analysis(path);
90        }
91        std::mem::take(&mut *self.function_requests().borrow_mut())
92    }
93
94    pub fn set_function_type(&self, source: &str, input: &VariableType, ts_type: Option<&str>) {
95        let key = Self::function_key_str(source, input);
96        let entry = match ts_type.and_then(TsTypeParser::variable_type) {
97            Some(resolved) => ResolvedFunction::Type(resolved),
98            None => ResolvedFunction::Unresolved,
99        };
100        self.function_types().borrow_mut().insert(key, entry);
101        self.invalidate_snapshot();
102    }
103
104    pub(crate) fn function_state(&self, key: FunctionKey) -> u64 {
105        match self.function_types().borrow().get(&key) {
106            None => 0,
107            Some(ResolvedFunction::Unresolved) => 1,
108            Some(ResolvedFunction::Type(t)) => {
109                let mut hasher = std::collections::hash_map::DefaultHasher::new();
110                2u8.hash(&mut hasher);
111                t.hash(&mut hasher);
112                hasher.finish()
113            }
114        }
115    }
116
117    pub(crate) fn function_key(source: &Arc<str>, input: &VariableType) -> FunctionKey {
118        Self::function_key_str(source.as_ref(), input)
119    }
120
121    fn function_key_str(source: &str, input: &VariableType) -> FunctionKey {
122        let mut source_hasher = std::collections::hash_map::DefaultHasher::new();
123        source.hash(&mut source_hasher);
124        let mut input_hasher = std::collections::hash_map::DefaultHasher::new();
125        input.hash(&mut input_hasher);
126        (source_hasher.finish(), input_hasher.finish())
127    }
128}