44import types
55
66from typing import NamedTuple
7+ from typing import Optional
78from typing import Set
89
910import src .api .global_ as gl
@@ -156,6 +157,12 @@ def visit_FUNCTION(self, node):
156157 yield node
157158 else :
158159 node .visited = True
160+ if node .body .token == 'BLOCK' and (not node .body or node .body [- 1 ].token != 'RETURN' ):
161+ # String functions must *ALWAYS* return a value.
162+ # Put a sentinel ("dummy") return "" sentence that will be removed if other is detected
163+ lineno = node .lineno if not node .body else node .body [- 1 ].lineno
164+ errmsg .warning_function_should_return_a_value (lineno , node .name , node .filename )
165+ node .body .append (symbols .ASM ('\n ld hl, 0\n ' , lineno , node .filename , is_sentinel = True ))
159166 yield (yield self .generic_visit (node ))
160167
161168 def visit_LET (self , node ):
@@ -195,9 +202,41 @@ def visit_UNARY(self, node):
195202 yield (yield self .generic_visit (node ))
196203
197204 def visit_BLOCK (self , node ):
205+ warning_emitted = False
206+ i = 0
207+ while i < len (node ):
208+ sentence = node [i ]
209+ if chk .is_ender (sentence ):
210+ j = i + 1
211+ while j < len (node ) - 1 :
212+ if chk .is_LABEL (node [j ]):
213+ break
214+
215+ if node [j ].token == 'FUNCDECL' :
216+ j += 1
217+ continue
218+
219+ if node [j ].is_sentinel : # "Sentinel" instructions can be freely removed
220+ node .pop (j )
221+ continue
222+
223+ if node [j ].token == 'ASM' :
224+ break # User's ASM must always be left there
225+
226+ if not warning_emitted and self .O_LEVEL > 0 :
227+ warning_emitted = True
228+ errmsg .warning_unreachable_code (lineno = node [j ].lineno , fname = node [j ].filename )
229+
230+ if self .O_LEVEL < 2 :
231+ break
232+
233+ node .pop (j )
234+ i += 1
235+
198236 if self .O_LEVEL >= 1 and chk .is_null (node ):
199237 yield self .NOP
200238 return
239+
201240 yield (yield self .generic_visit (node ))
202241
203242 def visit_IF (self , node ):
@@ -309,12 +348,12 @@ class VarDependency(NamedTuple):
309348
310349
311350class VariableVisitor (GenericVisitor ):
312- _original_variable = None
351+ _original_variable : Optional [ symbols . VAR ] = None
313352 _parent_variable = None
314- _visited = set ()
353+ _visited : Set [ symbols . SYMBOL ] = set ()
315354
316355 @staticmethod
317- def generic_visit (node ):
356+ def generic_visit (node : symbols . SYMBOL ): # type: ignore
318357 if node not in VariableVisitor ._visited :
319358 VariableVisitor ._visited .add (node )
320359 for i in range (len (node .children )):
@@ -332,7 +371,7 @@ def has_circular_dependency(self, var_dependency: VarDependency) -> bool:
332371 return False
333372
334373 def get_var_dependencies (self , var_entry : symbols .VAR ):
335- visited : Set [symbols .Var ] = set ()
374+ visited : Set [symbols .VAR ] = set ()
336375 result = set ()
337376
338377 def visit_var (entry ):
0 commit comments