semantic: add semantic checks for variables
Check read before first assignment Check unused variables
This commit is contained in:
parent
bcca6d4a6e
commit
f060608e73
1 changed files with 29 additions and 1 deletions
|
|
@ -5,10 +5,11 @@ from typing import Literal
|
|||
|
||||
from . import nodes
|
||||
from .errors import SemanticAnalysisError
|
||||
from .logger import Logger
|
||||
from .logger import Logger, Tracer, LogLevel
|
||||
from .typechecking import typecheck
|
||||
|
||||
logger = Logger(__name__)
|
||||
tracer = Tracer(logger=logger, level=LogLevel.Debug)
|
||||
|
||||
|
||||
class SymbolABC(abc.ABC):
|
||||
|
|
@ -181,6 +182,33 @@ class Context:
|
|||
def __repr__(self) -> str:
|
||||
return self._pprint()
|
||||
|
||||
@tracer.trace_method
|
||||
def check(self) -> None:
|
||||
for variable in self.variables.values():
|
||||
|
||||
# Check for reads before assignments
|
||||
for read in variable.reads:
|
||||
previous_write = None
|
||||
for write in variable.writes:
|
||||
if write.location() < read.location():
|
||||
previous_write = write
|
||||
break
|
||||
if previous_write is None:
|
||||
message = f"Reading undefined variable {variable.name}"
|
||||
if len(variable.writes) > 0:
|
||||
first_write = min(variable.writes, key=lambda w: w.location())
|
||||
message += f" (first assignment is at {first_write.location().begin})"
|
||||
raise SemanticAnalysisError(location=read.location(),
|
||||
message=message)
|
||||
|
||||
# Check for unused variables
|
||||
if len(variable.reads) == 0 and variable.definition is not None:
|
||||
raise SemanticAnalysisError(variable.definition.location(),
|
||||
message=f"Variable '{variable.name}' is unused")
|
||||
|
||||
for context in self.child_contexts.values():
|
||||
context.check()
|
||||
|
||||
|
||||
class BuiltinContext(Context):
|
||||
def __init__(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue