nickel_lang_core/bytecode/ast/pattern/
bindings.rs1use crate::{
4 bytecode::ast::{pattern::*, record::FieldMetadata},
5 identifier::LocIdent,
6};
7
8pub struct PatBinding<'ast> {
11 pub path: Vec<LocIdent>,
12 pub id: LocIdent,
13 pub metadata: FieldMetadata<'ast>,
14}
15
16pub trait Bindings<'ast> {
17 fn bindings(&self) -> Vec<PatBinding<'ast>>;
31}
32
33trait InjectBindings<'ast> {
34 fn inject_bindings(
49 &self,
50 bindings: &mut Vec<PatBinding<'ast>>,
51 path: Vec<LocIdent>,
52 parent_extra: Option<&FieldMetadata<'ast>>,
53 );
54}
55
56impl<'ast> Bindings<'ast> for Pattern<'ast> {
57 fn bindings(&self) -> Vec<PatBinding<'ast>> {
58 let mut bindings = Vec::new();
59 self.inject_bindings(&mut bindings, Vec::new(), None);
60 bindings
61 }
62}
63
64impl<'ast> InjectBindings<'ast> for Pattern<'ast> {
65 fn inject_bindings(
66 &self,
67 bindings: &mut Vec<PatBinding<'ast>>,
68 path: Vec<LocIdent>,
69 parent_deco: Option<&FieldMetadata<'ast>>,
70 ) {
71 if let Some(alias) = self.alias {
72 bindings.push(PatBinding {
73 path: path.clone(),
74 id: alias,
75 metadata: parent_deco.cloned().unwrap_or_default(),
76 });
77 }
78
79 self.data.inject_bindings(bindings, path, parent_deco);
80 }
81}
82
83impl<'ast> InjectBindings<'ast> for PatternData<'ast> {
84 fn inject_bindings(
85 &self,
86 bindings: &mut Vec<PatBinding<'ast>>,
87 path: Vec<LocIdent>,
88 parent_deco: Option<&FieldMetadata<'ast>>,
89 ) {
90 match self {
91 PatternData::Any(id) => bindings.push(PatBinding {
92 path,
93 id: *id,
94 metadata: parent_deco.cloned().unwrap_or_default(),
95 }),
96 PatternData::Record(record_pat) => {
97 record_pat.inject_bindings(bindings, path, parent_deco)
98 }
99 PatternData::Array(array_pat) => array_pat.inject_bindings(bindings, path, parent_deco),
100 PatternData::Enum(evariant_pat) => {
101 evariant_pat.inject_bindings(bindings, path, parent_deco)
102 }
103 PatternData::Or(or_pat) => or_pat.inject_bindings(bindings, path, parent_deco),
104 PatternData::Wildcard | PatternData::Constant(_) => (),
106 }
107 }
108}
109
110impl<'ast> InjectBindings<'ast> for RecordPattern<'ast> {
111 fn inject_bindings(
112 &self,
113 bindings: &mut Vec<PatBinding<'ast>>,
114 path: Vec<LocIdent>,
115 parent_extra: Option<&FieldMetadata<'ast>>,
116 ) {
117 for field_pat in self.patterns.iter() {
118 field_pat.inject_bindings(bindings, path.clone(), None);
121 }
122
123 if let TailPattern::Capture(rest) = self.tail {
124 bindings.push(PatBinding {
129 path,
130 id: rest,
131 metadata: parent_extra.cloned().unwrap_or_default(),
132 });
133 }
134 }
135}
136
137impl<'ast> InjectBindings<'ast> for ArrayPattern<'ast> {
138 fn inject_bindings(
139 &self,
140 bindings: &mut Vec<PatBinding<'ast>>,
141 path: Vec<LocIdent>,
142 _parent_extra: Option<&FieldMetadata<'ast>>,
143 ) {
144 for subpat in self.patterns.iter() {
145 subpat.inject_bindings(bindings, path.clone(), None);
148 }
149
150 if let TailPattern::Capture(rest) = self.tail {
151 bindings.push(PatBinding {
152 path,
153 id: rest,
154 metadata: Default::default(),
155 });
156 }
157 }
158}
159
160impl<'ast> InjectBindings<'ast> for FieldPattern<'ast> {
161 fn inject_bindings(
162 &self,
163 bindings: &mut Vec<PatBinding<'ast>>,
164 mut path: Vec<LocIdent>,
165 _parent_extra: Option<&FieldMetadata<'ast>>,
166 ) {
167 path.push(self.matched_id);
168 self.pattern.inject_bindings(
169 bindings,
170 path,
171 Some(&FieldMetadata::from(self.annotation.clone())),
172 );
173 }
174}
175
176impl<'ast> InjectBindings<'ast> for EnumPattern<'ast> {
177 fn inject_bindings(
178 &self,
179 bindings: &mut Vec<PatBinding<'ast>>,
180 path: Vec<LocIdent>,
181 _parent_extra: Option<&FieldMetadata<'ast>>,
182 ) {
183 if let Some(ref arg_pat) = self.pattern {
186 arg_pat.inject_bindings(bindings, path, None);
187 }
188 }
189}
190
191impl<'ast> InjectBindings<'ast> for OrPattern<'ast> {
192 fn inject_bindings(
193 &self,
194 bindings: &mut Vec<PatBinding<'ast>>,
195 path: Vec<LocIdent>,
196 parent_extra: Option<&FieldMetadata<'ast>>,
197 ) {
198 for subpat in self.patterns.iter() {
199 subpat.inject_bindings(bindings, path.clone(), parent_extra);
200 }
201 }
202}