graphix_compiler/typ/
tval.rs

1use super::{PrintFlag, Type};
2use crate::{env::Env, typ::format_with_flags, Rt, UserEvent};
3use fxhash::FxHashSet;
4use netidx::publisher::Value;
5use netidx_value::NakedValue;
6use poolshark::local::LPooled;
7use std::fmt;
8
9/// A value with it's type, used for formatting
10pub struct TVal<'a, R: Rt, E: UserEvent> {
11    pub env: &'a Env<R, E>,
12    pub typ: &'a Type,
13    pub v: &'a Value,
14}
15
16impl<'a, R: Rt, E: UserEvent> TVal<'a, R, E> {
17    fn fmt_int(
18        &self,
19        f: &mut fmt::Formatter<'_>,
20        hist: &mut FxHashSet<(usize, usize)>,
21    ) -> fmt::Result {
22        if !self.typ.is_a(&self.env, &self.v) {
23            return format_with_flags(PrintFlag::DerefTVars, || {
24                write!(
25                    f,
26                    "error, type {} does not match value {}",
27                    self.typ,
28                    NakedValue(self.v)
29                )
30            });
31        }
32        match (&self.typ, &self.v) {
33            (
34                Type::Primitive(_)
35                | Type::Bottom
36                | Type::Any
37                | Type::Fn(_)
38                | Type::Error(_),
39                v,
40            ) => {
41                write!(f, "{}", NakedValue(v))
42            }
43            (Type::Ref { .. }, v) => match self.typ.lookup_ref(&self.env) {
44                Err(e) => write!(f, "error, {e:?}"),
45                Ok(typ) => {
46                    let typ_addr = (typ as *const Type).addr();
47                    let v_addr = (self.v as *const Value).addr();
48                    if !hist.contains(&(typ_addr, v_addr)) {
49                        hist.insert((typ_addr, v_addr));
50                        Self { typ, env: self.env, v }.fmt_int(f, hist)?
51                    }
52                    Ok(())
53                }
54            },
55            (Type::Array(et), Value::Array(a)) => {
56                write!(f, "[")?;
57                for (i, v) in a.iter().enumerate() {
58                    Self { typ: et, env: self.env, v }.fmt_int(f, hist)?;
59                    if i < a.len() - 1 {
60                        write!(f, ", ")?
61                    }
62                }
63                write!(f, "]")
64            }
65            (Type::Array(_), v) => write!(f, "{}", NakedValue(v)),
66            (Type::Map { key, value }, Value::Map(m)) => {
67                write!(f, "{{")?;
68                for (i, (k, v)) in m.into_iter().enumerate() {
69                    Self { typ: key, env: self.env, v: k }.fmt_int(f, hist)?;
70                    write!(f, " => ")?;
71                    Self { typ: value, env: self.env, v: v }.fmt_int(f, hist)?;
72                    if i < m.len() - 1 {
73                        write!(f, ", ")?
74                    }
75                }
76                write!(f, "}}")
77            }
78            (Type::Map { .. }, v) => write!(f, "{}", NakedValue(v)),
79            (Type::ByRef(_), v) => write!(f, "{}", NakedValue(v)),
80            (Type::Struct(flds), Value::Array(a)) => {
81                write!(f, "{{")?;
82                for (i, ((n, et), v)) in flds.iter().zip(a.iter()).enumerate() {
83                    write!(f, "{n}: ")?;
84                    match v {
85                        Value::Array(a) if a.len() == 2 => {
86                            Self { typ: et, env: self.env, v: &a[1] }.fmt_int(f, hist)?
87                        }
88                        _ => write!(f, "err")?,
89                    }
90                    if i < flds.len() - 1 {
91                        write!(f, ", ")?
92                    }
93                }
94                write!(f, "}}")
95            }
96            (Type::Struct(_), v) => write!(f, "{}", NakedValue(v)),
97            (Type::Tuple(flds), Value::Array(a)) => {
98                write!(f, "(")?;
99                for (i, (t, v)) in flds.iter().zip(a.iter()).enumerate() {
100                    Self { typ: t, env: self.env, v }.fmt_int(f, hist)?;
101                    if i < flds.len() - 1 {
102                        write!(f, ", ")?
103                    }
104                }
105                write!(f, ")")
106            }
107            (Type::Tuple(_), v) => write!(f, "{}", NakedValue(v)),
108            (Type::TVar(tv), v) => match &*tv.read().typ.read() {
109                None => write!(f, "{}", NakedValue(v)),
110                Some(typ) => TVal { env: self.env, typ, v }.fmt_int(f, hist),
111            },
112            (Type::Variant(n, flds), Value::Array(a)) if a.len() >= 2 => {
113                write!(f, "`{n}(")?;
114                for (i, (t, v)) in flds.iter().zip(a[1..].iter()).enumerate() {
115                    Self { typ: t, env: self.env, v }.fmt_int(f, hist)?;
116                    if i < flds.len() - 1 {
117                        write!(f, ", ")?
118                    }
119                }
120                write!(f, ")")
121            }
122            (Type::Variant(_, _), Value::String(s)) => write!(f, "`{s}"),
123            (Type::Variant(_, _), v) => write!(f, "{}", NakedValue(v)),
124            (Type::Set(ts), v) => match ts.iter().find(|t| t.is_a(&self.env, v)) {
125                None => write!(f, "{}", NakedValue(v)),
126                Some(t) => Self { typ: t, env: self.env, v }.fmt_int(f, hist),
127            },
128        }
129    }
130}
131
132impl<'a, R: Rt, E: UserEvent> fmt::Display for TVal<'a, R, E> {
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        self.fmt_int(f, &mut LPooled::take())
135    }
136}