1#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
3
4pub use twenty_first;
5
6pub mod error;
7pub mod instruction;
8pub mod op_stack;
9pub mod parser;
10pub mod program;
11
12#[macro_export]
76macro_rules! triton_program {
77 {$($source_code:tt)*} => {{
78 let labelled_instructions = $crate::triton_asm!($($source_code)*);
79 $crate::program::Program::new(&labelled_instructions)
80 }};
81}
82
83#[macro_export]
161macro_rules! triton_asm {
162 (@fmt $fmt:expr, $($args:expr,)*; ) => {
163 format_args!($fmt $(,$args)*).to_string()
164 };
165 (@fmt $fmt:expr, $($args:expr,)*;
166 hint $var:ident: $ty:ident = stack[$start:literal..$end:literal] $($tail:tt)*) => {
167 $crate::triton_asm!(@fmt
168 concat!($fmt, " hint {}: {} = stack[{}..{}] "),
169 $($args,)* stringify!($var), stringify!($ty), $start, $end,;
170 $($tail)*
171 )
172 };
173 (@fmt $fmt:expr, $($args:expr,)*;
174 hint $var:ident = stack[$start:literal..$end:literal] $($tail:tt)*) => {
175 $crate::triton_asm!(@fmt
176 concat!($fmt, " hint {} = stack[{}..{}] "),
177 $($args,)* stringify!($var), $start, $end,;
178 $($tail)*
179 )
180 };
181 (@fmt $fmt:expr, $($args:expr,)*;
182 hint $var:ident: $ty:ident = stack[$index:literal] $($tail:tt)*) => {
183 $crate::triton_asm!(@fmt
184 concat!($fmt, " hint {}: {} = stack[{}] "),
185 $($args,)* stringify!($var), stringify!($ty), $index,;
186 $($tail)*
187 )
188 };
189 (@fmt $fmt:expr, $($args:expr,)*;
190 hint $var:ident = stack[$index:literal] $($tail:tt)*) => {
191 $crate::triton_asm!(@fmt
192 concat!($fmt, " hint {} = stack[{}] "),
193 $($args,)* stringify!($var), $index,;
194 $($tail)*
195 )
196 };
197 (@fmt $fmt:expr, $($args:expr,)*; $label_declaration:ident: $($tail:tt)*) => {
198 $crate::triton_asm!(@fmt
199 concat!($fmt, " ", stringify!($label_declaration), ": "), $($args,)*; $($tail)*
200 )
201 };
202 (@fmt $fmt:expr, $($args:expr,)*; $instruction:ident $($tail:tt)*) => {
203 $crate::triton_asm!(@fmt
204 concat!($fmt, " ", stringify!($instruction), " "), $($args,)*; $($tail)*
205 )
206 };
207 (@fmt $fmt:expr, $($args:expr,)*; $instruction_argument:literal $($tail:tt)*) => {
208 $crate::triton_asm!(@fmt
209 concat!($fmt, " ", stringify!($instruction_argument), " "), $($args,)*; $($tail)*
210 )
211 };
212 (@fmt $fmt:expr, $($args:expr,)*; {$label_declaration:expr}: $($tail:tt)*) => {
213 $crate::triton_asm!(@fmt concat!($fmt, "{}: "), $($args,)* $label_declaration,; $($tail)*)
214 };
215 (@fmt $fmt:expr, $($args:expr,)*; {&$instruction_list:expr} $($tail:tt)*) => {
216 $crate::triton_asm!(@fmt
217 concat!($fmt, "{} "), $($args,)*
218 $instruction_list.iter().map(|instr| instr.to_string()).collect::<Vec<_>>().join(" "),;
219 $($tail)*
220 )
221 };
222 (@fmt $fmt:expr, $($args:expr,)*; {$expression:expr} $($tail:tt)*) => {
223 $crate::triton_asm!(@fmt concat!($fmt, "{} "), $($args,)* $expression,; $($tail)*)
224 };
225
226 [pop $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(pop $arg); $num ] };
228 [push $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(push $arg); $num ] };
229 [divine $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(divine $arg); $num ] };
230 [pick $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(pick $arg); $num ] };
231 [place $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(place $arg); $num ] };
232 [dup $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(dup $arg); $num ] };
233 [swap $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(swap $arg); $num ] };
234 [call $arg:ident; $num:expr] => { vec![ $crate::triton_instr!(call $arg); $num ] };
235 [read_mem $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(read_mem $arg); $num ] };
236 [write_mem $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(write_mem $arg); $num ] };
237 [read_io $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(read_io $arg); $num ] };
238 [write_io $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(write_io $arg); $num ] };
239 [$instr:ident; $num:expr] => { vec![ $crate::triton_instr!($instr); $num ] };
240
241 {$($source_code:tt)*} => {{
243 let source_code = $crate::triton_asm!(@fmt "",; $($source_code)*);
244 let (_, instructions) = $crate::parser::tokenize(&source_code).unwrap();
245 $crate::parser::to_labelled_instructions(&instructions)
246 }};
247}
248
249#[macro_export]
264macro_rules! triton_instr {
265 (pop $arg:literal) => {{
266 let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
267 let instruction = $crate::instruction::AnInstruction::<String>::Pop(argument);
268 $crate::instruction::LabelledInstruction::Instruction(instruction)
269 }};
270 (push $arg:expr) => {{
271 let argument = $crate::twenty_first::prelude::BFieldElement::from($arg);
272 let instruction = $crate::instruction::AnInstruction::<String>::Push(argument);
273 $crate::instruction::LabelledInstruction::Instruction(instruction)
274 }};
275 (divine $arg:literal) => {{
276 let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
277 let instruction = $crate::instruction::AnInstruction::<String>::Divine(argument);
278 $crate::instruction::LabelledInstruction::Instruction(instruction)
279 }};
280 (pick $arg:literal) => {{
281 let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
282 let instruction = $crate::instruction::AnInstruction::<String>::Pick(argument);
283 $crate::instruction::LabelledInstruction::Instruction(instruction)
284 }};
285 (place $arg:literal) => {{
286 let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
287 let instruction = $crate::instruction::AnInstruction::<String>::Place(argument);
288 $crate::instruction::LabelledInstruction::Instruction(instruction)
289 }};
290 (dup $arg:literal) => {{
291 let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
292 let instruction = $crate::instruction::AnInstruction::<String>::Dup(argument);
293 $crate::instruction::LabelledInstruction::Instruction(instruction)
294 }};
295 (swap $arg:literal) => {{
296 let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
297 let instruction = $crate::instruction::AnInstruction::<String>::Swap(argument);
298 $crate::instruction::LabelledInstruction::Instruction(instruction)
299 }};
300 (call $arg:ident) => {{
301 let argument = stringify!($arg).to_string();
302 let instruction = $crate::instruction::AnInstruction::<String>::Call(argument);
303 $crate::instruction::LabelledInstruction::Instruction(instruction)
304 }};
305 (read_mem $arg:literal) => {{
306 let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
307 let instruction = $crate::instruction::AnInstruction::<String>::ReadMem(argument);
308 $crate::instruction::LabelledInstruction::Instruction(instruction)
309 }};
310 (write_mem $arg:literal) => {{
311 let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
312 let instruction = $crate::instruction::AnInstruction::<String>::WriteMem(argument);
313 $crate::instruction::LabelledInstruction::Instruction(instruction)
314 }};
315 (addi $arg:expr) => {{
316 let argument = $crate::twenty_first::prelude::BFieldElement::from($arg);
317 let instruction = $crate::instruction::AnInstruction::<String>::AddI(argument);
318 $crate::instruction::LabelledInstruction::Instruction(instruction)
319 }};
320 (read_io $arg:literal) => {{
321 let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
322 let instruction = $crate::instruction::AnInstruction::<String>::ReadIo(argument);
323 $crate::instruction::LabelledInstruction::Instruction(instruction)
324 }};
325 (write_io $arg:literal) => {{
326 let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
327 let instruction = $crate::instruction::AnInstruction::<String>::WriteIo(argument);
328 $crate::instruction::LabelledInstruction::Instruction(instruction)
329 }};
330 ($instr:ident) => {{
331 let (_, instructions) = $crate::parser::tokenize(stringify!($instr)).unwrap();
332 instructions[0].to_labelled_instruction()
333 }};
334}
335
336#[cfg(test)]
337#[cfg_attr(coverage_nightly, coverage(off))]
338mod tests {
339 use super::*;
340
341 #[test]
342 fn public_types_implement_usual_auto_traits() {
343 fn implements_auto_traits<T: Sized + Send + Sync + Unpin>() {}
344
345 implements_auto_traits::<error::AssertionError>();
346 implements_auto_traits::<error::InstructionError>();
347 implements_auto_traits::<error::NumberOfWordsError>();
348 implements_auto_traits::<error::OpStackElementError>();
349 implements_auto_traits::<error::OpStackError>();
350 implements_auto_traits::<error::ParseError>();
351 implements_auto_traits::<error::ProgramDecodingError>();
352
353 implements_auto_traits::<instruction::Instruction>();
354 implements_auto_traits::<instruction::AnInstruction<usize>>();
355 implements_auto_traits::<instruction::InstructionBit>();
356 implements_auto_traits::<instruction::TypeHint>();
357
358 implements_auto_traits::<op_stack::NumberOfWords>();
359 implements_auto_traits::<op_stack::OpStack>();
360 implements_auto_traits::<op_stack::OpStackElement>();
361 implements_auto_traits::<op_stack::UnderflowIO>();
362
363 implements_auto_traits::<parser::InstructionToken>();
364
365 implements_auto_traits::<program::InstructionIter>();
366 implements_auto_traits::<program::Program>();
367 }
368}