Skip to main content

scratch_test_model/scopes/
target_procedures.rs

1use std::collections::HashMap;
2
3use svalue::ARc;
4
5use crate::{
6    Id,
7    blocks::{ProcedureArgumentDef, ProcedureId},
8    scopes::{TargetBlocks, block_wrapper::BlockWrapper},
9};
10
11/// Contains all information about a defined custom/own block, also called procedure.
12///
13/// This information is collected by combining to categories of blocks from the target blocks:
14/// - a definition block
15/// - a prototype block
16#[derive(Debug, PartialEq, derive_getters::Getters)]
17pub struct Procedure {
18    proccode: ARc<str>,
19    definition_block: ARc<BlockWrapper>,
20    prototype_block_id: Id,
21    /// generated using proccode and arguments
22    procedure_id: ProcedureId,
23    arguments: ARc<[ProcedureArgumentDef]>,
24}
25
26/// This component has no equivalent in the scratch file format
27#[derive(Debug, PartialEq)]
28pub struct TargetProcedures(HashMap<ProcedureId, Procedure>);
29
30impl TargetProcedures {
31    pub(crate) fn new(blocks: &TargetBlocks) -> Self {
32        let mut cb = HashMap::new();
33        let mut proto_to_def_block = HashMap::new();
34
35        for block in blocks.iter_blocks() {
36            use crate::blocks::BlockKind as B;
37            match block.inner() {
38                B::ProceduresPrototype(proto) => {
39                    cb.insert(block.id().clone(), proto);
40                }
41                B::ProceduresDefinition(def) => {
42                    proto_to_def_block.insert(def.prototype().o_id(), block.clone());
43                }
44                _ => {}
45            }
46        }
47
48        let res = cb
49            .into_iter()
50            .filter_map(|(id, prototype)| {
51                Some((
52                    prototype.procedure_id().clone(),
53                    Procedure {
54                        proccode: prototype.proccode().clone(),
55                        arguments: prototype.arguments().clone(),
56                        definition_block: proto_to_def_block.get(&id)?.clone(),
57                        procedure_id: prototype.procedure_id().clone(),
58                        prototype_block_id: id,
59                    },
60                ))
61            })
62            .collect();
63        Self(res)
64    }
65    pub fn get(&self, id: &ProcedureId) -> Option<&Procedure> {
66        self.0.get(id)
67    }
68    pub fn iter(&self) -> impl Iterator<Item = (&ProcedureId, &Procedure)> {
69        self.0.iter()
70    }
71    pub fn iter_procedures(&self) -> impl Iterator<Item = &Procedure> {
72        self.0.values()
73    }
74}