1use std::{io::Result, str::Chars};
20
21use darkfi_serial::{serialize, VarInt};
22
23use super::{
24 ast::{Arg, Constant, Literal, Statement, StatementType, Witness},
25 constants::{
26 SECTION_CIRCUIT, SECTION_CONSTANT, SECTION_DEBUG, SECTION_LITERAL, SECTION_WITNESS,
27 },
28 error::ErrorEmitter,
29 types::HeapType,
30};
31
32pub const BINARY_VERSION: u8 = 2;
34pub const MAGIC_BYTES: [u8; 4] = [0x0b, 0x01, 0xb1, 0x35];
36
37pub struct Compiler {
38 namespace: String,
39 k: u32,
40 constants: Vec<Constant>,
41 witnesses: Vec<Witness>,
42 statements: Vec<Statement>,
43 literals: Vec<Literal>,
44 debug_info: bool,
45 error: ErrorEmitter,
46}
47
48impl Compiler {
49 #[allow(clippy::too_many_arguments)]
50 pub fn new(
51 filename: &str,
52 source: Chars,
53 namespace: String,
54 k: u32,
55 constants: Vec<Constant>,
56 witnesses: Vec<Witness>,
57 statements: Vec<Statement>,
58 literals: Vec<Literal>,
59 debug_info: bool,
60 ) -> Self {
61 let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
64 let error = ErrorEmitter::new("Compiler", filename, lines);
65
66 Self { namespace, k, constants, witnesses, statements, literals, debug_info, error }
67 }
68
69 pub fn compile(&self) -> Result<Vec<u8>> {
70 let mut bincode = vec![];
71
72 bincode.extend_from_slice(&MAGIC_BYTES);
74 bincode.push(BINARY_VERSION);
75
76 bincode.extend_from_slice(&serialize(&self.k));
78
79 bincode.extend_from_slice(&serialize(&self.namespace));
81
82 let mut tmp_heap = vec![];
84
85 bincode.extend_from_slice(SECTION_CONSTANT);
88 for i in &self.constants {
89 tmp_heap.push(i.name.as_str());
90 bincode.push(i.typ as u8);
91 bincode.extend_from_slice(&serialize(&i.name));
92 }
93
94 bincode.extend_from_slice(SECTION_LITERAL);
98 for i in &self.literals {
99 bincode.push(i.typ as u8);
100 bincode.extend_from_slice(&serialize(&i.name));
101 }
102
103 bincode.extend_from_slice(SECTION_WITNESS);
106 for i in &self.witnesses {
107 tmp_heap.push(i.name.as_str());
108 bincode.push(i.typ as u8);
109 }
110
111 bincode.extend_from_slice(SECTION_CIRCUIT);
112 for i in &self.statements {
113 match i.typ {
114 StatementType::Assign => tmp_heap.push(&i.lhs.as_ref().unwrap().name),
115 StatementType::Call => {}
117 _ => unreachable!("Invalid statement type in circuit: {:?}", i.typ),
118 }
119
120 bincode.push(i.opcode as u8);
121 bincode.extend_from_slice(&serialize(&VarInt(i.rhs.len() as u64)));
122
123 for arg in &i.rhs {
124 match arg {
125 Arg::Var(arg) => {
126 let heap_idx =
127 Compiler::lookup_heap(&tmp_heap, &arg.name).ok_or_else(|| {
128 self.error.abort(
129 &format!("Failed finding a heap reference for `{}`", arg.name),
130 arg.line,
131 arg.column,
132 )
133 })?;
134
135 bincode.push(HeapType::Var as u8);
136 bincode.extend_from_slice(&serialize(&VarInt(heap_idx as u64)));
137 }
138 Arg::Lit(lit) => {
139 let lit_idx = Compiler::lookup_literal(&self.literals, &lit.name)
140 .ok_or_else(|| {
141 self.error.abort(
142 &format!("Failed finding literal `{}`", lit.name),
143 lit.line,
144 lit.column,
145 )
146 })?;
147
148 bincode.push(HeapType::Lit as u8);
149 bincode.extend_from_slice(&serialize(&VarInt(lit_idx as u64)));
150 }
151 _ => unreachable!(),
152 };
153 }
154 }
155
156 if !self.debug_info {
158 return Ok(bincode)
159 }
160
161 bincode.extend_from_slice(SECTION_DEBUG);
163
164 bincode.extend_from_slice(&serialize(&VarInt(self.statements.len() as u64)));
167 for stmt in &self.statements {
168 bincode.extend_from_slice(&serialize(&VarInt(stmt.line as u64)));
169 let column = stmt.lhs.as_ref().map(|v| v.column).unwrap_or(0);
171 bincode.extend_from_slice(&serialize(&VarInt(column as u64)));
172 }
173
174 let heap_size = self.constants.len() +
178 self.witnesses.len() +
179 self.statements.iter().filter(|s| s.typ == StatementType::Assign).count();
180 bincode.extend_from_slice(&serialize(&VarInt(heap_size as u64)));
181
182 for constant in &self.constants {
183 bincode.extend_from_slice(&serialize(&constant.name));
184 }
185
186 for witness in &self.witnesses {
187 bincode.extend_from_slice(&serialize(&witness.name));
188 }
189
190 for stmt in &self.statements {
191 if stmt.typ == StatementType::Assign {
192 bincode.extend_from_slice(&serialize(&stmt.lhs.as_ref().unwrap().name));
193 }
194 }
195
196 bincode.extend_from_slice(&serialize(&VarInt(self.literals.len() as u64)));
198 for literal in &self.literals {
199 bincode.extend_from_slice(&serialize(&literal.name));
200 }
201
202 Ok(bincode)
203 }
204
205 fn lookup_heap(heap: &[&str], name: &str) -> Option<usize> {
206 heap.iter().position(|&n| n == name)
207 }
208
209 fn lookup_literal(literals: &[Literal], name: &str) -> Option<usize> {
210 literals.iter().position(|n| n.name == name)
211 }
212}