tasm_lib/list/
new.rs

1use std::collections::HashMap;
2
3use triton_vm::prelude::*;
4
5use crate::prelude::*;
6use crate::rust_shadowing_helper_functions::list::list_new;
7use crate::snippet_bencher::BenchmarkCase;
8use crate::traits::function::Function;
9use crate::traits::function::FunctionInitialState;
10
11/// Creates a new list and returns a pointer to it.
12///
13/// Lists like these do not have an explicit capacity. Instead, they have
14/// access to a full [memory page][crate::memory]. Snippets like
15/// [`Push`][super::push::Push] and [`Set`][super::set::Set] ensure that all
16/// list access is in bounds.
17#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
18pub struct New;
19
20impl BasicSnippet for New {
21    fn parameters(&self) -> Vec<(DataType, String)> {
22        vec![]
23    }
24
25    fn return_values(&self) -> Vec<(DataType, String)> {
26        vec![(DataType::VoidPointer, "*list".to_string())]
27    }
28
29    fn entrypoint(&self) -> String {
30        "tasmlib_list_new".to_string()
31    }
32
33    fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
34        let dyn_malloc = library.import(Box::new(DynMalloc));
35
36        triton_asm!(
37            // BEFORE: _
38            // AFTER:  _ *list
39            {self.entrypoint()}:
40                call {dyn_malloc}
41                            // _ *list
42
43                /* write initial length = 0 to `*list` */
44                push 0
45                pick 1
46                write_mem 1
47                addi -1
48                            // _ *list
49
50                return
51        )
52    }
53}
54
55impl Function for New {
56    fn rust_shadow(
57        &self,
58        stack: &mut Vec<BFieldElement>,
59        memory: &mut HashMap<BFieldElement, BFieldElement>,
60    ) {
61        DynMalloc.rust_shadow(stack, memory);
62
63        let &list_pointer = stack.last().unwrap();
64        list_new(list_pointer, memory);
65    }
66
67    fn pseudorandom_initial_state(
68        &self,
69        _: [u8; 32],
70        _: Option<BenchmarkCase>,
71    ) -> FunctionInitialState {
72        FunctionInitialState {
73            stack: self.init_stack_for_isolated_run(),
74            ..Default::default()
75        }
76    }
77}
78
79#[cfg(test)]
80pub(crate) mod tests {
81    use super::*;
82    use crate::test_prelude::*;
83
84    #[test]
85    fn rust_shadow() {
86        ShadowedFunction::new(New).test();
87    }
88}
89
90#[cfg(test)]
91mod benches {
92    use super::*;
93    use crate::test_prelude::*;
94
95    #[test]
96    fn benchmark() {
97        ShadowedFunction::new(New).bench();
98    }
99}