arithmetic_parser/ast/
lvalue.rs1use core::fmt;
4
5use crate::{alloc::Vec, spans::Spanned};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[non_exhaustive]
10pub enum LvalueLen {
11 Exact(usize),
13 AtLeast(usize),
15}
16
17impl LvalueLen {
18 pub fn matches(self, value: usize) -> bool {
20 match self {
21 Self::Exact(len) => value == len,
22 Self::AtLeast(len) => value >= len,
23 }
24 }
25}
26
27impl fmt::Display for LvalueLen {
28 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
29 match self {
30 Self::Exact(len) => write!(formatter, "{len}"),
31 Self::AtLeast(len) => write!(formatter, "at least {len}"),
32 }
33 }
34}
35
36impl From<usize> for LvalueLen {
37 fn from(value: usize) -> Self {
38 Self::Exact(value)
39 }
40}
41
42#[derive(Debug, Clone, PartialEq)]
44pub struct Destructure<'a, T> {
45 pub start: Vec<SpannedLvalue<'a, T>>,
47 pub middle: Option<Spanned<'a, DestructureRest<'a, T>>>,
49 pub end: Vec<SpannedLvalue<'a, T>>,
51}
52
53impl<T> Destructure<'_, T> {
54 pub fn len(&self) -> LvalueLen {
56 if self.middle.is_some() {
57 LvalueLen::AtLeast(self.start.len() + self.end.len())
58 } else {
59 LvalueLen::Exact(self.start.len())
60 }
61 }
62
63 pub fn is_empty(&self) -> bool {
65 self.start.is_empty()
66 }
67}
68
69#[derive(Debug, Clone, PartialEq)]
71pub enum DestructureRest<'a, T> {
72 Unnamed,
74 Named {
76 variable: Spanned<'a>,
78 ty: Option<Spanned<'a, T>>,
80 },
81}
82
83impl<'a, T> DestructureRest<'a, T> {
84 pub fn to_lvalue(&self) -> Option<SpannedLvalue<'a, T>> {
87 match self {
88 Self::Named { variable, .. } => {
89 Some(variable.copy_with_extra(Lvalue::Variable { ty: None }))
90 }
91 Self::Unnamed => None,
92 }
93 }
94}
95
96#[derive(Debug, Clone, PartialEq)]
98#[non_exhaustive]
99pub struct ObjectDestructure<'a, T> {
100 pub fields: Vec<ObjectDestructureField<'a, T>>,
102}
103
104#[derive(Debug, Clone, PartialEq)]
111pub struct ObjectDestructureField<'a, T> {
112 pub field_name: Spanned<'a>,
114 pub binding: Option<SpannedLvalue<'a, T>>,
116}
117
118#[derive(Debug, Clone, PartialEq)]
120#[non_exhaustive]
121pub enum Lvalue<'a, T> {
122 Variable {
124 ty: Option<Spanned<'a, T>>,
126 },
127 Tuple(Destructure<'a, T>),
129 Object(ObjectDestructure<'a, T>),
131}
132
133impl<T> Lvalue<'_, T> {
134 pub fn ty(&self) -> LvalueType {
136 match self {
137 Self::Variable { .. } => LvalueType::Variable,
138 Self::Tuple(_) => LvalueType::Tuple,
139 Self::Object(_) => LvalueType::Object,
140 }
141 }
142}
143
144pub type SpannedLvalue<'a, T> = Spanned<'a, Lvalue<'a, T>>;
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
149#[non_exhaustive]
150pub enum LvalueType {
151 Variable,
153 Tuple,
155 Object,
157}
158
159impl fmt::Display for LvalueType {
160 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
161 formatter.write_str(match self {
162 Self::Variable => "simple variable",
163 Self::Tuple => "tuple destructuring",
164 Self::Object => "object destructuring",
165 })
166 }
167}