Skip to main content

tasm_lib/io/
write_to_stdout.rs

1use std::collections::HashMap;
2
3use rand::prelude::*;
4use triton_vm::prelude::*;
5
6use crate::empty_stack;
7use crate::prelude::*;
8use crate::traits::procedure::Procedure;
9use crate::traits::procedure::ProcedureInitialState;
10use crate::traits::rust_shadow::RustShadowError;
11
12#[derive(Debug, Clone, Eq, PartialEq, Hash)]
13pub struct WriteToStdout {
14    pub data_type: DataType,
15}
16
17impl BasicSnippet for WriteToStdout {
18    fn parameters(&self) -> Vec<(DataType, String)> {
19        vec![(self.data_type.clone(), "value".to_string())]
20    }
21
22    fn return_values(&self) -> Vec<(DataType, String)> {
23        vec![]
24    }
25
26    fn entrypoint(&self) -> String {
27        format!(
28            "tasmlib_io_write_to_stdout___{}",
29            self.data_type.label_friendly_name()
30        )
31    }
32
33    fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
34        triton_asm!(
35            {self.entrypoint()}:
36                {&self.data_type.write_value_to_stdout()}
37                return
38        )
39    }
40}
41
42impl Procedure for WriteToStdout {
43    fn rust_shadow(
44        &self,
45        stack: &mut Vec<BFieldElement>,
46        _: &mut HashMap<BFieldElement, BFieldElement>,
47        _: &NonDeterminism,
48        _: &[BFieldElement],
49        _: &mut Option<Tip5>,
50    ) -> Result<Vec<BFieldElement>, RustShadowError> {
51        let mut ret = Vec::new();
52        for _ in 0..self.data_type.stack_size() {
53            let value = stack.pop().ok_or(RustShadowError::StackUnderflow)?;
54            ret.push(value);
55        }
56
57        Ok(ret)
58    }
59
60    fn pseudorandom_initial_state(
61        &self,
62        seed: [u8; 32],
63        _bench_case: Option<crate::snippet_bencher::BenchmarkCase>,
64    ) -> ProcedureInitialState {
65        let mut rng = StdRng::from_seed(seed);
66        let mut stack = empty_stack();
67        let random_value = self.data_type.seeded_random_element(&mut rng);
68        stack.extend(random_value.into_iter().rev());
69
70        ProcedureInitialState {
71            stack,
72            ..Default::default()
73        }
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use crate::test_prelude::*;
81
82    #[macro_rules_attr::apply(test)]
83    fn rust_shadow() {
84        for data_type in DataType::big_random_generatable_type_collection() {
85            ShadowedProcedure::new(WriteToStdout { data_type }).test();
86        }
87    }
88}
89
90#[cfg(test)]
91mod benches {
92    use super::*;
93    use crate::test_prelude::*;
94
95    #[macro_rules_attr::apply(test)]
96    fn benchmark_digest_writing() {
97        ShadowedProcedure::new(WriteToStdout {
98            data_type: DataType::Digest,
99        })
100        .bench();
101    }
102}