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