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
use std::{cell::RefCell, mem, ops::Deref, rc::Rc};
use crate::RantValue;
#[derive(Debug)]
pub enum RantVar {
ByVal(RantValue),
ByValConst(RantValue),
ByRef(Rc<RefCell<RantValue>>),
ByRefConst(Rc<RantValue>)
}
impl Default for RantVar {
fn default() -> Self {
Self::ByVal(RantValue::Empty)
}
}
impl Clone for RantVar {
fn clone(&self) -> Self {
match self {
Self::ByVal(val) => Self::ByVal(val.clone()),
Self::ByRef(val_ref) => Self::ByRef(Rc::clone(val_ref)),
Self::ByValConst(val) => Self::ByValConst(val.clone()),
Self::ByRefConst(val_ref) => Self::ByRefConst(Rc::clone(val_ref)),
}
}
}
impl RantVar {
#[inline]
pub fn is_const(&self) -> bool {
matches!(self, Self::ByValConst(_) | Self::ByRefConst(_))
}
#[inline]
pub fn is_by_val(&self) -> bool {
matches!(self, Self::ByVal(_) | Self::ByValConst(_))
}
#[inline]
pub fn is_by_ref(&self) -> bool {
matches!(self, Self::ByRef(_) | Self::ByRefConst(_))
}
#[inline]
pub fn make_by_ref(&mut self) {
if self.is_by_ref() { return }
match mem::take(self) {
Self::ByVal(val) => *self = Self::ByRef(Rc::new(RefCell::new(val))),
Self::ByValConst(val) => *self = Self::ByRefConst(Rc::new(val)),
_ => unreachable!()
}
}
#[inline]
pub fn write(&mut self, value: RantValue) -> bool {
match self {
Self::ByVal(val) => *val = value,
Self::ByRef(val_ref) => {
val_ref.replace(value);
},
Self::ByRefConst(_) | Self::ByValConst(_) => return false,
}
true
}
#[inline]
pub fn value_ref(&self) -> impl Deref<Target = RantValue> + '_ {
match self {
Self::ByVal(val) | Self::ByValConst(val) => cervine::Cow::Borrowed(val),
Self::ByRef(val_ref) => cervine::Cow::Owned(val_ref.borrow()),
Self::ByRefConst(val_ref) => cervine::Cow::Borrowed(val_ref.as_ref()),
}
}
#[inline]
pub fn value_cloned(&self) -> RantValue {
match self {
RantVar::ByVal(val) | RantVar::ByValConst(val) => val.clone(),
RantVar::ByRef(val_ref) => val_ref.borrow().clone(),
RantVar::ByRefConst(val_ref) => val_ref.as_ref().clone(),
}
}
}