1
1
use super :: PragmaSection ;
2
2
use crate :: {
3
- ast:: { AstFile , Function , Parameters , StmtKind , TypeKind } ,
3
+ ast:: { AstFile , Expr , ExprKind , Function , Parameters , Stmt , StmtKind , TypeKind } ,
4
+ diagnostics:: ErrorDiagnostic ,
4
5
inflow:: Inflow ,
5
6
parser:: { self , error:: ParseError , Input } ,
6
7
show:: { into_show, Show } ,
8
+ source_files:: Source ,
7
9
token:: { Token , TokenKind } ,
8
10
} ;
9
11
10
12
impl PragmaSection {
11
13
pub fn parse < ' a , I : Inflow < Token > > (
14
+ allow_experimental_pragma_features : bool ,
12
15
mut input : Input < ' a , I > ,
13
16
) -> Result < ( PragmaSection , Input < ' a , I > ) , Box < dyn Show > > {
14
17
// pragma ...
@@ -33,11 +36,18 @@ impl PragmaSection {
33
36
// "Whole-file" mode
34
37
35
38
// Parse top-level contructs until we hit a '}'
36
- while !parser. input . peek_is ( TokenKind :: CloseCurly ) {
37
- parser
38
- . parse_top_level ( & mut ast_file, vec ! [ ] )
39
- . map_err ( into_show) ?;
40
- parser. input . ignore_newlines ( ) ;
39
+ if allow_experimental_pragma_features {
40
+ while !parser. input . peek_is_or_eof ( TokenKind :: CloseCurly ) {
41
+ parser
42
+ . parse_top_level ( & mut ast_file, vec ! [ ] )
43
+ . map_err ( into_show) ?;
44
+ parser. input . ignore_newlines ( ) ;
45
+ }
46
+ } else {
47
+ return Err ( Box :: new ( ErrorDiagnostic :: new (
48
+ "Whole-file pragma directives are an experimental feature and may be removed" ,
49
+ pragma_source,
50
+ ) ) ) ;
41
51
}
42
52
43
53
// Eat the final '}'
@@ -62,6 +72,12 @@ impl PragmaSection {
62
72
vec ! [ StmtKind :: Expr ( expr) . at( expr_source) ]
63
73
} ;
64
74
75
+ if !allow_experimental_pragma_features {
76
+ for stmt in stmts. iter ( ) {
77
+ restrict_allowed_stmt ( stmt) ?;
78
+ }
79
+ }
80
+
65
81
ast_file. functions . push ( Function {
66
82
name : "main" . into ( ) ,
67
83
parameters : Parameters {
@@ -92,3 +108,44 @@ impl PragmaSection {
92
108
) )
93
109
}
94
110
}
111
+
112
+ fn restrict_allowed_stmt ( stmt : & Stmt ) -> Result < ( ) , Box < dyn Show > > {
113
+ match & stmt. kind {
114
+ StmtKind :: Expr ( inner) => restrict_allowed_expr ( inner) ?,
115
+ _ => return Err ( found_forbidden_stmt ( stmt. source ) ) ,
116
+ }
117
+
118
+ Ok ( ( ) )
119
+ }
120
+
121
+ fn restrict_allowed_expr ( expr : & Expr ) -> Result < ( ) , Box < dyn Show > > {
122
+ match & expr. kind {
123
+ ExprKind :: NullTerminatedString ( _) => ( ) ,
124
+ ExprKind :: Call ( call) => {
125
+ if call. expected_to_return . is_some ( ) {
126
+ return Err ( found_forbidden_expr ( expr. source ) ) ;
127
+ }
128
+
129
+ for argument in call. arguments . iter ( ) {
130
+ restrict_allowed_expr ( argument) ?;
131
+ }
132
+ }
133
+ _ => return Err ( found_forbidden_expr ( expr. source ) ) ,
134
+ }
135
+
136
+ Ok ( ( ) )
137
+ }
138
+
139
+ fn found_forbidden_stmt ( source : Source ) -> Box < dyn Show > {
140
+ Box :: new ( ErrorDiagnostic :: new (
141
+ "Support for this statement inside pragma directives is an experimental feature that may be removed" ,
142
+ source,
143
+ ) )
144
+ }
145
+
146
+ fn found_forbidden_expr ( source : Source ) -> Box < dyn Show > {
147
+ Box :: new ( ErrorDiagnostic :: new (
148
+ "Support for this expression inside pragma directives is an experimental feature that may be removed" ,
149
+ source,
150
+ ) )
151
+ }
0 commit comments