1 use crate::ident::Ident;
2 use crate::result::FResult;
3 use crate::serialize::{Deserialize, Serialize};
4 use crate::value::Value;
5 use crate::Attrs;
6 use crate::{ast::Expr, error::Interrupt};
7 use std::io;
8 use std::sync::Arc;
9
10 #[derive(Debug, Clone)]
11 enum ScopeValue {
12 LazyVariable(Expr, Option<Arc<Scope>>),
13 }
14
15 impl ScopeValue {
compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<bool>16 pub(crate) fn compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<bool> {
17 let Self::LazyVariable(a1, a2) = self;
18 let Self::LazyVariable(b1, b2) = other;
19 Ok(a1.compare(b1, int)? && compare_option_arc_scope(a2, b2, int)?)
20 }
21
eval<I: Interrupt>( &self, attrs: Attrs, context: &mut crate::Context, int: &I, ) -> FResult<Value>22 fn eval<I: Interrupt>(
23 &self,
24 attrs: Attrs,
25 context: &mut crate::Context,
26 int: &I,
27 ) -> FResult<Value> {
28 match self {
29 Self::LazyVariable(expr, scope) => {
30 let value = crate::ast::evaluate(expr.clone(), scope.clone(), attrs, context, int)?;
31 Ok(value)
32 }
33 }
34 }
35
serialize(&self, write: &mut impl io::Write) -> FResult<()>36 pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> {
37 match self {
38 Self::LazyVariable(e, s) => {
39 e.serialize(write)?;
40 match s {
41 None => false.serialize(write)?,
42 Some(s) => {
43 true.serialize(write)?;
44 s.serialize(write)?;
45 }
46 }
47 }
48 }
49 Ok(())
50 }
51
deserialize(read: &mut impl io::Read) -> FResult<Self>52 pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> {
53 Ok(Self::LazyVariable(Expr::deserialize(read)?, {
54 if bool::deserialize(read)? {
55 None
56 } else {
57 Some(Arc::new(Scope::deserialize(read)?))
58 }
59 }))
60 }
61 }
62
63 #[derive(Debug, Clone)]
64 pub(crate) struct Scope {
65 ident: Ident,
66 value: ScopeValue,
67 inner: Option<Arc<Scope>>,
68 }
69
compare_option_arc_scope<I: Interrupt>( a: &Option<Arc<Scope>>, b: &Option<Arc<Scope>>, int: &I, ) -> FResult<bool>70 pub(crate) fn compare_option_arc_scope<I: Interrupt>(
71 a: &Option<Arc<Scope>>,
72 b: &Option<Arc<Scope>>,
73 int: &I,
74 ) -> FResult<bool> {
75 Ok(match (a, b) {
76 (None, None) => true,
77 (Some(a), Some(b)) => a.compare(b, int)?,
78 _ => false,
79 })
80 }
81
82 impl Scope {
compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<bool>83 pub(crate) fn compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<bool> {
84 Ok(self.ident == other.ident
85 && self.value.compare(&other.value, int)?
86 && compare_option_arc_scope(&self.inner, &other.inner, int)?)
87 }
88
serialize(&self, write: &mut impl io::Write) -> FResult<()>89 pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> {
90 self.ident.serialize(write)?;
91 self.value.serialize(write)?;
92 match &self.inner {
93 None => false.serialize(write)?,
94 Some(s) => {
95 true.serialize(write)?;
96 s.serialize(write)?;
97 }
98 }
99 Ok(())
100 }
101
deserialize(read: &mut impl io::Read) -> FResult<Self>102 pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> {
103 Ok(Self {
104 ident: Ident::deserialize(read)?,
105 value: ScopeValue::deserialize(read)?,
106 inner: {
107 if bool::deserialize(read)? {
108 None
109 } else {
110 Some(Arc::new(Self::deserialize(read)?))
111 }
112 },
113 })
114 }
115
with_scope_value(ident: Ident, value: ScopeValue, inner: Option<Arc<Self>>) -> Self116 const fn with_scope_value(ident: Ident, value: ScopeValue, inner: Option<Arc<Self>>) -> Self {
117 Self {
118 ident,
119 value,
120 inner,
121 }
122 }
123
with_variable( name: Ident, expr: Expr, scope: Option<Arc<Self>>, inner: Option<Arc<Self>>, ) -> Self124 pub(crate) fn with_variable(
125 name: Ident,
126 expr: Expr,
127 scope: Option<Arc<Self>>,
128 inner: Option<Arc<Self>>,
129 ) -> Self {
130 Self::with_scope_value(name, ScopeValue::LazyVariable(expr, scope), inner)
131 }
132
get<I: Interrupt>( &self, ident: &Ident, attrs: Attrs, context: &mut crate::Context, int: &I, ) -> FResult<Option<Value>>133 pub(crate) fn get<I: Interrupt>(
134 &self,
135 ident: &Ident,
136 attrs: Attrs,
137 context: &mut crate::Context,
138 int: &I,
139 ) -> FResult<Option<Value>> {
140 if self.ident.as_str() == ident.as_str() {
141 let value = self.value.eval(attrs, context, int)?;
142 Ok(Some(value))
143 } else {
144 self.inner
145 .as_ref()
146 .map_or_else(|| Ok(None), |inner| inner.get(ident, attrs, context, int))
147 }
148 }
149 }
150