1
//! Per-`(defun_name, signature)` monomorph cache.
2
//!
3
//! Tier 1.5 closes Gap B (recursive defun called with a runtime arg) by
4
//! lowering through a real wasm fn rather than the inline const-fold
5
//! walk. Each distinct call-site signature gets its own emitted fn:
6
//! `(defun fact (n) ...)` called with a `Ratio` arg emits one wasm fn,
7
//! the same defun called with (hypothetically) a `Commodity` arg emits
8
//! another. The cache lookup is keyed by `(name, params)` so call sites
9
//! with identical signatures share one fn — including the recursive
10
//! self-call inside the body.
11
//!
12
//! The cache is mutated only by [`CompileContext::lookup_or_emit_monomorph`]
13
//! (added in `compiler/expr/call.rs`) and snapshot-restored along with
14
//! the rest of the wasm-section state via [`super::snapshot`].
15

            
16
use std::collections::HashMap;
17

            
18
use crate::ast::WasmType;
19

            
20
use super::CompileContext;
21

            
22
/// One monomorph entry: the wasm fn idx at which the body was emitted
23
/// plus the body-derived return type. Cloneable + Eq because it lives
24
/// in the snapshot/restore graph.
25
#[derive(Debug, Clone, PartialEq, Eq)]
26
pub(crate) struct MonomorphEntry {
27
    pub func_idx: u32,
28
    pub ret_ty: WasmType,
29
}
30

            
31
/// Cache key: defun name + monomorph parameter signature. The body
32
/// AST stays stored on the `Symbol::function` slot — re-fetched at
33
/// emit time rather than duplicated here, so renaming or redefining a
34
/// defun invalidates the cache implicitly via lookup.
35
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
36
pub(crate) struct MonomorphKey {
37
    pub name: String,
38
    pub params: Vec<WasmType>,
39
}
40

            
41
#[derive(Debug, Default, Clone)]
42
pub(crate) struct MonomorphCache {
43
    entries: HashMap<MonomorphKey, MonomorphEntry>,
44
}
45

            
46
impl MonomorphCache {
47
1836
    pub(crate) fn get(&self, key: &MonomorphKey) -> Option<&MonomorphEntry> {
48
1836
        self.entries.get(key)
49
1836
    }
50

            
51
3060
    pub(crate) fn insert(&mut self, key: MonomorphKey, entry: MonomorphEntry) {
52
3060
        self.entries.insert(key, entry);
53
3060
    }
54
}
55

            
56
impl CompileContext {
57
1836
    pub(crate) fn monomorph_cache(&self) -> &MonomorphCache {
58
1836
        &self.monomorphs
59
1836
    }
60

            
61
3060
    pub(crate) fn monomorph_cache_mut(&mut self) -> &mut MonomorphCache {
62
3060
        &mut self.monomorphs
63
3060
    }
64
}