+68
-49
src/checker.rs
+68
-49
src/checker.rs
···
105
105
106
106
/// Checker context
107
107
struct CheckContext<'a> {
108
-
globals: &'a dyn Variables<ExpressionResult>,
108
+
globals: &'a dyn Variables<VariableResult>,
109
109
file_query: &'a Query,
110
110
stanza_index: usize,
111
111
stanza_query: &'a Query,
112
-
locals: &'a mut dyn MutVariables<ExpressionResult>,
112
+
locals: &'a mut dyn MutVariables<VariableResult>,
113
+
}
114
+
115
+
#[derive(Clone, Debug)]
116
+
struct VariableResult {
117
+
is_local: bool,
118
+
quantifier: CaptureQuantifier,
113
119
}
114
120
115
121
//-----------------------------------------------------------------------------
···
122
128
globals
123
129
.add(
124
130
global.name.clone(),
125
-
ExpressionResult {
131
+
VariableResult {
126
132
quantifier: global.quantifier,
127
133
is_local: true,
128
-
used_captures: HashSet::new(),
129
134
},
130
135
false,
131
136
)
···
150
155
impl ast::Stanza {
151
156
fn check(
152
157
&mut self,
153
-
globals: &dyn Variables<ExpressionResult>,
158
+
globals: &dyn Variables<VariableResult>,
154
159
file_query: &Query,
155
160
stanza_index: usize,
156
161
) -> Result<(), CheckError> {
···
232
237
let mut used_captures = HashSet::new();
233
238
let value = self.value.check(ctx)?;
234
239
used_captures.extend(value.used_captures.iter().cloned());
235
-
let var_result = self.variable.check_add(ctx, value, false)?;
240
+
let var_result = self.variable.check_add(ctx, value.into(), false)?;
236
241
used_captures.extend(var_result.used_captures);
237
242
Ok(StatementResult { used_captures })
238
243
}
···
243
248
let mut used_captures = HashSet::new();
244
249
let value = self.value.check(ctx)?;
245
250
used_captures.extend(value.used_captures.iter().cloned());
246
-
let var_result = self.variable.check_add(ctx, value, true)?;
251
+
let var_result = self.variable.check_add(ctx, value.into(), true)?;
247
252
used_captures.extend(var_result.used_captures);
248
253
Ok(StatementResult { used_captures })
249
254
}
···
254
259
let mut used_captures = HashSet::new();
255
260
let value = self.value.check(ctx)?;
256
261
used_captures.extend(value.used_captures.iter().cloned());
257
-
let var_result = self.variable.check_set(ctx, value)?;
262
+
let var_result = self.variable.check_set(ctx, value.into())?;
258
263
used_captures.extend(var_result.used_captures);
259
264
Ok(StatementResult { used_captures })
260
265
}
···
264
269
fn check(&mut self, ctx: &mut CheckContext) -> Result<StatementResult, CheckError> {
265
270
let node_result = self.node.check_add(
266
271
ctx,
267
-
ExpressionResult {
272
+
VariableResult {
268
273
is_local: true,
269
274
quantifier: One,
270
-
used_captures: HashSet::new(),
271
275
},
272
276
false,
273
277
)?;
···
445
449
};
446
450
let var_result = self
447
451
.variable
448
-
.check_add(&mut loop_ctx, value_result, false)?;
452
+
.check_add(&mut loop_ctx, value_result.into(), false)?;
449
453
used_captures.extend(var_result.used_captures);
450
454
451
455
for statement in &mut self.statements {
···
577
581
};
578
582
let var_result = self
579
583
.variable
580
-
.check_add(&mut loop_ctx, value_result, false)?;
584
+
.check_add(&mut loop_ctx, value_result.into(), false)?;
581
585
used_captures.extend(var_result.used_captures);
582
586
583
587
let element_result = self.element.check(&mut loop_ctx)?;
···
614
618
};
615
619
let var_result = self
616
620
.variable
617
-
.check_add(&mut loop_ctx, value_result, false)?;
621
+
.check_add(&mut loop_ctx, value_result.into(), false)?;
618
622
used_captures.extend(var_result.used_captures);
619
623
620
624
let element_result = self.element.check(&mut loop_ctx)?;
···
680
684
//-----------------------------------------------------------------------------
681
685
// Variables
682
686
683
-
#[derive(Clone, Debug)]
684
-
struct VariableResult {
685
-
used_captures: HashSet<Identifier>,
686
-
}
687
-
688
687
impl ast::Variable {
689
688
fn check_add(
690
689
&mut self,
691
690
ctx: &mut CheckContext,
692
-
value: ExpressionResult,
691
+
value: VariableResult,
693
692
mutable: bool,
694
-
) -> Result<VariableResult, CheckError> {
693
+
) -> Result<StatementResult, CheckError> {
695
694
match self {
696
695
Self::Unscoped(v) => v.check_add(ctx, value, mutable),
697
696
Self::Scoped(v) => v.check_add(ctx, value, mutable),
···
701
700
fn check_set(
702
701
&mut self,
703
702
ctx: &mut CheckContext,
704
-
value: ExpressionResult,
705
-
) -> Result<VariableResult, CheckError> {
703
+
value: VariableResult,
704
+
) -> Result<StatementResult, CheckError> {
706
705
match self {
707
706
Self::Unscoped(v) => v.check_set(ctx, value),
708
707
Self::Scoped(v) => v.check_set(ctx, value),
···
721
720
fn check_add(
722
721
&mut self,
723
722
ctx: &mut CheckContext,
724
-
value: ExpressionResult,
723
+
value: VariableResult,
725
724
mutable: bool,
726
-
) -> Result<VariableResult, CheckError> {
725
+
) -> Result<StatementResult, CheckError> {
727
726
if ctx.globals.get(&self.name).is_some() {
728
727
return Err(CheckError::CannotHideGlobalVariable(
729
728
self.name.as_str().to_string(),
···
738
737
if mutable {
739
738
value.is_local = false;
740
739
}
741
-
let used_captures = value.used_captures.clone();
742
-
value.used_captures.clear(); // prevent used captures from escaping
743
-
// we may want to separate quantifier/is_local from
744
-
// the used_captures and only store the former in the
745
-
// future for a cleaner solution
746
740
ctx.locals
747
741
.add(self.name.clone(), value, mutable)
748
742
.map_err(|e| CheckError::Variable(e, format!("{}", self.name), self.location))?;
749
-
Ok(VariableResult { used_captures })
743
+
Ok(StatementResult {
744
+
used_captures: HashSet::default(),
745
+
})
750
746
}
751
747
752
748
fn check_set(
753
749
&mut self,
754
750
ctx: &mut CheckContext,
755
-
value: ExpressionResult,
756
-
) -> Result<VariableResult, CheckError> {
751
+
value: VariableResult,
752
+
) -> Result<StatementResult, CheckError> {
757
753
if ctx.globals.get(&self.name).is_some() {
758
754
return Err(CheckError::CannotSetGlobalVariable(
759
755
self.name.as_str().to_string(),
···
766
762
// Since we process all statement in order, we don't have info on later
767
763
// assignments, and can assume non-local to be sound.
768
764
value.is_local = false;
769
-
let used_captures = value.used_captures.clone();
770
-
value.used_captures.clear(); // prevent used captures from escaping
771
-
// we may want to separate quantifier/is_local from
772
-
// the used_captures and only store the former in the
773
-
// future for a cleaner solution
774
765
ctx.locals
775
766
.set(self.name.clone(), value)
776
767
.map_err(|e| CheckError::Variable(e, format!("{}", self.name), self.location))?;
777
-
Ok(VariableResult { used_captures })
768
+
Ok(StatementResult {
769
+
used_captures: HashSet::default(),
770
+
})
778
771
}
779
772
780
773
fn check_get(&mut self, ctx: &mut CheckContext) -> Result<ExpressionResult, CheckError> {
···
783
776
} else {
784
777
ctx.locals.get(&self.name)
785
778
}
786
-
.cloned()
779
+
.map(|value| value.into())
787
780
.ok_or_else(|| CheckError::UndefinedVariable(self.name.as_str().to_string(), self.location))
788
781
}
789
782
}
···
792
785
fn check_add(
793
786
&mut self,
794
787
ctx: &mut CheckContext,
795
-
_value: ExpressionResult,
788
+
_value: VariableResult,
796
789
_mutable: bool,
797
-
) -> Result<VariableResult, CheckError> {
790
+
) -> Result<StatementResult, CheckError> {
798
791
let scope_result = self.scope.check(ctx)?;
799
-
Ok(VariableResult {
800
-
used_captures: scope_result.used_captures,
801
-
})
792
+
Ok(scope_result.into())
802
793
}
803
794
804
795
fn check_set(
805
796
&mut self,
806
797
ctx: &mut CheckContext,
807
-
_value: ExpressionResult,
808
-
) -> Result<VariableResult, CheckError> {
798
+
_value: VariableResult,
799
+
) -> Result<StatementResult, CheckError> {
809
800
let scope_result = self.scope.check(ctx)?;
810
-
Ok(VariableResult {
811
-
used_captures: scope_result.used_captures,
812
-
})
801
+
Ok(scope_result.into())
813
802
}
814
803
815
804
fn check_get(&mut self, ctx: &mut CheckContext) -> Result<ExpressionResult, CheckError> {
···
838
827
})
839
828
}
840
829
}
830
+
831
+
//-----------------------------------------------------------------------------
832
+
// Result Conversions
833
+
834
+
impl Into<StatementResult> for ExpressionResult {
835
+
fn into(self) -> StatementResult {
836
+
StatementResult {
837
+
used_captures: self.used_captures,
838
+
}
839
+
}
840
+
}
841
+
842
+
impl Into<ExpressionResult> for &VariableResult {
843
+
fn into(self) -> ExpressionResult {
844
+
ExpressionResult {
845
+
is_local: self.is_local,
846
+
quantifier: self.quantifier,
847
+
used_captures: HashSet::default(),
848
+
}
849
+
}
850
+
}
851
+
852
+
impl Into<VariableResult> for ExpressionResult {
853
+
fn into(self) -> VariableResult {
854
+
VariableResult {
855
+
is_local: self.is_local,
856
+
quantifier: self.quantifier,
857
+
}
858
+
}
859
+
}