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