1use super::functions::*;
6use oxilean_kernel::Name;
7use std::collections::{HashMap, HashSet};
8
9#[derive(Clone, Debug, Default)]
11pub struct LcnfModuleMetadata {
12 pub decl_count: usize,
14 pub lambdas_lifted: usize,
16 pub proofs_erased: usize,
18 pub types_erased: usize,
20 pub let_bindings: usize,
22}
23#[derive(Clone, PartialEq, Eq, Hash, Debug)]
27pub enum LcnfArg {
28 Var(LcnfVarId),
30 Lit(LcnfLit),
32 Erased,
34 Type(LcnfType),
36}
37#[derive(Clone, Debug, Default)]
39pub struct LcnfModule {
40 pub fun_decls: Vec<LcnfFunDecl>,
42 pub extern_decls: Vec<LcnfExternDecl>,
44 pub name: String,
46 pub metadata: LcnfModuleMetadata,
48}
49#[derive(Clone, Debug)]
51pub struct PrettyConfig {
52 pub indent: usize,
53 pub max_width: usize,
54 pub show_types: bool,
55 pub show_erased: bool,
56}
57#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
59pub struct LcnfVarId(pub u64);
60pub struct FreeVarCollector {
62 pub(super) bound: HashSet<LcnfVarId>,
63 pub(super) free: HashSet<LcnfVarId>,
64}
65impl FreeVarCollector {
66 pub(super) fn new() -> Self {
67 FreeVarCollector {
68 bound: HashSet::new(),
69 free: HashSet::new(),
70 }
71 }
72 pub(super) fn collect_from_arg(&mut self, arg: &LcnfArg) {
73 if let LcnfArg::Var(id) = arg {
74 if !self.bound.contains(id) {
75 self.free.insert(*id);
76 }
77 }
78 }
79 pub(super) fn collect_from_let_value(&mut self, val: &LcnfLetValue) {
80 match val {
81 LcnfLetValue::App(func, args) => {
82 self.collect_from_arg(func);
83 for arg in args {
84 self.collect_from_arg(arg);
85 }
86 }
87 LcnfLetValue::Proj(_, _, var) => {
88 if !self.bound.contains(var) {
89 self.free.insert(*var);
90 }
91 }
92 LcnfLetValue::Ctor(_, _, args) => {
93 for arg in args {
94 self.collect_from_arg(arg);
95 }
96 }
97 LcnfLetValue::FVar(id) => {
98 if !self.bound.contains(id) {
99 self.free.insert(*id);
100 }
101 }
102 LcnfLetValue::Lit(_)
103 | LcnfLetValue::Erased
104 | LcnfLetValue::Reset(_)
105 | LcnfLetValue::Reuse(_, _, _, _) => {}
106 }
107 }
108 pub(super) fn collect_expr(&mut self, expr: &LcnfExpr) {
109 match expr {
110 LcnfExpr::Let {
111 id, value, body, ..
112 } => {
113 self.collect_from_let_value(value);
114 self.bound.insert(*id);
115 self.collect_expr(body);
116 }
117 LcnfExpr::Case {
118 scrutinee,
119 alts,
120 default,
121 ..
122 } => {
123 if !self.bound.contains(scrutinee) {
124 self.free.insert(*scrutinee);
125 }
126 for alt in alts {
127 let saved = self.bound.clone();
128 for param in &alt.params {
129 self.bound.insert(param.id);
130 }
131 self.collect_expr(&alt.body);
132 self.bound = saved;
133 }
134 if let Some(def) = default {
135 self.collect_expr(def);
136 }
137 }
138 LcnfExpr::Return(arg) => self.collect_from_arg(arg),
139 LcnfExpr::Unreachable => {}
140 LcnfExpr::TailCall(func, args) => {
141 self.collect_from_arg(func);
142 for arg in args {
143 self.collect_from_arg(arg);
144 }
145 }
146 }
147 }
148}
149#[derive(Clone, PartialEq, Eq, Hash, Debug)]
154pub enum LcnfType {
155 Erased,
157 Var(String),
159 Fun(Vec<LcnfType>, Box<LcnfType>),
161 Ctor(String, Vec<LcnfType>),
163 Object,
165 Nat,
167 Int,
169 LcnfString,
171 Unit,
173 Irrelevant,
175}
176pub struct UsageCounter {
178 pub(super) counts: HashMap<LcnfVarId, usize>,
179}
180impl UsageCounter {
181 pub(super) fn new() -> Self {
182 UsageCounter {
183 counts: HashMap::new(),
184 }
185 }
186 pub(super) fn count_arg(&mut self, arg: &LcnfArg) {
187 if let LcnfArg::Var(id) = arg {
188 *self.counts.entry(*id).or_insert(0) += 1;
189 }
190 }
191 pub(super) fn count_let_value(&mut self, val: &LcnfLetValue) {
192 match val {
193 LcnfLetValue::App(func, args) => {
194 self.count_arg(func);
195 for arg in args {
196 self.count_arg(arg);
197 }
198 }
199 LcnfLetValue::Proj(_, _, var) => {
200 *self.counts.entry(*var).or_insert(0) += 1;
201 }
202 LcnfLetValue::Ctor(_, _, args) => {
203 for arg in args {
204 self.count_arg(arg);
205 }
206 }
207 LcnfLetValue::FVar(id) => {
208 *self.counts.entry(*id).or_insert(0) += 1;
209 }
210 LcnfLetValue::Lit(_)
211 | LcnfLetValue::Erased
212 | LcnfLetValue::Reset(_)
213 | LcnfLetValue::Reuse(_, _, _, _) => {}
214 }
215 }
216 pub(super) fn count_expr(&mut self, expr: &LcnfExpr) {
217 match expr {
218 LcnfExpr::Let { value, body, .. } => {
219 self.count_let_value(value);
220 self.count_expr(body);
221 }
222 LcnfExpr::Case {
223 scrutinee,
224 alts,
225 default,
226 ..
227 } => {
228 *self.counts.entry(*scrutinee).or_insert(0) += 1;
229 for alt in alts {
230 self.count_expr(&alt.body);
231 }
232 if let Some(def) = default {
233 self.count_expr(def);
234 }
235 }
236 LcnfExpr::Return(arg) => self.count_arg(arg),
237 LcnfExpr::Unreachable => {}
238 LcnfExpr::TailCall(func, args) => {
239 self.count_arg(func);
240 for arg in args {
241 self.count_arg(arg);
242 }
243 }
244 }
245 }
246}
247#[derive(Clone, PartialEq, Debug)]
252pub enum LcnfLetValue {
253 App(LcnfArg, Vec<LcnfArg>),
255 Proj(String, u32, LcnfVarId),
257 Ctor(String, u32, Vec<LcnfArg>),
259 Lit(LcnfLit),
261 Erased,
263 FVar(LcnfVarId),
265 Reset(LcnfVarId),
268 Reuse(LcnfVarId, String, u32, Vec<LcnfArg>),
271}
272#[derive(Clone, Debug, Default)]
274pub struct Substitution(pub HashMap<LcnfVarId, LcnfArg>);
275impl Substitution {
276 pub fn new() -> Self {
277 Substitution(HashMap::new())
278 }
279 pub fn insert(&mut self, var: LcnfVarId, arg: LcnfArg) {
280 self.0.insert(var, arg);
281 }
282 pub fn get(&self, var: &LcnfVarId) -> Option<&LcnfArg> {
283 self.0.get(var)
284 }
285 pub fn contains(&self, var: &LcnfVarId) -> bool {
286 self.0.contains_key(var)
287 }
288 pub fn compose(&self, other: &Substitution) -> Substitution {
289 let mut result = HashMap::new();
290 for (var, arg) in &self.0 {
291 result.insert(*var, substitute_arg(arg, other));
292 }
293 for (var, arg) in &other.0 {
294 result.entry(*var).or_insert_with(|| arg.clone());
295 }
296 Substitution(result)
297 }
298 pub fn is_empty(&self) -> bool {
299 self.0.is_empty()
300 }
301}
302#[derive(Clone, PartialEq, Eq, Hash, Debug)]
304pub struct LcnfParam {
305 pub id: LcnfVarId,
307 pub name: String,
309 pub ty: LcnfType,
311 pub erased: bool,
313 pub borrowed: bool,
315}
316#[derive(Clone, Debug, PartialEq)]
318pub struct DefinitionSite {
319 pub var: LcnfVarId,
320 pub name: String,
321 pub ty: LcnfType,
322 pub depth: usize,
323}
324#[derive(Clone, PartialEq, Debug)]
326pub struct LcnfAlt {
327 pub ctor_name: String,
329 pub ctor_tag: u32,
331 pub params: Vec<LcnfParam>,
333 pub body: LcnfExpr,
335}
336#[derive(Clone, PartialEq, Debug)]
338pub struct LcnfExternDecl {
339 pub name: String,
341 pub params: Vec<LcnfParam>,
343 pub ret_type: LcnfType,
345}
346#[derive(Clone, PartialEq, Debug)]
348pub struct LcnfFunDecl {
349 pub name: String,
351 pub original_name: Option<Name>,
353 pub params: Vec<LcnfParam>,
355 pub ret_type: LcnfType,
357 pub body: LcnfExpr,
359 pub is_recursive: bool,
361 pub is_lifted: bool,
363 pub inline_cost: usize,
365}
366#[derive(Clone, Debug, PartialEq)]
368pub enum ValidationError {
369 UnboundVariable(LcnfVarId),
370 DuplicateBinding(LcnfVarId),
371 EmptyCase,
372 InvalidTag(String, u32),
373 NonAtomicArgument,
374}
375pub struct LcnfBuilder {
377 pub(super) next_id: u64,
378 pub(super) bindings: Vec<(LcnfVarId, String, LcnfType, LcnfLetValue)>,
379}
380impl LcnfBuilder {
381 pub fn new() -> Self {
382 LcnfBuilder {
383 next_id: 0,
384 bindings: Vec::new(),
385 }
386 }
387 pub fn with_start_id(start: u64) -> Self {
388 LcnfBuilder {
389 next_id: start,
390 bindings: Vec::new(),
391 }
392 }
393 pub fn fresh_var(&mut self, _name: &str, _ty: LcnfType) -> LcnfVarId {
394 let id = LcnfVarId(self.next_id);
395 self.next_id += 1;
396 id
397 }
398 pub fn let_bind(&mut self, name: &str, ty: LcnfType, val: LcnfLetValue) -> LcnfVarId {
399 let id = LcnfVarId(self.next_id);
400 self.next_id += 1;
401 self.bindings.push((id, name.to_string(), ty, val));
402 id
403 }
404 pub fn let_app(
405 &mut self,
406 name: &str,
407 ty: LcnfType,
408 func: LcnfArg,
409 args: Vec<LcnfArg>,
410 ) -> LcnfVarId {
411 self.let_bind(name, ty, LcnfLetValue::App(func, args))
412 }
413 pub fn let_ctor(
414 &mut self,
415 name: &str,
416 ty: LcnfType,
417 ctor: &str,
418 tag: u32,
419 args: Vec<LcnfArg>,
420 ) -> LcnfVarId {
421 self.let_bind(name, ty, LcnfLetValue::Ctor(ctor.to_string(), tag, args))
422 }
423 pub fn let_proj(
424 &mut self,
425 name: &str,
426 ty: LcnfType,
427 type_name: &str,
428 idx: u32,
429 var: LcnfVarId,
430 ) -> LcnfVarId {
431 self.let_bind(
432 name,
433 ty,
434 LcnfLetValue::Proj(type_name.to_string(), idx, var),
435 )
436 }
437 pub fn build_return(self, arg: LcnfArg) -> LcnfExpr {
438 self.wrap_bindings(LcnfExpr::Return(arg))
439 }
440 pub fn build_case(
441 self,
442 scrutinee: LcnfVarId,
443 scrutinee_ty: LcnfType,
444 alts: Vec<LcnfAlt>,
445 default: Option<LcnfExpr>,
446 ) -> LcnfExpr {
447 self.wrap_bindings(LcnfExpr::Case {
448 scrutinee,
449 scrutinee_ty,
450 alts,
451 default: default.map(Box::new),
452 })
453 }
454 pub fn build_tail_call(self, func: LcnfArg, args: Vec<LcnfArg>) -> LcnfExpr {
455 self.wrap_bindings(LcnfExpr::TailCall(func, args))
456 }
457 pub(super) fn wrap_bindings(self, terminal: LcnfExpr) -> LcnfExpr {
458 let mut result = terminal;
459 for (id, name, ty, value) in self.bindings.into_iter().rev() {
460 result = LcnfExpr::Let {
461 id,
462 name,
463 ty,
464 value,
465 body: Box::new(result),
466 };
467 }
468 result
469 }
470 pub fn peek_next_id(&self) -> u64 {
471 self.next_id
472 }
473 pub fn binding_count(&self) -> usize {
474 self.bindings.len()
475 }
476}
477#[derive(Clone, Debug)]
479pub struct CostModel {
480 pub let_cost: u64,
481 pub app_cost: u64,
482 pub case_cost: u64,
483 pub return_cost: u64,
484 pub branch_penalty: u64,
485}
486#[derive(Clone, PartialEq, Eq, Hash, Debug)]
488pub enum LcnfLit {
489 Nat(u64),
491 Int(i64),
493 Str(String),
495}
496#[derive(Clone, PartialEq, Debug)]
498pub enum LcnfExpr {
499 Let {
501 id: LcnfVarId,
503 name: String,
505 ty: LcnfType,
507 value: LcnfLetValue,
509 body: Box<LcnfExpr>,
511 },
512 Case {
514 scrutinee: LcnfVarId,
516 scrutinee_ty: LcnfType,
518 alts: Vec<LcnfAlt>,
520 default: Option<Box<LcnfExpr>>,
522 },
523 Return(LcnfArg),
525 Unreachable,
527 TailCall(LcnfArg, Vec<LcnfArg>),
529}