kind_target_hvm/
lib.rs

1use hvm::u60;
2
3use kind_tree::untyped;
4
5use hvm::syntax::{File, Rule, Term};
6
7pub fn compile_book(book: untyped::Book, trace: bool) -> File {
8    let mut file = File {
9        rules: Default::default(),
10        smaps: Default::default(),
11    };
12    for (_, entry) in book.entrs {
13        compile_entry(&mut file, entry, trace);
14    }
15    file
16}
17
18pub fn compile_str(val: &str) -> Box<Term> {
19    let nil = Box::new(Term::Ctr {
20        name: String::from("Data.String.nil"),
21        args: vec![],
22    });
23
24    let cons = |numb, next| {
25        Box::new(Term::Ctr {
26            name: String::from("Data.String.cons"),
27            args: vec![Box::new(Term::U6O { numb }), next],
28        })
29    };
30
31    val.chars().rfold(nil, |rest, chr| cons(chr as u64, rest))
32}
33
34pub fn compile_term(expr: &untyped::Expr) -> Box<Term> {
35    use untyped::ExprKind::*;
36    match &expr.data {
37        Var { name } => Box::new(Term::Var {
38            name: name.to_string(),
39        }),
40        Lambda { param, body, .. } => Box::new(Term::Lam {
41            name: param.to_string(),
42            body: compile_term(body),
43        }),
44        App { fun, args } => args.iter().fold(compile_term(fun), |func, arg| {
45            Box::new(Term::App {
46                func,
47                argm: compile_term(arg),
48            })
49        }),
50        Fun { name, args } | Ctr { name, args } => Box::new(Term::Ctr {
51            name: name.to_string(),
52            args: args.iter().map(|x| compile_term(x)).collect(),
53        }),
54        Let { name, val, next } => Box::new(Term::Let {
55            name: name.to_string(),
56            expr: compile_term(val),
57            body: compile_term(next),
58        }),
59        U60 { numb } => Box::new(Term::U6O {
60            numb: u60::new(*numb),
61        }),
62        F60 { numb: _ } => todo!(),
63        Binary { op, left, right } => Box::new(Term::Ctr {
64            name: op.to_string(),
65            args: vec![compile_term(left), compile_term(right)],
66        }),
67        Str { val } => compile_str(val),
68        Err => unreachable!("Internal Error: 'ERR' cannot be a relevant term"),
69    }
70}
71
72fn compile_rule(name: String, rule: untyped::Rule) -> Rule {
73    Rule {
74        lhs: Box::new(Term::Ctr {
75            name,
76            args: rule.pats.iter().map(|x| compile_term(x)).collect(),
77        }),
78        rhs: compile_term(&rule.body),
79    }
80}
81
82fn compile_entry(file: &mut File, entry: Box<untyped::Entry>, trace: bool) {
83    if entry.attrs.trace.is_some() || trace {
84        let _with_args = entry.attrs.trace.unwrap_or(false);
85
86        let name_trace = format!("{}__trace", entry.name);
87        for rule in entry.rules {
88            file.rules.push(compile_rule(name_trace.clone(), rule))
89        }
90
91        let args = entry
92            .args
93            .iter()
94            .enumerate()
95            .map(|(i, x)| {
96                Box::new(Term::Var {
97                    name: format!("_{}{}", i, x.0.clone()),
98                })
99            })
100            .collect::<Vec<_>>();
101
102        file.rules.push(Rule {
103            lhs: Box::new(Term::Ctr {
104                name: entry.name.to_string(),
105                args: args.clone(),
106            }),
107            rhs: Box::new(Term::Ctr {
108                name: "Apps.HVM.log".to_string(),
109                args: vec![
110                    compile_str(entry.name.to_str()),
111                    Box::new(Term::Ctr {
112                        name: name_trace,
113                        args,
114                    }),
115                ],
116            }),
117        })
118    } else {
119        let name = entry.name.to_string();
120        for rule in entry.rules {
121            file.rules.push(compile_rule(name.clone(), rule))
122        }
123    }
124}