@@ -5,7 +5,8 @@ use crate::diagnostic::{Diagnostic, code};
55use crate :: hir:: { DuplicateSymbolKind , Hir , HirTypeKind } ;
66use crate :: lexer:: { Token , lex} ;
77use crate :: syntax:: ast:: {
8- Callee , DataEffect , EffectDecl , Expr , GenericBound , GenericParam , Item , Stmt , TypeKind , TypeRef ,
8+ Block , Callee , DataEffect , EffectDecl , Expr , GenericBound , GenericParam , Item , Stmt , TypeKind ,
9+ TypeRef ,
910} ;
1011use crate :: syntax:: parse_source;
1112
@@ -90,6 +91,7 @@ impl Analyzer<'_> {
9091 fn run ( & mut self ) {
9192 self . check_single_feature_declaration ( ) ;
9293 self . check_removed_profile_declarations ( ) ;
94+ self . check_unsupported_syntax ( ) ;
9395 self . check_duplicate_declarations ( ) ;
9496 self . check_signature_explicitness ( ) ;
9597 self . check_generic_constraints ( ) ;
@@ -142,6 +144,112 @@ impl Analyzer<'_> {
142144 }
143145 }
144146
147+ fn check_unsupported_syntax ( & mut self ) {
148+ let bodies = self
149+ . syntax_program
150+ . items
151+ . iter ( )
152+ . filter_map ( |item| match item {
153+ Item :: Function ( function) => Some ( function. body . clone ( ) ) ,
154+ Item :: Type ( _) => None ,
155+ } )
156+ . collect :: < Vec < _ > > ( ) ;
157+ for body in & bodies {
158+ self . check_unsupported_syntax_block ( body) ;
159+ }
160+ }
161+
162+ fn check_unsupported_syntax_block ( & mut self , block : & Block ) {
163+ for statement in & block. statements {
164+ self . check_unsupported_syntax_stmt ( statement) ;
165+ }
166+ }
167+
168+ fn check_unsupported_syntax_stmt ( & mut self , statement : & Stmt ) {
169+ match statement {
170+ Stmt :: Let ( stmt) => {
171+ if let Some ( value) = & stmt. value {
172+ self . check_unsupported_syntax_expr ( value) ;
173+ }
174+ }
175+ Stmt :: Return ( stmt) => {
176+ if let Some ( value) = & stmt. value {
177+ self . check_unsupported_syntax_expr ( value) ;
178+ }
179+ }
180+ Stmt :: With ( stmt) => {
181+ self . check_unsupported_syntax_expr ( & stmt. resource ) ;
182+ self . check_unsupported_syntax_block ( & stmt. body ) ;
183+ }
184+ Stmt :: If ( stmt) => {
185+ self . check_unsupported_syntax_expr ( & stmt. condition ) ;
186+ self . check_unsupported_syntax_block ( & stmt. then_body ) ;
187+ if let Some ( else_body) = & stmt. else_body {
188+ self . check_unsupported_syntax_block ( else_body) ;
189+ }
190+ }
191+ Stmt :: Loop ( stmt) => {
192+ if let Some ( condition) = & stmt. condition {
193+ self . check_unsupported_syntax_expr ( condition) ;
194+ }
195+ self . check_unsupported_syntax_block ( & stmt. body ) ;
196+ }
197+ Stmt :: Expr ( expr) => self . check_unsupported_syntax_expr ( expr) ,
198+ Stmt :: Break ( _) | Stmt :: Continue ( _) => { }
199+ Stmt :: Unknown ( span) => self . unsupported_syntax (
200+ span. clone ( ) ,
201+ "unsupported statement" ,
202+ "This statement is outside the current RSScript parser surface." ,
203+ ) ,
204+ }
205+ }
206+
207+ fn check_unsupported_syntax_expr ( & mut self , expr : & Expr ) {
208+ match expr {
209+ Expr :: Binary { left, right, .. } => {
210+ self . check_unsupported_syntax_expr ( left) ;
211+ self . check_unsupported_syntax_expr ( right) ;
212+ }
213+ Expr :: Field { base, .. } => self . check_unsupported_syntax_expr ( base) ,
214+ Expr :: Index { base, index, .. } => {
215+ self . check_unsupported_syntax_expr ( base) ;
216+ self . check_unsupported_syntax_expr ( index) ;
217+ }
218+ Expr :: Call { args, .. } => {
219+ for arg in args {
220+ self . check_unsupported_syntax_expr ( & arg. value ) ;
221+ }
222+ }
223+ Expr :: Effect { value, .. } | Expr :: Manage { value, .. } | Expr :: Try { value, .. } => {
224+ self . check_unsupported_syntax_expr ( value) ;
225+ }
226+ Expr :: Closure { body, .. } => self . check_unsupported_syntax_block ( body) ,
227+ Expr :: Ident ( _, _) | Expr :: Number ( _, _) | Expr :: String ( _, _) => { }
228+ Expr :: Unknown ( span) => self . unsupported_syntax (
229+ span. clone ( ) ,
230+ "unsupported expression" ,
231+ "This expression is outside the current RSScript parser surface." ,
232+ ) ,
233+ }
234+ }
235+
236+ fn unsupported_syntax ( & mut self , span : crate :: diagnostic:: Span , label : & str , cause : & str ) {
237+ self . diagnostics . push (
238+ Diagnostic :: error (
239+ code:: UNSUPPORTED_SYNTAX ,
240+ "unsupported RSScript syntax." ,
241+ span,
242+ label,
243+ )
244+ . with_cause ( cause)
245+ . with_fix (
246+ "rewrite_supported_syntax" ,
247+ "Rewrite this construct using the currently supported RSScript syntax." ,
248+ "manual" ,
249+ ) ,
250+ ) ;
251+ }
252+
145253 fn check_signature_explicitness ( & mut self ) {
146254 for item in & self . syntax_program . items {
147255 let Item :: Function ( function) = item else {
0 commit comments