What:
A part of the Compiler Frontend that checks if the abstract syntax tree is semantically correct. This includes:
- Assignment Target Analysis: Are all left-hand-sides of assignments valid targets? Options are:
- Variable name, e.g.
x = 4 + 5
- An index to a list, e.g.
x[0] = 4 + 5
- Variable name, e.g.
- Name Analysis: Are all variables and functions declared before they’re used?
- Type Analysis / Checking: Are variable types consistent?
How?
We do 3 iterative passes of the AST, tackling a different analysis each time. Ok but how?
How to Traverse the Tree?
We use the visitor pattern - a class with a traverse
and visit
method.
traverse
goes over the tree andvisit
actually changes the node in question
You could check overload the visit()
function with the different things to do based on which part of the AST you’re on. Example below:
1. Assignment Target Analysis:
Write a visit_assign()
function that gets called whenever you’ve hit an assignment (=
) operator. Check the left of it is a variable name or index expression.
2. Name Analysis:
To do this, we keep a context (aka environment) of all of the variables and functions that reflects what we typically refer to as “scope”. You parse through the program and add to it as you go.
But what about in the following context:
def foo():
bar()
def bar():
foo()
It’s a chicken and egg scenario. To check foo
, we need to know if bar
is valid and vice versa. To solve this, we do 2 contexts.