1pub(crate) mod builtins;
6pub(crate) mod common;
7#[cfg(feature = "runtime")]
8pub mod dafny;
9#[cfg(feature = "runtime")]
10pub mod lean;
11#[cfg(feature = "runtime")]
12pub mod recursion;
13#[cfg(feature = "runtime")]
14pub mod rust;
15#[cfg(feature = "wasm-compile")]
16pub mod wasm;
17
18use std::collections::{HashMap, HashSet};
19
20use crate::ast::{FnDef, TopLevel, TypeDef};
21use crate::types::checker::TypeCheckResult;
22
23pub struct ModuleInfo {
25 pub prefix: String,
27 pub depends: Vec<String>,
29 pub type_defs: Vec<TypeDef>,
31 pub fn_defs: Vec<FnDef>,
33}
34
35pub struct CodegenContext {
37 pub items: Vec<TopLevel>,
39 pub fn_sigs: HashMap<String, (Vec<crate::types::Type>, crate::types::Type, Vec<String>)>,
41 pub memo_fns: HashSet<String>,
43 pub memo_safe_types: HashSet<String>,
45 pub type_defs: Vec<TypeDef>,
47 pub fn_defs: Vec<FnDef>,
49 pub project_name: String,
51 pub modules: Vec<ModuleInfo>,
53 pub module_prefixes: HashSet<String>,
55 #[cfg(feature = "runtime")]
57 pub policy: Option<crate::config::ProjectConfig>,
58 pub emit_replay_runtime: bool,
60 pub runtime_policy_from_env: bool,
62 pub guest_entry: Option<String>,
64 pub emit_self_host_support: bool,
66 pub extra_fn_defs: Vec<FnDef>,
70 pub mutual_tco_members: HashSet<String>,
73}
74
75pub struct ProjectOutput {
77 pub files: Vec<(String, String)>,
79}
80
81pub fn build_context(
83 items: Vec<TopLevel>,
84 tc_result: &TypeCheckResult,
85 memo_fns: HashSet<String>,
86 project_name: String,
87 modules: Vec<ModuleInfo>,
88) -> CodegenContext {
89 let type_defs: Vec<TypeDef> = items
90 .iter()
91 .filter_map(|item| {
92 if let TopLevel::TypeDef(td) = item {
93 Some(td.clone())
94 } else {
95 None
96 }
97 })
98 .collect();
99
100 let fn_defs: Vec<FnDef> = items
101 .iter()
102 .filter_map(|item| {
103 if let TopLevel::FnDef(fd) = item {
104 Some(fd.clone())
105 } else {
106 None
107 }
108 })
109 .collect();
110
111 let module_prefixes: HashSet<String> = modules.iter().map(|m| m.prefix.clone()).collect();
112
113 let mut mutual_tco_members = HashSet::new();
115 {
116 let entry_fns: Vec<&FnDef> = fn_defs.iter().filter(|fd| fd.name != "main").collect();
118 for group in crate::call_graph::tailcall_scc_components(&entry_fns) {
119 for fd in &group {
120 mutual_tco_members.insert(fd.name.clone());
121 }
122 }
123 for module in &modules {
125 let mod_fns: Vec<&FnDef> = module.fn_defs.iter().collect();
126 for group in crate::call_graph::tailcall_scc_components(&mod_fns) {
127 for fd in &group {
128 mutual_tco_members.insert(fd.name.clone());
129 }
130 }
131 }
132 }
133
134 let mut fn_sigs = tc_result.fn_sigs.clone();
139 {
140 let pairs: Vec<(String, Vec<TopLevel>)> = modules
141 .iter()
142 .map(|m| {
143 let items: Vec<TopLevel> = m
144 .fn_defs
145 .iter()
146 .map(|fd| TopLevel::FnDef(fd.clone()))
147 .chain(m.type_defs.iter().map(|td| TopLevel::TypeDef(td.clone())))
148 .collect();
149 (m.prefix.clone(), items)
150 })
151 .collect();
152 let registry = crate::visibility::SymbolRegistry::from_modules_all(&pairs);
153 for entry in ®istry.entries {
154 if fn_sigs.contains_key(&entry.canonical_name) {
155 continue;
156 }
157 if let crate::visibility::SymbolKind::Function {
158 params,
159 return_type,
160 effects,
161 ..
162 } = &entry.kind
163 {
164 let parsed_params: Vec<crate::types::Type> = params
165 .iter()
166 .map(|(_, ty_str)| crate::types::parse_type_str(ty_str))
167 .collect();
168 let ret = crate::types::parse_type_str(return_type);
169 fn_sigs.insert(
170 entry.canonical_name.clone(),
171 (parsed_params, ret, effects.clone()),
172 );
173 }
174 }
175 }
176
177 CodegenContext {
178 items,
179 fn_sigs,
180 memo_fns,
181 memo_safe_types: tc_result.memo_safe_types.clone(),
182 type_defs,
183 fn_defs,
184 project_name,
185 modules,
186 module_prefixes,
187 #[cfg(feature = "runtime")]
188 policy: None,
189 emit_replay_runtime: false,
190 runtime_policy_from_env: false,
191 guest_entry: None,
192 emit_self_host_support: false,
193 extra_fn_defs: Vec::new(),
194 mutual_tco_members,
195 }
196}