Hello and welcome.
In this lecture, I'm going to discuss scopes.
So firstly, what is a scope?
Pretty much most of you watching the course probably have a rough idea of what a scope is.
A scope holds variables.
Scopes can have parent scopes so they can nest.
And when searching for a variable, we check from the most recent scope upwards.
In other words, someone someone accessing a variable in a scope lower than them, they will not have
access to it.
So here's a scope example.
So we have a global variable of DH.
We have a function called Main that takes variable of Z, and we have two variables A and B in the function
body.
And this is how our compiler will understand it.
So for the most recent scope created, it's kind of a stack.
You can think of it as a stack, pushing the scope and pop in the scope of the scope.
You can see our most recent scope, the function body scope has variable A and B, and then the next
level is our function arguments, which has variable Z.
And the final level up is our global scope, which is variable DX.
Okay.
So yeah, a scopes in our system, they don't necessarily have to be between these brackets or function
arguments.
Our global scope also counts.
So in our function body, if we were to go B equals DX, it'll first check this local scope, every
variable above itself.
It won't find DX.
So then it will go on to the function argument scope here.
It'll check all the variables in there.
It won't find D, so then it will check the global scope and it will find DX.
If it still can't find DX in the global scope, then the variable doesn't exist.
And that's where our compiler then needs to say, Hold on a minute, you're accessing a variable that
doesn't exist.
So you can think of it as this hierarchy.
So here are the scope rules in our compiler.
No two variables can have the same name in the same scope.
So obviously you know that inside a function you can have two variables named X, right?
But if you have an if statement, then of course you can have a variable called X inside that F statement,
no problem.
So when opening brackets, that creates a new scope.
So you can see here scope two has variable X, scope one has variable Y and it sets to x.
X cannot access scope one y scope one can access scope two's x.
So function arguments can have their own scopes.
As as I've just described to you, global variables are in the global scope.
So if we go back can see variable DX that's in the global scope.
And finally, the global scope is the highest possible scope.
So the global global scope has no parent.
You can't get any higher than that if you can't find what you're looking for.
By the time you reach the global scope, then the variable doesn't exist.
It's as simple as that.
So now let's explain structure scopes.
So structure bodies will have their own scopes that will have no parents.
So let me explain what I mean by that structure.
ABC here, where we have an X that will be a scope on its own.
It will not link to the global scope, it will have no parent.
Now the reason for this is because when we have a structure, we can put it anywhere.
We can create a structure variable in the global scope, we can create it in the function body scope.
It can be like five F statements down in a function name test, you know what I mean?
We do not know where those variables can go.
They can go absolutely anywhere.
We don't know where they are.
So because of that, it doesn't make sense to try and link these scopes to their own parents.
Therefore, we treat them as independent beings.
They have their own scope and that doesn't link anywhere.
You can't go any higher than it x.
That's how it sees itself.
So you might be wondering them.
Well, okay, if that's the case, how can we do an expression such as dot x equals 50?
Or you can see here A is in our global scope, D is in the structured dog and the ABC, which is variable
DX is here which holds X.
So how does that work?
Okay.
Well, the first thing we do is we find variable A, which is here and we know that's on the global
scope.
So great.
We've already got an offset now that we can work with.
We then look through the structure, dog's static scope that has no parent.
We look through it and find the offset for DX and then we know it's that's a structure too.
So we go in there and we find the next scope of struct ABC.
Remember, these are static scopes, they don't change and we go and look in there for variable x and
then we sum all of those offsets together.
And then there we go.
We now have the position of a dot x and that's how it works.
But we'll be using a special tool that will be creating this course called the resolver, and the resolver
will be in charge of all of this.
We won't be creating that for a good couple lectures down the line, but it's important that I tell
you on this lecture that structures have their own scopes so that you're aware of that.
So we will be programmatically creating these scopes.
That's why I'm talking about scopes in this lecture.
So.
We're going to be creating systems that keep track of all the scopes in our compiler because obviously
we need to be able to know where variable X is located in the executable binary.
And we also need to know are they accessing a variable that doesn't exist?
And the only way we can know those things is if we keep some sort of system that keeps track of scopes
for us.
So this Scopes system will be split into two parts.
The first part be called the scope system, which will basically represent what I've described here
in the scope example, this hierarchy.
And then we have the resolve in scope system which will basically be in charge of going through individual
scopes, static scopes will call them and essentially merging offsets and stuff like that to find the
actual real position of a variable in a scope.
So they are the two scopes systems where creating the scope system and the resolver system.
So the resolver system will come later in the course.
In the next few lectures, we'll be focusing more on the scope system.
So thanks for watching.