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
use super::*;
impl Table {
    
    pub fn calc(
        x: usize,
        y: usize,
        tree_table: &mut Vec<Vec<Box<ThreadSafeNode>>>,
        ref_src_table: &mut Vec<Vec<Vec<(usize, usize)>>>,
        dependents_table: &mut Vec<Vec<HashMap<(usize, usize), u32>>>,
        calculated_table: &mut Vec<Vec<Value>>,
        walked_position: &mut Vec<(usize, usize)>,
    ) {
        walked_position.push((x, y));
        calculated_table[y][x] =
            if ref_src_table[y][x]
                .iter()
                .fold(false, |b, (x_of_target, y_of_target)| {
                    b || walked_position.contains(&(*x_of_target, *y_of_target))
                })
            {
                Value::Error
            } else {
                
                let (calculated_value, old_dependents, new_dependents) =
                    tree_table[y][x].calc(&calculated_table);
                
                for dependent in new_dependents {
                    let entry = dependents_table[y][x].entry(dependent).or_insert(0);
                    if *entry == 0 {
                        ref_src_table[dependent.1][dependent.0].push((x, y));
                    }
                    *entry += 1;
                }
                
                for dependent in old_dependents {
                    if let Some(n) = dependents_table[y][x].get_mut(&dependent) {
                        *n -= 1;
                        if *n == 0 {
                            ref_src_table[dependent.1][dependent.0]
                                .retain(|&(x_src, y_src)| x_src == x && y_src == y);
                        }
                    }
                }
                
                dependents_table[y][x].retain(|_, v| *v != 0);
                calculated_value
            };
        for i in 0..ref_src_table[y][x].len() {
            let (x_of_target, y_of_target) = ref_src_table[y][x][i];
            if !walked_position.contains(&(x_of_target, y_of_target)) {
                Self::calc(
                    x_of_target,
                    y_of_target,
                    tree_table,
                    ref_src_table,
                    dependents_table,
                    calculated_table,
                    walked_position,
                );
            }
        }
    }
}