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