tinymist_analysis/ty/
convert.rs

1use typst::syntax::Span;
2
3use crate::func_signature;
4
5use super::*;
6
7/// Checks if a value is a plain value.
8pub fn is_plain_value(value: &Value) -> bool {
9    matches!(
10        value,
11        Value::Label(..)
12            | Value::None
13            | Value::Auto
14            | Value::Bool(..)
15            | Value::Int(..)
16            | Value::Float(..)
17            | Value::Decimal(..)
18            | Value::Length(..)
19            | Value::Angle(..)
20            | Value::Ratio(..)
21            | Value::Relative(..)
22            | Value::Fraction(..)
23            | Value::Color(..)
24            | Value::Gradient(..)
25            | Value::Tiling(..)
26            | Value::Symbol(..)
27            | Value::Version(..)
28            | Value::Str(..)
29            | Value::Bytes(..)
30            | Value::Datetime(..)
31            | Value::Duration(..)
32            | Value::Content(..)
33            | Value::Styles(..)
34    )
35}
36
37/// Gets the type of a value.
38#[comemo::memoize]
39pub fn term_value(value: &Value) -> Ty {
40    match value {
41        Value::Array(a) => {
42            let values = a
43                .iter()
44                .map(|v| term_value_rec(v, Span::detached()))
45                .collect::<Vec<_>>();
46            Ty::Tuple(values.into())
47        }
48        // todo: term arguments
49        Value::Args(..) => Ty::Builtin(BuiltinTy::Args),
50        Value::Dict(dict) => {
51            let values = dict
52                .iter()
53                .map(|(k, v)| (k.as_str().into(), term_value_rec(v, Span::detached())))
54                .collect();
55            Ty::Dict(RecordTy::new(values))
56        }
57        Value::Module(module) => {
58            let values = module
59                .scope()
60                .iter()
61                .map(|(k, b)| (k.into(), term_value_rec(b.read(), b.span())))
62                .collect();
63            Ty::Dict(RecordTy::new(values))
64        }
65        Value::Type(ty) => Ty::Builtin(BuiltinTy::TypeType(*ty)),
66        Value::Dyn(dyn_val) => Ty::Builtin(BuiltinTy::Type(dyn_val.ty())),
67        Value::Func(func) => Ty::Func(func_signature(func.clone()).type_sig()),
68        _ if is_plain_value(value) => Ty::Value(InsTy::new(value.clone())),
69        _ => Ty::Any,
70    }
71}
72
73/// Gets the type of a value recursively.
74pub fn term_value_rec(value: &Value, s: Span) -> Ty {
75    match value {
76        Value::Type(ty) => Ty::Builtin(BuiltinTy::TypeType(*ty)),
77        Value::Dyn(v) => Ty::Builtin(BuiltinTy::Type(v.ty())),
78        Value::None
79        | Value::Auto
80        | Value::Array(..)
81        | Value::Args(..)
82        | Value::Dict(..)
83        | Value::Module(..)
84        | Value::Func(..)
85        | Value::Label(..)
86        | Value::Bool(..)
87        | Value::Int(..)
88        | Value::Float(..)
89        | Value::Decimal(..)
90        | Value::Length(..)
91        | Value::Angle(..)
92        | Value::Ratio(..)
93        | Value::Relative(..)
94        | Value::Fraction(..)
95        | Value::Color(..)
96        | Value::Gradient(..)
97        | Value::Tiling(..)
98        | Value::Symbol(..)
99        | Value::Version(..)
100        | Value::Str(..)
101        | Value::Bytes(..)
102        | Value::Datetime(..)
103        | Value::Duration(..)
104        | Value::Content(..)
105        | Value::Styles(..) => {
106            if !s.is_detached() {
107                Ty::Value(InsTy::new_at(value.clone(), s))
108            } else {
109                Ty::Value(InsTy::new(value.clone()))
110            }
111        }
112    }
113}