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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::{
statement::*,
BoolAnd,
Expression,
Monoid,
MonoidalReducerExpression,
MonoidalReducerStatement,
Node,
Span,
};
pub struct ReturnPathReducer {
pub errors: Vec<(Span, String)>,
}
impl ReturnPathReducer {
fn record_error(&mut self, span: Option<&Span>, error: String) {
self.errors.push((span.cloned().unwrap_or_default(), error));
}
pub fn new() -> ReturnPathReducer {
ReturnPathReducer { errors: vec![] }
}
}
impl Default for ReturnPathReducer {
fn default() -> Self {
Self::new()
}
}
#[allow(unused_variables)]
impl<'a> MonoidalReducerExpression<'a, BoolAnd> for ReturnPathReducer {
fn reduce_expression(&mut self, input: &'a Expression<'a>, value: BoolAnd) -> BoolAnd {
BoolAnd(false)
}
}
#[allow(unused_variables)]
impl<'a> MonoidalReducerStatement<'a, BoolAnd> for ReturnPathReducer {
fn reduce_assign_access(&mut self, input: &AssignAccess, left: Option<BoolAnd>, right: Option<BoolAnd>) -> BoolAnd {
BoolAnd(false)
}
fn reduce_assign(&mut self, input: &AssignStatement, accesses: Vec<BoolAnd>, value: BoolAnd) -> BoolAnd {
BoolAnd(false)
}
fn reduce_block(&mut self, input: &BlockStatement, statements: Vec<BoolAnd>) -> BoolAnd {
if statements.is_empty() {
BoolAnd(false)
} else if let Some(index) = statements[..statements.len() - 1].iter().map(|x| x.0).position(|x| x) {
self.record_error(
input.statements[index].get().span(),
"dead code due to unconditional early return".to_string(),
);
BoolAnd(true)
} else {
BoolAnd(statements[statements.len() - 1].0)
}
}
fn reduce_conditional_statement(
&mut self,
input: &ConditionalStatement,
condition: BoolAnd,
if_true: BoolAnd,
if_false: Option<BoolAnd>,
) -> BoolAnd {
if if_false.as_ref().map(|x| x.0).unwrap_or(false) != if_true.0 {
self.record_error(
input.span(),
"cannot have asymmetrical return in if statement".to_string(),
);
}
if_true.append(if_false.unwrap_or(BoolAnd(false)))
}
fn reduce_formatted_string(&mut self, input: &FormatString, parameters: Vec<BoolAnd>) -> BoolAnd {
BoolAnd(false)
}
fn reduce_console(&mut self, input: &ConsoleStatement, argument: BoolAnd) -> BoolAnd {
BoolAnd(false)
}
fn reduce_definition(&mut self, input: &DefinitionStatement, value: BoolAnd) -> BoolAnd {
BoolAnd(false)
}
fn reduce_expression_statement(&mut self, input: &ExpressionStatement, expression: BoolAnd) -> BoolAnd {
BoolAnd(false)
}
fn reduce_iteration(
&mut self,
input: &IterationStatement,
start: BoolAnd,
stop: BoolAnd,
body: BoolAnd,
) -> BoolAnd {
BoolAnd(false)
}
fn reduce_return(&mut self, input: &ReturnStatement, value: BoolAnd) -> BoolAnd {
BoolAnd(true)
}
}