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