swamp_script_core/
extra.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/script
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 */

use crate::idx_gen::IndexAllocator;
use crate::value::ValueRef;
use crate::value::{to_rust_value, Value};
use sparse_slot::{Id, SparseSlot};
use std::cell::RefCell;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
use swamp_script_semantic::{ResolvedRustTypeRef, ResolvedType};

#[derive(Debug)]
pub struct SparseValueId(pub Id);

impl Display for SparseValueId {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "id:{}:{}", self.0.index, self.0.generation)
    }
}

#[derive(Debug)]
pub struct SparseValueMap {
    pub sparse_slot: SparseSlot<Rc<RefCell<Value>>>,
    pub id_generator: IndexAllocator,
    pub type_parameter: ResolvedType,
    pub resolved_type: ResolvedType,
    pub rust_type_ref_for_id: ResolvedRustTypeRef,
}

impl Display for SparseValueMap {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Sparse<{:?}> len:{}",
            self.type_parameter,
            self.sparse_slot.len()
        )
    }
}

impl SparseValueMap {
    #[must_use]
    pub fn new(rust_type_ref_for_id: ResolvedRustTypeRef, resolved_type: ResolvedType) -> Self {
        let type_parameter = match &resolved_type {
            ResolvedType::Generic(_, parameters) => parameters[0].clone(),
            _ => panic!("illegal sparse type. not generic"),
        };

        Self {
            sparse_slot: SparseSlot::<Rc<RefCell<Value>>>::new(2048),
            id_generator: IndexAllocator::new(),
            type_parameter,
            resolved_type,
            rust_type_ref_for_id,
        }
    }

    pub fn add(&mut self, v: Value) -> Value {
        // TODO: Check that value is of correct type parameter
        let (index, generation) = self.id_generator.create();

        let id = Id { index, generation };

        // Always store mutable references
        let mutable_reference = Rc::new(RefCell::new(v));

        self.sparse_slot
            .try_set(id, mutable_reference)
            .expect("sparse should work");

        let script_id = SparseValueId(id);

        to_rust_value(self.rust_type_ref_for_id.clone(), script_id)
    }

    pub fn remove(&mut self, id: &SparseValueId) {
        self.id_generator.remove((id.0.index, id.0.generation));
        self.sparse_slot.remove(id.0);
    }

    #[must_use]
    pub fn get(&self, id: &SparseValueId) -> Option<&ValueRef> {
        self.sparse_slot.get(id.0)
    }

    #[allow(unused)]
    #[must_use]
    pub fn iter(&self) -> sparse_slot::Iter<'_, Rc<RefCell<Value>>> {
        self.sparse_slot.iter()
    }
    pub fn iter_mut(&mut self) -> sparse_slot::IterMut<'_, Rc<RefCell<Value>>> {
        self.sparse_slot.iter_mut()
    }

    #[must_use]
    pub fn values(&self) -> Vec<Rc<RefCell<Value>>> {
        self.sparse_slot.iter().map(|(_id, v)| v.clone()).collect()
    }
}