Skip to main content

xidl_parser/hir/
annotation.rs

1use super::*;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize, Clone)]
5pub enum Annotation {
6    Id {
7        value: ConstExpr,
8    },
9    Key,
10    Builtin {
11        name: String,
12        params: Option<AnnotationParams>,
13    },
14    ScopedName {
15        name: ScopedName,
16        params: Option<AnnotationParams>,
17    },
18}
19
20#[derive(Debug, Serialize, Deserialize, Clone)]
21pub enum AnnotationParams {
22    ConstExpr(ConstExpr),
23    Params(Vec<AnnotationParam>),
24    Raw(String),
25}
26
27#[derive(Debug, Serialize, Deserialize, Clone)]
28pub struct AnnotationParam {
29    pub ident: String,
30    pub value: Option<ConstExpr>,
31}
32
33pub fn annotation_id_value(annotations: &[Annotation]) -> Option<u32> {
34    for annotation in annotations {
35        if let Annotation::Id { value } = annotation {
36            if let Some(value) = super::expr::const_expr_to_i64(value) {
37                if value >= 0 && value <= u32::MAX as i64 {
38                    return Some(value as u32);
39                }
40            }
41        }
42    }
43    None
44}
45
46pub fn expand_annotations(values: Vec<crate::typed_ast::AnnotationAppl>) -> Vec<Annotation> {
47    let mut out = Vec::new();
48    for value in values {
49        push_annotation(&mut out, value);
50    }
51    out
52}
53
54fn push_annotation(out: &mut Vec<Annotation>, mut value: crate::typed_ast::AnnotationAppl) {
55    let extra = std::mem::take(&mut value.extra);
56    out.push(Annotation::from(value));
57    for item in extra {
58        push_annotation(out, item);
59    }
60}
61
62impl From<crate::typed_ast::AnnotationAppl> for Annotation {
63    fn from(value: crate::typed_ast::AnnotationAppl) -> Self {
64        let params = value.params.map(Into::into);
65        match value.name {
66            crate::typed_ast::AnnotationName::ScopedName(name) => Self::ScopedName {
67                name: name.into(),
68                params,
69            },
70            crate::typed_ast::AnnotationName::Builtin(name) => {
71                if name.eq_ignore_ascii_case("id") {
72                    if let Some(AnnotationParams::ConstExpr(expr)) = &params {
73                        return Self::Id {
74                            value: expr.clone(),
75                        };
76                    }
77                } else if name.eq_ignore_ascii_case("key") {
78                    if params.is_none() {
79                        return Self::Key;
80                    }
81                }
82                Self::Builtin { name, params }
83            }
84        }
85    }
86}
87
88impl From<crate::typed_ast::AnnotationParams> for AnnotationParams {
89    fn from(value: crate::typed_ast::AnnotationParams) -> Self {
90        match value {
91            crate::typed_ast::AnnotationParams::ConstExpr(expr) => Self::ConstExpr(expr.into()),
92            crate::typed_ast::AnnotationParams::Params(params) => {
93                Self::Params(params.into_iter().map(Into::into).collect())
94            }
95            crate::typed_ast::AnnotationParams::Raw(value) => Self::Raw(value),
96        }
97    }
98}
99
100impl From<crate::typed_ast::AnnotationApplParam> for AnnotationParam {
101    fn from(value: crate::typed_ast::AnnotationApplParam) -> Self {
102        Self {
103            ident: value.ident.0,
104            value: value.value.map(Into::into),
105        }
106    }
107}