pub use twenty_first;
pub mod error;
pub mod instruction;
pub mod op_stack;
pub mod parser;
pub mod program;
#[macro_export]
macro_rules! triton_program {
{$($source_code:tt)*} => {{
let labelled_instructions = $crate::triton_asm!($($source_code)*);
$crate::program::Program::new(&labelled_instructions)
}};
}
#[macro_export]
macro_rules! triton_asm {
(@fmt $fmt:expr, $($args:expr,)*; ) => {
format_args!($fmt $(,$args)*).to_string()
};
(@fmt $fmt:expr, $($args:expr,)*;
hint $var:ident: $ty:ident = stack[$start:literal..$end:literal] $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, " hint {}: {} = stack[{}..{}] "),
$($args,)* stringify!($var), stringify!($ty), $start, $end,;
$($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*;
hint $var:ident = stack[$start:literal..$end:literal] $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, " hint {} = stack[{}..{}] "),
$($args,)* stringify!($var), $start, $end,;
$($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*;
hint $var:ident: $ty:ident = stack[$index:literal] $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, " hint {}: {} = stack[{}] "),
$($args,)* stringify!($var), stringify!($ty), $index,;
$($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*;
hint $var:ident = stack[$index:literal] $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, " hint {} = stack[{}] "),
$($args,)* stringify!($var), $index,;
$($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*; $label_declaration:ident: $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, " ", stringify!($label_declaration), ": "), $($args,)*; $($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*; $instruction:ident $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, " ", stringify!($instruction), " "), $($args,)*; $($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*; $instruction_argument:literal $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, " ", stringify!($instruction_argument), " "), $($args,)*; $($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*; {$label_declaration:expr}: $($tail:tt)*) => {
$crate::triton_asm!(@fmt concat!($fmt, "{}: "), $($args,)* $label_declaration,; $($tail)*)
};
(@fmt $fmt:expr, $($args:expr,)*; {&$instruction_list:expr} $($tail:tt)*) => {
$crate::triton_asm!(@fmt
concat!($fmt, "{} "), $($args,)*
$instruction_list.iter().map(|instr| instr.to_string()).collect::<Vec<_>>().join(" "),;
$($tail)*
)
};
(@fmt $fmt:expr, $($args:expr,)*; {$expression:expr} $($tail:tt)*) => {
$crate::triton_asm!(@fmt concat!($fmt, "{} "), $($args,)* $expression,; $($tail)*)
};
[pop $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(pop $arg); $num ] };
[push $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(push $arg); $num ] };
[divine $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(divine $arg); $num ] };
[pick $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(pick $arg); $num ] };
[place $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(place $arg); $num ] };
[dup $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(dup $arg); $num ] };
[swap $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(swap $arg); $num ] };
[call $arg:ident; $num:expr] => { vec![ $crate::triton_instr!(call $arg); $num ] };
[read_mem $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(read_mem $arg); $num ] };
[write_mem $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(write_mem $arg); $num ] };
[read_io $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(read_io $arg); $num ] };
[write_io $arg:literal; $num:expr] => { vec![ $crate::triton_instr!(write_io $arg); $num ] };
[$instr:ident; $num:expr] => { vec![ $crate::triton_instr!($instr); $num ] };
{$($source_code:tt)*} => {{
let source_code = $crate::triton_asm!(@fmt "",; $($source_code)*);
let (_, instructions) = $crate::parser::tokenize(&source_code).unwrap();
$crate::parser::to_labelled_instructions(&instructions)
}};
}
#[macro_export]
macro_rules! triton_instr {
(pop $arg:literal) => {{
let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::Pop(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(push $arg:expr) => {{
let argument = $crate::twenty_first::prelude::BFieldElement::from($arg);
let instruction = $crate::instruction::AnInstruction::<String>::Push(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(divine $arg:literal) => {{
let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::Divine(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(pick $arg:literal) => {{
let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::Pick(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(place $arg:literal) => {{
let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::Place(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(dup $arg:literal) => {{
let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::Dup(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(swap $arg:literal) => {{
let argument = $crate::op_stack::OpStackElement::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::Swap(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(call $arg:ident) => {{
let argument = stringify!($arg).to_string();
let instruction = $crate::instruction::AnInstruction::<String>::Call(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(read_mem $arg:literal) => {{
let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::ReadMem(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(write_mem $arg:literal) => {{
let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::WriteMem(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(addi $arg:expr) => {{
let argument = $crate::twenty_first::prelude::BFieldElement::from($arg);
let instruction = $crate::instruction::AnInstruction::<String>::AddI(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(read_io $arg:literal) => {{
let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::ReadIo(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
(write_io $arg:literal) => {{
let argument = $crate::op_stack::NumberOfWords::try_from($arg).unwrap();
let instruction = $crate::instruction::AnInstruction::<String>::WriteIo(argument);
$crate::instruction::LabelledInstruction::Instruction(instruction)
}};
($instr:ident) => {{
let (_, instructions) = $crate::parser::tokenize(stringify!($instr)).unwrap();
instructions[0].to_labelled_instruction()
}};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn public_types_implement_usual_auto_traits() {
fn implements_auto_traits<T: Sized + Send + Sync + Unpin>() {}
implements_auto_traits::<error::AssertionError>();
implements_auto_traits::<error::InstructionError>();
implements_auto_traits::<error::NumberOfWordsError>();
implements_auto_traits::<error::OpStackElementError>();
implements_auto_traits::<error::OpStackError>();
implements_auto_traits::<error::ParseError>();
implements_auto_traits::<error::ProgramDecodingError>();
implements_auto_traits::<instruction::Instruction>();
implements_auto_traits::<instruction::AnInstruction<usize>>();
implements_auto_traits::<instruction::InstructionBit>();
implements_auto_traits::<instruction::TypeHint>();
implements_auto_traits::<op_stack::NumberOfWords>();
implements_auto_traits::<op_stack::OpStack>();
implements_auto_traits::<op_stack::OpStackElement>();
implements_auto_traits::<op_stack::UnderflowIO>();
implements_auto_traits::<parser::InstructionToken>();
implements_auto_traits::<program::InstructionIter>();
implements_auto_traits::<program::Program>();
}
}