ryna/
cache.rs

1use std::{cell::{RefCell, RefMut}, hash::Hash};
2use rustc_hash::{FxHashMap, FxHashSet};
3use serde::{Deserialize, Serialize};
4
5use crate::{types::Type, parser::{RynaExpr, ImportType}, patterns::Pattern, config::Imports, compilation::CompiledRynaExpr};
6
7#[derive(Clone, Serialize, Deserialize)]
8pub struct Cache<K: Hash + PartialEq + Eq + Clone, V: Clone> {
9    inner: RefCell<FxHashMap<K, V>>
10}
11
12impl<K: Hash + PartialEq + Eq + Clone, V: Clone> Default for Cache<K, V> {
13    fn default() -> Self {
14        Self { inner: Default::default() }
15    }
16}
17
18impl<K: Hash + PartialEq + Eq + Clone, V: Clone> Cache<K, V> {
19    pub fn inner_clone(&self) -> FxHashMap<K, V> {
20        return self.inner.borrow().clone();
21    }
22
23    pub fn inner_borrow_mut(&self) -> RefMut<FxHashMap<K, V>> {
24        self.inner.borrow_mut()
25    }
26
27    pub fn get<F: FnMut(K) -> V>(&self, key: K, mut f: F) -> V {
28        let contents = self.inner.borrow_mut().get(&key).cloned();
29
30        return match contents {
31            Some(v) => v,
32            None => {
33                let v = f(key.clone());
34                self.inner.borrow_mut().insert(key, v.clone());
35                v
36            },
37        };
38    }
39
40    pub fn get_checked(&self, key: &K) -> Option<V> {
41        return self.inner.borrow().get(key).cloned();
42    }
43
44    pub fn contains(&self, key: &K) -> bool {
45        return self.inner.borrow().contains_key(key);
46    }
47
48    pub fn insert(&self, key: K, value: V) -> bool {
49        return self.inner.borrow_mut().insert(key, value).is_none();
50    }
51
52    pub fn invalidate(&self, key: &K) {
53        self.inner.borrow_mut().remove(key);
54    }
55}
56
57// Concrete types
58
59type ResultCache<K, O, E> = Cache<K, Result<O, E>>;
60type StringCache<V> = Cache<String, V>;
61type IdCache = ResultCache<String, usize, String>;
62type TemplateCache = Cache<(usize, Vec<Type>, Vec<Type>), Vec<RynaExpr>>;
63type OverloadCache = Cache<(usize, Vec<Type>, Vec<Type>), usize>;
64type UsageCache = Cache<usize, FxHashSet<(Vec<Type>, Vec<Type>)>>;
65type ImportCache<T> = FxHashSet<(String, T)>;
66type OpcodeCache = Cache<(usize, usize), (CompiledRynaExpr, usize)>;
67
68//  Concrete functionalities
69
70impl UsageCache {
71    pub fn add_new(&self, f_id: usize, args: Vec<Type>, templates: Vec<Type>) -> bool {
72        return self.inner.borrow_mut().entry(f_id).or_default().insert((args, templates));
73    }
74}
75
76// Full Ryna cache
77
78#[allow(clippy::type_complexity)]
79#[derive(Default, Clone, Serialize, Deserialize)]
80pub struct RynaImportCache {
81    pub functions: ImportCache<(usize, Vec<String>, Vec<(String, Type)>, Type)>,
82    pub unary: ImportCache<(usize, Vec<String>, Type, Type)>,
83    pub binary: ImportCache<(usize, Vec<String>, Type, Type, Type)>,
84    pub nary: ImportCache<(usize, Vec<String>, Type, Vec<(String, Type)>, Type)>,
85    
86    pub classes: ImportCache<(String, Vec<String>)>,
87
88    pub interface_def: ImportCache<(String, Vec<String>)>,
89    pub interface_impl: ImportCache<(Vec<String>, Type, String, Vec<Type>)>,
90
91    pub macros: ImportCache<(String, Pattern)>,
92
93    pub lines: ImportCache<usize>
94}
95
96#[derive(Default, Clone, Serialize, Deserialize)]
97pub struct RynaDividedCache<T> {
98    pub functions: T,
99    pub unary: T,
100    pub binary: T,
101    pub nary: T
102}
103
104#[derive(Default, Clone, Serialize, Deserialize)]
105pub struct RynaCache {
106    pub class_id: IdCache,
107    pub function_id: IdCache,
108    pub interface_id: IdCache,
109    pub templates: RynaDividedCache<TemplateCache>,
110    pub usages: RynaDividedCache<UsageCache>,
111    pub overloads: RynaDividedCache<OverloadCache>,
112    pub locations: RynaDividedCache<OverloadCache>,
113    pub opcodes: RynaDividedCache<OpcodeCache>,
114    pub imports: RynaImportCache,
115    pub ranges: StringCache<(usize, usize)>
116}
117
118pub fn needs_line_import(module: &str, line: usize, cache: &mut ImportCache<usize>) -> bool {    
119    cache.insert((module.to_owned(), line))
120}
121
122pub fn needs_import<T: Hash + PartialEq + Eq>(module: &str, import_type: ImportType, name: &String, imports: &Imports, cache: &mut ImportCache<T>, obj: T) -> bool {    
123    (imports.contains_key(&ImportType::All) || (
124        imports.contains_key(&import_type) && 
125        (imports[&import_type].contains(name) || imports[&import_type].contains("*"))
126    )) && cache.insert((module.to_owned(), obj))
127}