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