1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
use super::{ops, EvalResult, Value};
use crate::diag::{At, TypError};
use crate::syntax::Span;
/// A control flow event that occurred during evaluation.
#[derive(Clone, Debug, PartialEq)]
pub enum Control {
/// Stop iteration in a loop.
Break(Value, Span),
/// Skip the remainder of the current iteration in a loop.
Continue(Value, Span),
/// Stop execution of a function early, returning a value. The bool
/// indicates whether this was an explicit return with value.
Return(Value, bool, Span),
/// Stop the execution because an error occurred.
Err(TypError),
}
impl From<TypError> for Control {
fn from(error: TypError) -> Self {
Self::Err(error)
}
}
impl From<Control> for TypError {
fn from(control: Control) -> Self {
match control {
Control::Break(_, span) => {
error!(span, "cannot break outside of loop")
}
Control::Continue(_, span) => {
error!(span, "cannot continue outside of loop")
}
Control::Return(_, _, span) => {
error!(span, "cannot return outside of function")
}
Control::Err(e) => e,
}
}
}
/// Join a value with an evaluated result.
pub(super) fn join_result(
prev: Value,
result: EvalResult<Value>,
result_span: Span,
) -> EvalResult<Value> {
match result {
Ok(value) => Ok(ops::join(prev, value).at(result_span)?),
Err(Control::Break(value, span)) => Err(Control::Break(
ops::join(prev, value).at(result_span)?,
span,
)),
Err(Control::Continue(value, span)) => Err(Control::Continue(
ops::join(prev, value).at(result_span)?,
span,
)),
Err(Control::Return(value, false, span)) => Err(Control::Return(
ops::join(prev, value).at(result_span)?,
false,
span,
)),
other => other,
}
}
|