rusty_cpp/parser/
type_annotations.rs

1// Type-level lifetime annotations for STL and other types
2// This module handles @type_lifetime annotations that describe
3// how lifetimes flow through type methods and members
4
5use std::collections::HashMap;
6use regex::Regex;
7
8#[derive(Debug, Clone, PartialEq)]
9pub enum TypeLifetime {
10    // &'self - borrows from the object
11    SelfRef,
12    // &'self mut - mutably borrows from the object  
13    SelfMutRef,
14    // &'a - reference with explicit lifetime
15    Ref(String),
16    // &'a mut - mutable reference with explicit lifetime
17    MutRef(String),
18    // *const - const raw pointer
19    ConstPtr,
20    // *mut - mutable raw pointer
21    MutPtr,
22    // owned - ownership transfer
23    Owned,
24}
25
26#[derive(Debug, Clone)]
27pub struct MethodLifetime {
28    pub method_name: String,
29    pub is_const: bool,
30    pub param_lifetimes: Vec<TypeLifetime>,
31    pub return_lifetime: TypeLifetime,
32}
33
34#[derive(Debug, Clone)]
35pub struct TypeLifetimeSpec {
36    pub type_name: String,
37    pub methods: HashMap<String, Vec<MethodLifetime>>, // method name -> overloads
38    pub members: HashMap<String, TypeLifetime>,
39    pub typedefs: HashMap<String, TypeLifetime>, // iterator, const_iterator, etc.
40}
41
42// Global registry of type lifetime specifications
43pub struct TypeLifetimeRegistry {
44    specs: HashMap<String, TypeLifetimeSpec>,
45}
46
47impl TypeLifetimeRegistry {
48    pub fn new() -> Self {
49        let mut registry = TypeLifetimeRegistry {
50            specs: HashMap::new(),
51        };
52        registry.load_stl_annotations();
53        registry
54    }
55    
56    pub fn get_type_spec(&self, type_name: &str) -> Option<&TypeLifetimeSpec> {
57        // Handle template instantiations like vector<int>
58        let base_type = extract_base_type(type_name);
59        self.specs.get(base_type)
60    }
61    
62    pub fn add_type_spec(&mut self, spec: TypeLifetimeSpec) {
63        self.specs.insert(spec.type_name.clone(), spec);
64    }
65    
66    // Load built-in STL annotations
67    fn load_stl_annotations(&mut self) {
68        // std::vector<T>
69        let mut vector_spec = TypeLifetimeSpec {
70            type_name: "std::vector".to_string(),
71            methods: HashMap::new(),
72            members: HashMap::new(),
73            typedefs: HashMap::new(),
74        };
75        
76        // Add vector methods
77        vector_spec.methods.insert("at".to_string(), vec![
78            MethodLifetime {
79                method_name: "at".to_string(),
80                is_const: false,
81                param_lifetimes: vec![TypeLifetime::Owned], // size_t
82                return_lifetime: TypeLifetime::SelfMutRef,
83            },
84            MethodLifetime {
85                method_name: "at".to_string(),
86                is_const: true,
87                param_lifetimes: vec![TypeLifetime::Owned], // size_t
88                return_lifetime: TypeLifetime::SelfRef,
89            },
90        ]);
91        
92        vector_spec.methods.insert("operator[]".to_string(), vec![
93            MethodLifetime {
94                method_name: "operator[]".to_string(),
95                is_const: false,
96                param_lifetimes: vec![TypeLifetime::Owned], // size_t
97                return_lifetime: TypeLifetime::SelfMutRef,
98            },
99            MethodLifetime {
100                method_name: "operator[]".to_string(),
101                is_const: true,
102                param_lifetimes: vec![TypeLifetime::Owned], // size_t
103                return_lifetime: TypeLifetime::SelfRef,
104            },
105        ]);
106        
107        vector_spec.methods.insert("push_back".to_string(), vec![
108            MethodLifetime {
109                method_name: "push_back".to_string(),
110                is_const: false,
111                param_lifetimes: vec![TypeLifetime::Owned], // T
112                return_lifetime: TypeLifetime::Owned, // void
113            },
114        ]);
115        
116        vector_spec.methods.insert("data".to_string(), vec![
117            MethodLifetime {
118                method_name: "data".to_string(),
119                is_const: false,
120                param_lifetimes: vec![],
121                return_lifetime: TypeLifetime::MutPtr,
122            },
123            MethodLifetime {
124                method_name: "data".to_string(),
125                is_const: true,
126                param_lifetimes: vec![],
127                return_lifetime: TypeLifetime::ConstPtr,
128            },
129        ]);
130        
131        vector_spec.methods.insert("begin".to_string(), vec![
132            MethodLifetime {
133                method_name: "begin".to_string(),
134                is_const: false,
135                param_lifetimes: vec![],
136                return_lifetime: TypeLifetime::SelfMutRef,
137            },
138            MethodLifetime {
139                method_name: "begin".to_string(),
140                is_const: true,
141                param_lifetimes: vec![],
142                return_lifetime: TypeLifetime::SelfRef,
143            },
144        ]);
145        
146        vector_spec.typedefs.insert("iterator".to_string(), TypeLifetime::SelfMutRef);
147        vector_spec.typedefs.insert("const_iterator".to_string(), TypeLifetime::SelfRef);
148        
149        self.specs.insert("std::vector".to_string(), vector_spec);
150        
151        // std::unique_ptr<T>
152        let mut unique_ptr_spec = TypeLifetimeSpec {
153            type_name: "std::unique_ptr".to_string(),
154            methods: HashMap::new(),
155            members: HashMap::new(),
156            typedefs: HashMap::new(),
157        };
158        
159        unique_ptr_spec.methods.insert("get".to_string(), vec![
160            MethodLifetime {
161                method_name: "get".to_string(),
162                is_const: false,
163                param_lifetimes: vec![],
164                return_lifetime: TypeLifetime::MutPtr,
165            },
166            MethodLifetime {
167                method_name: "get".to_string(),
168                is_const: true,
169                param_lifetimes: vec![],
170                return_lifetime: TypeLifetime::ConstPtr,
171            },
172        ]);
173        
174        unique_ptr_spec.methods.insert("operator*".to_string(), vec![
175            MethodLifetime {
176                method_name: "operator*".to_string(),
177                is_const: false,
178                param_lifetimes: vec![],
179                return_lifetime: TypeLifetime::SelfMutRef,
180            },
181            MethodLifetime {
182                method_name: "operator*".to_string(),
183                is_const: true,
184                param_lifetimes: vec![],
185                return_lifetime: TypeLifetime::SelfRef,
186            },
187        ]);
188        
189        unique_ptr_spec.methods.insert("release".to_string(), vec![
190            MethodLifetime {
191                method_name: "release".to_string(),
192                is_const: false,
193                param_lifetimes: vec![],
194                return_lifetime: TypeLifetime::Owned,
195            },
196        ]);
197        
198        self.specs.insert("std::unique_ptr".to_string(), unique_ptr_spec);
199        
200        // std::map<K,V>
201        let mut map_spec = TypeLifetimeSpec {
202            type_name: "std::map".to_string(),
203            methods: HashMap::new(),
204            members: HashMap::new(),
205            typedefs: HashMap::new(),
206        };
207        
208        map_spec.methods.insert("at".to_string(), vec![
209            MethodLifetime {
210                method_name: "at".to_string(),
211                is_const: false,
212                param_lifetimes: vec![TypeLifetime::SelfRef], // const K&
213                return_lifetime: TypeLifetime::SelfMutRef,
214            },
215            MethodLifetime {
216                method_name: "at".to_string(),
217                is_const: true,
218                param_lifetimes: vec![TypeLifetime::SelfRef], // const K&
219                return_lifetime: TypeLifetime::SelfRef,
220            },
221        ]);
222        
223        map_spec.methods.insert("operator[]".to_string(), vec![
224            MethodLifetime {
225                method_name: "operator[]".to_string(),
226                is_const: false,
227                param_lifetimes: vec![TypeLifetime::SelfRef], // const K&
228                return_lifetime: TypeLifetime::SelfMutRef,
229            },
230        ]);
231        
232        map_spec.methods.insert("find".to_string(), vec![
233            MethodLifetime {
234                method_name: "find".to_string(),
235                is_const: false,
236                param_lifetimes: vec![TypeLifetime::SelfRef], // const K&
237                return_lifetime: TypeLifetime::SelfMutRef,
238            },
239            MethodLifetime {
240                method_name: "find".to_string(),
241                is_const: true,
242                param_lifetimes: vec![TypeLifetime::SelfRef], // const K&
243                return_lifetime: TypeLifetime::SelfRef,
244            },
245        ]);
246        
247        self.specs.insert("std::map".to_string(), map_spec);
248        
249        // Add more STL types as needed...
250    }
251}
252
253// Parse @type_lifetime annotations from comments
254pub fn parse_type_lifetime_annotation(comment: &str) -> Option<TypeLifetimeSpec> {
255    let type_re = Regex::new(r"@type_lifetime:\s*([^{]+)\s*\{([^}]+)\}").ok()?;
256    
257    if let Some(captures) = type_re.captures(comment) {
258        let type_name = captures.get(1)?.as_str().trim();
259        let body = captures.get(2)?.as_str();
260        
261        let mut spec = TypeLifetimeSpec {
262            type_name: type_name.to_string(),
263            methods: HashMap::new(),
264            members: HashMap::new(),
265            typedefs: HashMap::new(),
266        };
267        
268        // Parse each line in the body
269        for line in body.lines() {
270            let line = line.trim();
271            if line.is_empty() || line.starts_with("//") {
272                continue;
273            }
274            
275            if line.contains("->") {
276                // Method signature
277                parse_method_lifetime(line, &mut spec);
278            } else if line.contains(":") {
279                // Member or typedef
280                parse_member_lifetime(line, &mut spec);
281            }
282        }
283        
284        Some(spec)
285    } else {
286        None
287    }
288}
289
290fn parse_method_lifetime(line: &str, spec: &mut TypeLifetimeSpec) {
291    // Parse patterns like: at(size_t) const -> &'self
292    let method_re = Regex::new(r"(\w+)\((.*?)\)(\s+const)?\s*->\s*(.+)").unwrap();
293    
294    if let Some(captures) = method_re.captures(line) {
295        let method_name = captures.get(1).map(|m| m.as_str()).unwrap_or("");
296        let params = captures.get(2).map(|m| m.as_str()).unwrap_or("");
297        let is_const = captures.get(3).is_some();
298        let return_type = captures.get(4).map(|m| m.as_str()).unwrap_or("");
299        
300        let method_lifetime = MethodLifetime {
301            method_name: method_name.to_string(),
302            is_const,
303            param_lifetimes: parse_param_types(params),
304            return_lifetime: parse_type_lifetime(return_type),
305        };
306        
307        spec.methods.entry(method_name.to_string())
308            .or_insert_with(Vec::new)
309            .push(method_lifetime);
310    }
311}
312
313fn parse_member_lifetime(line: &str, spec: &mut TypeLifetimeSpec) {
314    // Parse patterns like: iterator: &'self mut
315    if let Some(colon_pos) = line.find(':') {
316        let name = line[..colon_pos].trim();
317        let lifetime = line[colon_pos + 1..].trim();
318        
319        // Check if it's a known typedef
320        if name == "iterator" || name == "const_iterator" || 
321           name == "reference" || name == "const_reference" ||
322           name == "pointer" || name == "const_pointer" {
323            spec.typedefs.insert(name.to_string(), parse_type_lifetime(lifetime));
324        } else {
325            spec.members.insert(name.to_string(), parse_type_lifetime(lifetime));
326        }
327    }
328}
329
330fn parse_param_types(params: &str) -> Vec<TypeLifetime> {
331    if params.is_empty() {
332        return vec![];
333    }
334    
335    params.split(',')
336        .map(|p| parse_type_lifetime(p.trim()))
337        .collect()
338}
339
340fn parse_type_lifetime(s: &str) -> TypeLifetime {
341    let s = s.trim();
342    
343    match s {
344        "&'self" => TypeLifetime::SelfRef,
345        "&'self mut" => TypeLifetime::SelfMutRef,
346        "*const" => TypeLifetime::ConstPtr,
347        "*mut" => TypeLifetime::MutPtr,
348        "owned" => TypeLifetime::Owned,
349        _ => {
350            if s.starts_with("&'") && s.contains("mut") {
351                // Extract lifetime name
352                if let Some(name) = extract_lifetime_name(s) {
353                    TypeLifetime::MutRef(name)
354                } else {
355                    TypeLifetime::Owned
356                }
357            } else if s.starts_with("&'") {
358                if let Some(name) = extract_lifetime_name(s) {
359                    TypeLifetime::Ref(name)
360                } else {
361                    TypeLifetime::Owned
362                }
363            } else {
364                TypeLifetime::Owned
365            }
366        }
367    }
368}
369
370fn extract_lifetime_name(s: &str) -> Option<String> {
371    let re = Regex::new(r"'([a-z][a-z0-9]*)").ok()?;
372    re.captures(s)
373        .and_then(|cap| cap.get(1))
374        .map(|m| m.as_str().to_string())
375}
376
377fn extract_base_type(type_name: &str) -> &str {
378    // Extract base type from template instantiation
379    // e.g., "std::vector<int>" -> "std::vector"
380    if let Some(angle_pos) = type_name.find('<') {
381        &type_name[..angle_pos]
382    } else {
383        type_name
384    }
385}
386
387#[cfg(test)]
388mod tests {
389    use super::*;
390    
391    #[test]
392    fn test_parse_type_lifetime() {
393        let comment = r#"
394        @type_lifetime: std::vector<T> {
395            at(size_t) -> &'self mut
396            at(size_t) const -> &'self
397            data() -> *mut
398            iterator: &'self mut
399        }
400        "#;
401        
402        let spec = parse_type_lifetime_annotation(comment).unwrap();
403        assert_eq!(spec.type_name, "std::vector<T>");
404        assert_eq!(spec.methods["at"].len(), 2);
405        assert_eq!(spec.typedefs["iterator"], TypeLifetime::SelfMutRef);
406    }
407    
408    #[test]
409    fn test_registry() {
410        let registry = TypeLifetimeRegistry::new();
411        let vector_spec = registry.get_type_spec("std::vector<int>").unwrap();
412        assert_eq!(vector_spec.type_name, "std::vector");
413    }
414}