src5_rs/core/parser/
cairo_function.rs

1use anyhow::{Ok, Result};
2// Module for handling Cairo functions
3use cairo_lang_compiler::db::RootDatabase;
4use cairo_lang_syntax::node::kind::SyntaxKind;
5use cairo_lang_syntax::node::SyntaxNode;
6
7use super::cairo_enum::CairoEnum;
8use super::cairo_struct::CairoStruct;
9use super::utils::find_children;
10use crate::core::src5_type::SRC5Typed;
11
12#[derive(Debug)]
13pub struct CairoNonGenericFunction {
14    pub name: String,
15    pub inputs_types: Vec<SyntaxNode>,
16    pub return_type: Option<SyntaxNode>,
17}
18
19impl CairoNonGenericFunction {
20    pub fn new(
21        name: String,
22        inputs_types: Vec<SyntaxNode>,
23        return_type: Option<SyntaxNode>,
24    ) -> CairoNonGenericFunction {
25        CairoNonGenericFunction {
26            name,
27            inputs_types,
28            return_type,
29        }
30    }
31
32    /// Get the Extended Function Selector signature
33    pub fn get_efs_signature(
34        &self,
35        db: &RootDatabase,
36        cairo_structs: &[CairoStruct],
37        cairo_enums: &[CairoEnum],
38    ) -> Result<String> {
39        let mut efs_signature = format!("{}(", self.name);
40        // Resolve each member type
41        for input in self.inputs_types.iter() {
42            efs_signature.push_str(&input.get_src5_type(db, cairo_structs, cairo_enums)?);
43            efs_signature.push(',');
44        }
45        if efs_signature.ends_with(',') {
46            efs_signature.pop(); // Remove last comma
47        }
48        efs_signature.push(')');
49
50        // Resolve return type
51        if let Some(return_type) = &self.return_type {
52            efs_signature.push_str("->");
53            efs_signature.push_str(&return_type.get_src5_type(db, cairo_structs, cairo_enums)?);
54        }
55        Ok(efs_signature)
56    }
57}
58
59pub fn get_functions_from_trait_body(
60    db: &RootDatabase,
61    trait_body: &SyntaxNode,
62) -> Vec<CairoNonGenericFunction> {
63    let mut functions = Vec::new();
64
65    let trait_items = find_children(db, trait_body, SyntaxKind::TraitItemList).unwrap();
66    for node in trait_items.children(db) {
67        if node.kind(db) == SyntaxKind::TraitItemFunction {
68            // Look up the Function name
69            let declaration_node =
70                find_children(db, &node, SyntaxKind::FunctionDeclaration).unwrap();
71            let id_node =
72                find_children(db, &declaration_node, SyntaxKind::TerminalIdentifier).unwrap();
73            let function_name = id_node.get_text_without_trivia(db);
74
75            // Look up the Function inputs types
76            let signature_node =
77                find_children(db, &declaration_node, SyntaxKind::FunctionSignature).unwrap();
78            let function_inputs =
79                find_children(db, &signature_node, SyntaxKind::ParamList).unwrap();
80            let mut inputs_types = Vec::new();
81            for node in function_inputs.descendants(db) {
82                if node.kind(db) == SyntaxKind::TypeClause {
83                    inputs_types.push(node);
84                }
85            }
86
87            // Look up the Function return type
88            let return_type = find_children(db, &signature_node, SyntaxKind::ReturnTypeClause);
89
90            functions.push(CairoNonGenericFunction {
91                name: function_name,
92                inputs_types,
93                return_type,
94            });
95        }
96    }
97    functions
98}