Skip to main content

microcom_codegen/
ast.rs

1//! Syntax tree of a MicroCom IDL file.
2
3#[derive(Debug, Clone, Default, PartialEq)]
4pub struct Idl {
5    /// `@name value` lines in file order (`cpp-preamble` holds the text
6    /// between the `@@` markers).
7    pub directives: Vec<Directive>,
8    pub enums: Vec<Enum>,
9    pub structs: Vec<Struct>,
10    pub interfaces: Vec<Interface>,
11}
12
13impl Idl {
14    pub fn directive(&self, name: &str) -> Option<&str> {
15        self.directives.iter().find(|d| d.name == name).map(|d| d.value.as_str())
16    }
17
18    /// All values of a directive that may be repeated (e.g. `clr-map`).
19    pub fn directive_values<'a>(&'a self, name: &'a str) -> impl Iterator<Item = &'a str> {
20        self.directives.iter().filter(move |d| d.name == name).map(|d| d.value.as_str())
21    }
22
23    pub fn find_interface(&self, name: &str) -> Option<&Interface> {
24        self.interfaces.iter().find(|i| i.name == name)
25    }
26}
27
28#[derive(Debug, Clone, PartialEq)]
29pub struct Directive {
30    pub name: String,
31    pub value: String,
32}
33
34/// `[name]` or `[name(value)]`.
35#[derive(Debug, Clone, PartialEq)]
36pub struct Attribute {
37    pub name: String,
38    pub value: Option<String>,
39}
40
41pub fn has_attr(attrs: &[Attribute], name: &str) -> bool {
42    attrs.iter().any(|a| a.name == name)
43}
44
45pub fn attr_value<'a>(attrs: &'a [Attribute], name: &str) -> Option<&'a str> {
46    attrs.iter().find(|a| a.name == name).and_then(|a| a.value.as_deref())
47}
48
49#[derive(Debug, Clone, PartialEq)]
50pub struct Enum {
51    pub attributes: Vec<Attribute>,
52    pub name: String,
53    pub members: Vec<EnumMember>,
54}
55
56impl Enum {
57    pub fn is_class_enum(&self) -> bool {
58        has_attr(&self.attributes, "class-enum")
59    }
60}
61
62#[derive(Debug, Clone, PartialEq)]
63pub struct EnumMember {
64    pub name: String,
65    /// Source text of the value expression, if one was given.
66    pub value: Option<String>,
67}
68
69#[derive(Debug, Clone, PartialEq)]
70pub struct Struct {
71    pub attributes: Vec<Attribute>,
72    pub name: String,
73    pub fields: Vec<Field>,
74}
75
76#[derive(Debug, Clone, PartialEq)]
77pub struct Field {
78    pub ty: TypeRef,
79    pub name: String,
80}
81
82#[derive(Debug, Clone, PartialEq)]
83pub struct TypeRef {
84    /// Type name as written (`int`, `FrnSize`, `IFrnWindow`, ...).
85    pub name: String,
86    /// Number of `*`.
87    pub pointers: u32,
88    /// Trailing `&`.
89    pub reference: bool,
90}
91
92#[derive(Debug, Clone, PartialEq)]
93pub struct Interface {
94    pub attributes: Vec<Attribute>,
95    pub name: String,
96    /// `None` when no base is written (the generators then use `IUnknown`).
97    pub base: Option<String>,
98    pub methods: Vec<Method>,
99}
100
101impl Interface {
102    pub fn uuid(&self) -> Option<&str> {
103        attr_value(&self.attributes, "uuid")
104    }
105
106    pub fn cpp_virtual_inherits(&self) -> bool {
107        has_attr(&self.attributes, "cpp-virtual-inherits")
108    }
109
110    pub fn base_name(&self) -> &str {
111        self.base.as_deref().unwrap_or("IUnknown")
112    }
113}
114
115#[derive(Debug, Clone, PartialEq)]
116pub struct Method {
117    /// Attributes written before the return type (e.g. `[intptr]`).
118    pub attributes: Vec<Attribute>,
119    pub return_type: TypeRef,
120    pub name: String,
121    pub params: Vec<Param>,
122}
123
124#[derive(Debug, Clone, PartialEq)]
125pub struct Param {
126    /// `[const]`, `[intptr]`, ...
127    pub attributes: Vec<Attribute>,
128    pub ty: TypeRef,
129    pub name: String,
130}
131
132impl Param {
133    pub fn is_const(&self) -> bool {
134        has_attr(&self.attributes, "const")
135    }
136}