1use std::ops::{Deref, DerefMut};
5use std::borrow::Cow;
6use std::convert::{TryInto, TryFrom, Infallible};
7use std::cmp::Ordering;
8use smallvec::SmallVec;
9use std::fmt::{self, Debug, Display, Formatter};
10use std::hash::{Hash, Hasher};
11use either::Either;
12
13use crate::graph::{
14 node::{Node, WeakNode, NodeData, View, Backlink},
15 region::{WeakRegion, Parameter},
16 cons::CacheEntry
17};
18
19pub mod primitive;
20use primitive::{
21 Unit,
22 logical::{self, LogicalOp, Bool}
23};
24
25pub mod expr;
26use expr::Sexpr;
27
28
29pub mod lambda;
30use lambda::Lambda;
31
32pub mod error;
33use error::{IncomparableRegions, ValueError};
34
35pub mod judgement;
36use judgement::JEq;
37
38pub mod eval;
39
40pub mod cons;
41use cons::VALUE_CACHE;
42
43const SMALL_DEPENDENTS: usize = 2;
45
46#[derive(Debug, Clone, PartialEq, Eq, Hash)]
48pub enum ValueEnum {
49 Sexpr(Sexpr),
51 Bool(bool),
53 LogicalOp(LogicalOp),
55 Lambda(Lambda),
57 BoolTy(Bool),
59 UnitTy(Unit),
61 Parameter(Parameter)
63}
64
65#[derive(Debug, Clone)]
67pub enum Dependencies<'a> {
68 Slice(std::slice::Iter<'a, ValId>)
70}
71
72impl<'a> Iterator for Dependencies<'a> {
73 type Item = &'a ValId;
74 fn next(&mut self) -> Option<&'a ValId> {
75 match self {
76 Dependencies::Slice(s) => s.next()
77 }
78 }
79}
80
81impl ValueEnum {
82 pub fn applicable(&self) -> bool {
84 use ValueEnum::*;
85 match self {
86 Sexpr(_) | LogicalOp(_) | Parameter(_) | Lambda(_) => true,
87 _ => false
88 }
89 }
90 pub fn name_print(&self, fmt: &mut fmt::Formatter, name: Option<&str>)
92 -> Result<(), fmt::Error> {
93 use ValueEnum::*;
94 match (self, name) {
95 (Parameter(parameter), Some(name)) => write!(fmt, "({} : {})", name, parameter.ty),
96 (value, _) => write!(fmt, "{}", value)
97 }
98 }
99 pub fn base_region(&self) -> Cow<WeakRegion> {
101 match self {
102 ValueEnum::Parameter(p) => Cow::Borrowed(p.region()),
103 ValueEnum::Lambda(l) => Cow::Owned(l.region().downgrade()),
104 _ => Cow::Owned(WeakRegion::default())
105 }
106 }
107}
108
109pub trait ValueDesc: TryInto<ValId> {
111 type Err:
113 From<<Self as TryInto<ValId>>::Error>
114 + Into<ValueError>;
115 #[inline] fn to_node<E>(self) -> Result<ValId, E>
117 where <Self as TryInto<ValId>>::Error: Into<E> {
118 let v: Result<ValId, _> = self.try_into();
119 v.map_err(|err| err.into())
120 }
121}
122
123pub trait Value: ValueDesc + TryInto<ValueEnum> + JEq<ValueEnum> + JEq<Self> + JEq<ValId> {
125 #[inline] fn to_value<E>(self) -> Result<ValueEnum, E>
127 where <Self as TryInto<ValueEnum>>::Error: Into<E> {
128 let v: Result<ValueEnum, _> = self.try_into();
129 v.map_err(|err| err.into())
130 }
131}
132
133impl ValueDesc for ValueEnum {
134 type Err = ValueError;
135 fn to_node<E>(self) -> Result<ValId, E>
136 where <Self as TryInto<ValId>>::Error: Into<E> {
137 match self {
138 ValueEnum::Sexpr(s) => s.to_node(),
139 v => Node::try_new(ValueData::from(v)).map_err(|err| err.into())
140 }
141 }
142}
143
144impl Value for ValueEnum {}
145
146macro_rules! primitive_value {
147 ($p_ty:ty, $e_ty:expr) => {
148 impl From<$p_ty> for ValueEnum {
149 fn from(p: $p_ty) -> ValueEnum { $e_ty(p) }
150 }
151 impl From<$p_ty> for ValueData {
152 fn from(p: $p_ty) -> ValueData { ValueData::new($e_ty(p)) }
153 }
154 impl From<$p_ty> for ValId {
155 fn from(p: $p_ty) -> ValId {
156 Node::try_new(ValueData::new($e_ty(p))).expect("Impossible")
157 }
158 }
159 impl ValueDesc for $p_ty { type Err = Infallible; }
160 impl Value for $p_ty {}
161 }
162}
163
164primitive_value!(bool, ValueEnum::Bool);
165primitive_value!(Bool, ValueEnum::BoolTy);
166primitive_value!(Unit, ValueEnum::UnitTy);
167primitive_value!(LogicalOp, ValueEnum::LogicalOp);
168primitive_value!(logical::Binary, |b| ValueEnum::LogicalOp(LogicalOp::Binary(b)));
169primitive_value!(logical::Unary, |u| ValueEnum::LogicalOp(LogicalOp::Unary(u)));
170
171impl Display for ValueEnum {
172 fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
173 match self {
174 ValueEnum::Sexpr(x) => write!(fmt, "{}", x),
175 ValueEnum::Bool(x) => write!(fmt, "#{}", x),
176 ValueEnum::LogicalOp(x) => write!(fmt, "{}", x),
177 ValueEnum::BoolTy(b) => write!(fmt, "{}", b),
178 ValueEnum::Lambda(_l) => write!(fmt, "#lambda #TODO"), ValueEnum::UnitTy(u) => write!(fmt, "{}", u),
180 ValueEnum::Parameter(p) => write!(fmt, "#param({})", p.ty)
181 }
182 }
183}
184
185#[derive(Debug, Clone)]
187pub struct ValueData {
188 pub value: ValueEnum,
190 pub name: Option<String>,
192 pub region: WeakRegion,
194 dependents: SmallVec<[WeakId; SMALL_DEPENDENTS]>,
196 }
201
202impl<R> View<R> where R: DerefMut<Target=ValueData> {
203 #[inline]
205 pub fn add_dependent(&mut self, dependent: WeakId) {
206 self.0.deref_mut().dependents.push(dependent)
207 }
208 pub fn set_name(&mut self, name: String) -> Result<(), String> {
210 if self.name.is_none() {
211 self.0.name = Some(name);
212 Ok(())
213 } else {
214 Err(name)
215 }
216 }
217}
218
219impl Deref for ValueData {
220 type Target = ValueEnum;
221 #[inline(always)] fn deref(&self) -> &ValueEnum { &self.value }
222}
223
224impl ValueData {
225 pub fn with_region(value: ValueEnum, region: WeakRegion) -> ValueData {
238 ValueData {
239 value,
240 region,
241 name: None,
242 dependents: SmallVec::new()
243 }
244 }
245 pub fn new(value: ValueEnum) -> ValueData {
247 Self::with_region(value, WeakRegion::default())
248 }
249 #[inline]
251 pub fn add_dependent(&mut self, dependent: WeakNode<Self>) { self.dependents.push(dependent) }
252 pub fn dependencies(&self) -> Dependencies {
254 match &self.value {
255 ValueEnum::Sexpr(s) => Dependencies::Slice(s.dependencies()),
256 ValueEnum::Lambda(l) => Dependencies::Slice(l.dependencies()),
257 _ => Dependencies::Slice([].iter())
258 }
259 }
260 pub fn dependents(&self) -> &[WeakId] { self.dependents.deref() }
262}
263
264impl Display for ValueData {
265 fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
266 self.value.name_print(fmt, self.name.as_ref().map(|s| s.as_str()))
267 }
268}
269
270impl From<ValueEnum> for ValueData {
271 fn from(value: ValueEnum) -> ValueData { ValueData::new(value) }
272}
273
274impl PartialEq for ValueData {
275 fn eq(&self, other: &ValueData) -> bool {
276 self.value == other.value
277 }
278}
279
280impl Hash for ValueData {
281 fn hash<H: Hasher>(&self, hasher: &mut H) {
282 self.value.hash(hasher)
283 }
284}
285
286pub type ValId = Node<ValueData>;
288
289pub type WeakId = WeakNode<ValueData>;
291
292impl NodeData for ValueData {
293 type Error = ValueError;
294 type CacheAcceptor = CacheEntry<'static, ValueData>;
295 #[inline] fn backlink(&mut self, backlink: Backlink<ValueData>) -> Result<(), ValueError> {
296 let mut region = WeakRegion::default();
300 std::mem::swap(&mut self.region, &mut region);
301
302 let max_region = |acc: &mut WeakRegion, region: &WeakRegion| {
303 let ord = (*acc).partial_cmp(region);
304 match ord {
305 None => return Err(
306 ValueError::IncomparableRegions(
307 IncomparableRegions(
308 SmallVec::from([region.clone(), region.clone()])
309 )
310 )
311 ),
312 Some(Ordering::Greater) => *acc = region.clone(),
313 _ => {}
314 }
315 Ok(())
316 };
317 max_region(&mut region, &self.value.base_region())?;
318
319 for dependency in self.dependencies() {
320 let mut dependency = dependency.data_mut();
321 dependency.add_dependent(backlink.downgrade());
322 max_region(&mut region, &dependency.region)?;
323 }
324 self.region = region;
325 Ok(())
326 }
327 #[inline] fn dedup(&mut self) -> Either<ValId, CacheEntry<'static, ValueData>> {
328 VALUE_CACHE.deref().cached_entry(self)
329 }
330}
331
332impl ValId {
333 #[inline] pub fn add_dependent(&self, dependent: WeakId) {
335 self.data_mut().add_dependent(dependent)
336 }
337}
338
339impl TryFrom<ValueEnum> for ValId {
340 type Error = ValueError;
341 fn try_from(value: ValueEnum) -> Result<ValId, ValueError> {
342 Node::try_new(ValueData::try_from(value)?)
343 }
344}