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