Skip to main content

mago_syntax/ast/ast/
partial_application.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::ast::argument::PartialArgumentList;
8use crate::ast::ast::class_like::member::ClassLikeMemberSelector;
9use crate::ast::ast::expression::Expression;
10
11#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
12#[serde(tag = "type", content = "value")]
13pub enum PartialApplication<'arena> {
14    Function(FunctionPartialApplication<'arena>),
15    Method(MethodPartialApplication<'arena>),
16    StaticMethod(StaticMethodPartialApplication<'arena>),
17}
18
19#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
20pub struct FunctionPartialApplication<'arena> {
21    pub function: &'arena Expression<'arena>,
22    pub argument_list: PartialArgumentList<'arena>,
23}
24
25#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
26pub struct MethodPartialApplication<'arena> {
27    pub object: &'arena Expression<'arena>,
28    pub arrow: Span,
29    pub method: ClassLikeMemberSelector<'arena>,
30    pub argument_list: PartialArgumentList<'arena>,
31}
32
33#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
34pub struct StaticMethodPartialApplication<'arena> {
35    pub class: &'arena Expression<'arena>,
36    pub double_colon: Span,
37    pub method: ClassLikeMemberSelector<'arena>,
38    pub argument_list: PartialArgumentList<'arena>,
39}
40
41impl<'arena> PartialApplication<'arena> {
42    #[inline]
43    #[must_use]
44    pub fn is_first_class_callable(&self) -> bool {
45        self.get_argument_list().is_first_class_callable()
46    }
47
48    #[inline]
49    #[must_use]
50    pub fn get_argument_list(&self) -> &PartialArgumentList<'arena> {
51        match self {
52            PartialApplication::Function(f) => &f.argument_list,
53            PartialApplication::Method(m) => &m.argument_list,
54            PartialApplication::StaticMethod(s) => &s.argument_list,
55        }
56    }
57}
58
59impl HasSpan for PartialApplication<'_> {
60    fn span(&self) -> Span {
61        match self {
62            PartialApplication::Function(f) => f.span(),
63            PartialApplication::Method(m) => m.span(),
64            PartialApplication::StaticMethod(s) => s.span(),
65        }
66    }
67}
68
69impl HasSpan for FunctionPartialApplication<'_> {
70    fn span(&self) -> Span {
71        self.function.span().join(self.argument_list.span())
72    }
73}
74
75impl HasSpan for MethodPartialApplication<'_> {
76    fn span(&self) -> Span {
77        self.object.span().join(self.argument_list.span())
78    }
79}
80
81impl HasSpan for StaticMethodPartialApplication<'_> {
82    fn span(&self) -> Span {
83        self.class.span().join(self.argument_list.span())
84    }
85}