compose_library/foundations/
ty.rs1use crate::{Scope, Sink, Trace, UnBoundError, Value};
2use compose_library::diag::StrResult;
3use compose_library::{UnboundItem, UntypedRef};
4use compose_macros::{cast, ty};
5use compose_syntax::Span;
6use compose_utils::Static;
7use ecow::eco_format;
8use std::fmt::Display;
9use std::sync::LazyLock;
10
11#[derive(Clone, Debug, PartialEq)]
12#[ty(cast, name = "type")]
13pub struct Type(Static<NativeTypeData>);
14
15impl Type {
16 pub fn of<T: NativeType>() -> Self {
17 T::ty()
18 }
19
20 pub fn scope(&self) -> &'static Scope {
21 &self.0.0.scope
22 }
23
24 pub fn field(&self, field: &str, access_span: Span, sink: &mut Sink) -> StrResult<&Value> {
25 self.0
26 .scope
27 .get(field)
28 .map(|b| b.read_checked(access_span, sink))
29 .ok_or_else(|| eco_format!("no field or method `{}` on type `{}`", field, self))
30 }
31
32 pub fn path(
33 &self,
34 path: &str,
35 access_span: Span,
36 sink: &mut Sink,
37 ) -> Result<&Value, UnBoundError> {
38 self.0
39 .scope
40 .try_get(path)
41 .map_err(|e| e.with_item(UnboundItem::AssociatedFieldOrFunction(self.name().into())))
42 .map(|b| b.read_checked(access_span, sink))
43 }
44
45 pub fn name(&self) -> &'static str {
46 self.0.name
47 }
48}
49
50impl Trace for Type {
51 fn visit_refs(&self, f: &mut dyn FnMut(UntypedRef)) {
52 self.scope().visit_refs(f);
53 }
54}
55
56#[derive(Debug)]
57pub struct NativeTypeData {
58 pub name: &'static str,
59 pub title: &'static str,
60 pub docs: &'static str,
61 pub scope: LazyLock<&'static Scope>,
62}
63
64impl Display for Type {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 write!(f, "{}", self.0.name)
67 }
68}
69
70pub trait NativeType {
71 const NAME: &'static str;
72 fn ty() -> Type {
73 Type::from(Self::data())
74 }
75
76 fn data() -> &'static NativeTypeData;
77}
78
79impl From<&'static NativeTypeData> for Type {
80 fn from(data: &'static NativeTypeData) -> Self {
81 Self(Static(data))
82 }
83}
84
85cast! {
86 &'static NativeTypeData,
87 self => Type::from(self).into_value(),
88}