Skip to main content

aver/codegen/
mod.rs

1/// Aver → target language transpilation.
2///
3/// The codegen module transforms a type-checked Aver AST into source code
4/// for a target language. Current backends: Rust and Lean (WIP).
5pub(crate) mod common;
6pub mod lean;
7pub mod rust;
8
9use std::collections::{HashMap, HashSet};
10
11use crate::ast::{FnDef, TopLevel, TypeDef};
12use crate::types::checker::TypeCheckResult;
13
14/// Information about a dependent module loaded for codegen.
15pub struct ModuleInfo {
16    /// Qualified module path, e.g. "Examples.Fibonacci".
17    pub prefix: String,
18    /// Type definitions from the module.
19    pub type_defs: Vec<TypeDef>,
20    /// Function definitions from the module (excluding `main`).
21    pub fn_defs: Vec<FnDef>,
22}
23
24/// Collected context from the Aver program, shared across all backends.
25pub struct CodegenContext {
26    /// All top-level items (post-TCO transform, post-typecheck).
27    pub items: Vec<TopLevel>,
28    /// Function signatures: name → (param_types, return_type, effects).
29    pub fn_sigs: HashMap<String, (Vec<crate::types::Type>, crate::types::Type, Vec<String>)>,
30    /// Functions eligible for auto-memoization.
31    pub memo_fns: HashSet<String>,
32    /// Set of type names whose values are memo-safe.
33    pub memo_safe_types: HashSet<String>,
34    /// User-defined type definitions (for struct/enum generation).
35    pub type_defs: Vec<TypeDef>,
36    /// User-defined function definitions.
37    pub fn_defs: Vec<FnDef>,
38    /// Project/binary name.
39    pub project_name: String,
40    /// Dependent modules loaded for inlining.
41    pub modules: Vec<ModuleInfo>,
42    /// Set of module prefixes for qualified name resolution (e.g. "Examples.Fibonacci").
43    pub module_prefixes: HashSet<String>,
44}
45
46/// Output files from a codegen backend.
47pub struct ProjectOutput {
48    /// Files to write: (relative_path, content).
49    pub files: Vec<(String, String)>,
50}
51
52/// Build a CodegenContext from parsed + type-checked items.
53pub fn build_context(
54    items: Vec<TopLevel>,
55    tc_result: &TypeCheckResult,
56    memo_fns: HashSet<String>,
57    project_name: String,
58    modules: Vec<ModuleInfo>,
59) -> CodegenContext {
60    let type_defs: Vec<TypeDef> = items
61        .iter()
62        .filter_map(|item| {
63            if let TopLevel::TypeDef(td) = item {
64                Some(td.clone())
65            } else {
66                None
67            }
68        })
69        .collect();
70
71    let fn_defs: Vec<FnDef> = items
72        .iter()
73        .filter_map(|item| {
74            if let TopLevel::FnDef(fd) = item {
75                Some(fd.clone())
76            } else {
77                None
78            }
79        })
80        .collect();
81
82    let module_prefixes: HashSet<String> = modules.iter().map(|m| m.prefix.clone()).collect();
83
84    CodegenContext {
85        items,
86        fn_sigs: tc_result.fn_sigs.clone(),
87        memo_fns,
88        memo_safe_types: tc_result.memo_safe_types.clone(),
89        type_defs,
90        fn_defs,
91        project_name,
92        modules,
93        module_prefixes,
94    }
95}