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}