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 LcnfString,
169 Unit,
171 Irrelevant,
173}
174pub struct UsageCounter {
176 pub(super) counts: HashMap<LcnfVarId, usize>,
177}
178impl UsageCounter {
179 pub(super) fn new() -> Self {
180 UsageCounter {
181 counts: HashMap::new(),
182 }
183 }
184 pub(super) fn count_arg(&mut self, arg: &LcnfArg) {
185 if let LcnfArg::Var(id) = arg {
186 *self.counts.entry(*id).or_insert(0) += 1;
187 }
188 }
189 pub(super) fn count_let_value(&mut self, val: &LcnfLetValue) {
190 match val {
191 LcnfLetValue::App(func, args) => {
192 self.count_arg(func);
193 for arg in args {
194 self.count_arg(arg);
195 }
196 }
197 LcnfLetValue::Proj(_, _, var) => {
198 *self.counts.entry(*var).or_insert(0) += 1;
199 }
200 LcnfLetValue::Ctor(_, _, args) => {
201 for arg in args {
202 self.count_arg(arg);
203 }
204 }
205 LcnfLetValue::FVar(id) => {
206 *self.counts.entry(*id).or_insert(0) += 1;
207 }
208 LcnfLetValue::Lit(_)
209 | LcnfLetValue::Erased
210 | LcnfLetValue::Reset(_)
211 | LcnfLetValue::Reuse(_, _, _, _) => {}
212 }
213 }
214 pub(super) fn count_expr(&mut self, expr: &LcnfExpr) {
215 match expr {
216 LcnfExpr::Let { value, body, .. } => {
217 self.count_let_value(value);
218 self.count_expr(body);
219 }
220 LcnfExpr::Case {
221 scrutinee,
222 alts,
223 default,
224 ..
225 } => {
226 *self.counts.entry(*scrutinee).or_insert(0) += 1;
227 for alt in alts {
228 self.count_expr(&alt.body);
229 }
230 if let Some(def) = default {
231 self.count_expr(def);
232 }
233 }
234 LcnfExpr::Return(arg) => self.count_arg(arg),
235 LcnfExpr::Unreachable => {}
236 LcnfExpr::TailCall(func, args) => {
237 self.count_arg(func);
238 for arg in args {
239 self.count_arg(arg);
240 }
241 }
242 }
243 }
244}
245#[derive(Clone, PartialEq, Debug)]
250pub enum LcnfLetValue {
251 App(LcnfArg, Vec<LcnfArg>),
253 Proj(String, u32, LcnfVarId),
255 Ctor(String, u32, Vec<LcnfArg>),
257 Lit(LcnfLit),
259 Erased,
261 FVar(LcnfVarId),
263 Reset(LcnfVarId),
266 Reuse(LcnfVarId, String, u32, Vec<LcnfArg>),
269}
270#[derive(Clone, Debug, Default)]
272pub struct Substitution(pub HashMap<LcnfVarId, LcnfArg>);
273impl Substitution {
274 pub fn new() -> Self {
275 Substitution(HashMap::new())
276 }
277 pub fn insert(&mut self, var: LcnfVarId, arg: LcnfArg) {
278 self.0.insert(var, arg);
279 }
280 pub fn get(&self, var: &LcnfVarId) -> Option<&LcnfArg> {
281 self.0.get(var)
282 }
283 pub fn contains(&self, var: &LcnfVarId) -> bool {
284 self.0.contains_key(var)
285 }
286 pub fn compose(&self, other: &Substitution) -> Substitution {
287 let mut result = HashMap::new();
288 for (var, arg) in &self.0 {
289 result.insert(*var, substitute_arg(arg, other));
290 }
291 for (var, arg) in &other.0 {
292 result.entry(*var).or_insert_with(|| arg.clone());
293 }
294 Substitution(result)
295 }
296 pub fn is_empty(&self) -> bool {
297 self.0.is_empty()
298 }
299}
300#[derive(Clone, PartialEq, Eq, Hash, Debug)]
302pub struct LcnfParam {
303 pub id: LcnfVarId,
305 pub name: String,
307 pub ty: LcnfType,
309 pub erased: bool,
311 pub borrowed: bool,
313}
314#[derive(Clone, Debug, PartialEq)]
316pub struct DefinitionSite {
317 pub var: LcnfVarId,
318 pub name: String,
319 pub ty: LcnfType,
320 pub depth: usize,
321}
322#[derive(Clone, PartialEq, Debug)]
324pub struct LcnfAlt {
325 pub ctor_name: String,
327 pub ctor_tag: u32,
329 pub params: Vec<LcnfParam>,
331 pub body: LcnfExpr,
333}
334#[derive(Clone, PartialEq, Debug)]
336pub struct LcnfExternDecl {
337 pub name: String,
339 pub params: Vec<LcnfParam>,
341 pub ret_type: LcnfType,
343}
344#[derive(Clone, PartialEq, Debug)]
346pub struct LcnfFunDecl {
347 pub name: String,
349 pub original_name: Option<Name>,
351 pub params: Vec<LcnfParam>,
353 pub ret_type: LcnfType,
355 pub body: LcnfExpr,
357 pub is_recursive: bool,
359 pub is_lifted: bool,
361 pub inline_cost: usize,
363}
364#[derive(Clone, Debug, PartialEq)]
366pub enum ValidationError {
367 UnboundVariable(LcnfVarId),
368 DuplicateBinding(LcnfVarId),
369 EmptyCase,
370 InvalidTag(String, u32),
371 NonAtomicArgument,
372}
373pub struct LcnfBuilder {
375 pub(super) next_id: u64,
376 pub(super) bindings: Vec<(LcnfVarId, String, LcnfType, LcnfLetValue)>,
377}
378impl LcnfBuilder {
379 pub fn new() -> Self {
380 LcnfBuilder {
381 next_id: 0,
382 bindings: Vec::new(),
383 }
384 }
385 pub fn with_start_id(start: u64) -> Self {
386 LcnfBuilder {
387 next_id: start,
388 bindings: Vec::new(),
389 }
390 }
391 pub fn fresh_var(&mut self, _name: &str, _ty: LcnfType) -> LcnfVarId {
392 let id = LcnfVarId(self.next_id);
393 self.next_id += 1;
394 id
395 }
396 pub fn let_bind(&mut self, name: &str, ty: LcnfType, val: LcnfLetValue) -> LcnfVarId {
397 let id = LcnfVarId(self.next_id);
398 self.next_id += 1;
399 self.bindings.push((id, name.to_string(), ty, val));
400 id
401 }
402 pub fn let_app(
403 &mut self,
404 name: &str,
405 ty: LcnfType,
406 func: LcnfArg,
407 args: Vec<LcnfArg>,
408 ) -> LcnfVarId {
409 self.let_bind(name, ty, LcnfLetValue::App(func, args))
410 }
411 pub fn let_ctor(
412 &mut self,
413 name: &str,
414 ty: LcnfType,
415 ctor: &str,
416 tag: u32,
417 args: Vec<LcnfArg>,
418 ) -> LcnfVarId {
419 self.let_bind(name, ty, LcnfLetValue::Ctor(ctor.to_string(), tag, args))
420 }
421 pub fn let_proj(
422 &mut self,
423 name: &str,
424 ty: LcnfType,
425 type_name: &str,
426 idx: u32,
427 var: LcnfVarId,
428 ) -> LcnfVarId {
429 self.let_bind(
430 name,
431 ty,
432 LcnfLetValue::Proj(type_name.to_string(), idx, var),
433 )
434 }
435 pub fn build_return(self, arg: LcnfArg) -> LcnfExpr {
436 self.wrap_bindings(LcnfExpr::Return(arg))
437 }
438 pub fn build_case(
439 self,
440 scrutinee: LcnfVarId,
441 scrutinee_ty: LcnfType,
442 alts: Vec<LcnfAlt>,
443 default: Option<LcnfExpr>,
444 ) -> LcnfExpr {
445 self.wrap_bindings(LcnfExpr::Case {
446 scrutinee,
447 scrutinee_ty,
448 alts,
449 default: default.map(Box::new),
450 })
451 }
452 pub fn build_tail_call(self, func: LcnfArg, args: Vec<LcnfArg>) -> LcnfExpr {
453 self.wrap_bindings(LcnfExpr::TailCall(func, args))
454 }
455 pub(super) fn wrap_bindings(self, terminal: LcnfExpr) -> LcnfExpr {
456 let mut result = terminal;
457 for (id, name, ty, value) in self.bindings.into_iter().rev() {
458 result = LcnfExpr::Let {
459 id,
460 name,
461 ty,
462 value,
463 body: Box::new(result),
464 };
465 }
466 result
467 }
468 pub fn peek_next_id(&self) -> u64 {
469 self.next_id
470 }
471 pub fn binding_count(&self) -> usize {
472 self.bindings.len()
473 }
474}
475#[derive(Clone, Debug)]
477pub struct CostModel {
478 pub let_cost: u64,
479 pub app_cost: u64,
480 pub case_cost: u64,
481 pub return_cost: u64,
482 pub branch_penalty: u64,
483}
484#[derive(Clone, PartialEq, Eq, Hash, Debug)]
486pub enum LcnfLit {
487 Nat(u64),
489 Str(String),
491}
492#[derive(Clone, PartialEq, Debug)]
494pub enum LcnfExpr {
495 Let {
497 id: LcnfVarId,
499 name: String,
501 ty: LcnfType,
503 value: LcnfLetValue,
505 body: Box<LcnfExpr>,
507 },
508 Case {
510 scrutinee: LcnfVarId,
512 scrutinee_ty: LcnfType,
514 alts: Vec<LcnfAlt>,
516 default: Option<Box<LcnfExpr>>,
518 },
519 Return(LcnfArg),
521 Unreachable,
523 TailCall(LcnfArg, Vec<LcnfArg>),
525}