Hello and welcome, everybody.
So you obviously all know what functions are.
However, you probably don't know how we would go about implementing them in our compiler, so I'm going
to explain that in this lecture.
So firstly, let's ask what the functions have.
Functions have arguments.
Of course, you know, you might have a function called test that accepts and it x and Y functions have
scopes.
So if we are inside a function body, we can access the function arguments.
So the function arguments is a scope.
The body of the function is also a scope.
If we access a variable from a function body, it's first going to check the function body for that
variable.
If it can't find it, it's then going to check the function arguments for that variable.
If it's still confined it, then it's going to check the global scope, the global variables for that
variable.
And if it still can't find it, then then we have a compile error because we're accessing a variable
that doesn't exist.
So that explains the function scopes.
So functions have names that are unique.
So we can't have a structure name, the same name as a function name, for example, or vice versa.
We also can't have two functions having the same name.
Now you can in C++, but not C in C we cannot overload.
So function names have to be unique.
So this is why we have the symbol resolver, right?
Because then we can register a symbol with a given name and guarantee that a function isn't going to
come along and have the same name as a structure.
Functions can also return data.
So we can return integers, longs, pointers, you know, whatever we really want.
So here is how our finished structure will look like.
I have excluded a few things from here that the code generator will rely on, and that's mainly so I
don't feed you too much information right now.
So let's explain what we need to worry about at the moment.
So this is one of the substructures that will be inside struct node.
So, you know, we have like underscore struct and the scroll union, but we haven't made underscore
union yet.
We will do.
We also have things like expression.
It's a substructure of struct note.
Right?
Well, this is a substructure called struc function that will be inside the struct node later in the
course.
So it contains flags.
These are special flags for the function.
We'll discuss that soon in the next slide.
So let's now discuss this structure.
So we have flags.
This will be explained in the next slide.
We have a return type.
So the return type will be things like void, integer, long struct, union, whatever, it's returning.
We have a name.
This is self explanatory.
That's the function name, you know, like the main function.
This is our function argument structure with inside the structure function.
And this is quite a special structure.
So it contains a vector of struct node.
All the nodes in this vector have to be variable nodes.
If they're not, then there's an error like, you know, we should never allow anything other than a
variable node to be pushed to this vector.
Now, here's something you might be a bit confused about.
What is a stack addition?
Well, one, accessing a function argument from inside a function.
We have to look up the stack.
And I showed you this in a previous presentation.
Right.
We have to look up the stack, not down the stack.
Now, usually that would be eight bytes on a 32 bit system, but there are situations when it can be
more than eight bytes.
Okay.
We will discuss more on that later on.
But there are situations where it can be more than eight bytes and that's why we have a stack addition
here.
So whenever we access any variable inside this vector during code generation, we have to add the stack
addition.
So the offset of the variable node in this vector.
So that is what the stack addition is used for.
You won't have to worry about that until we get on to the code generator generator where I will then
go over this again in more detail for you.
But that's all that that is at the moment.
So then we have the body and variable.
This is the body, no variable.
So it's going to be null if it's just a function deck definition, like a function prototype.
If it's a fully declared function, then this will have.
See equal the body node of what's between those brackets of those brackets, essentially.
All right.
So if someone does in a test and they have those brackets, then obviously the body note will be equal
to the test body.
Finally, we have the stack size.
This is the sum of all variables inside of a function.
We need to know the stack size because when we enter a function, we need to reserve enough room on
the stack to access all of the variables inside the function.
And obviously, we can't just leave the stack hanging.
We have to restore it back to its old state, which is why we need to be aware of the stack size.
So I hope that explains our function memory structure and we will be parsing function soon.
So let me just explain the special flags of the function.
There's only one at the moment that I have in mind.
We might add more later on if I believe it's necessary.
Function No flag is native.
So later in the course we're going to have native functions.
So what do I mean by a native function?
I mean a function that exists only in the compiler.
And if you were to call it, it'll generate inline assembly.
So, for example, you can think of VA copy and VA start, right?
These functions that do do exist in C, they can work similar to like a macro function.
So what we will do is when someone comes and calls VA, start will actually generate inline assembly
in the actual output.
So that won't ever be a function symbol called VA start for example.
It will just simply generate assembly and it'll call that assembly when it's one, it's executing one,
our programs compile them running basically.
So you can think of our native functions as simply you call a function.
It gets replaced with a bunch of assembly code.
So it's kind of like volatile functions, right?
And you declare a volatile keyword and the compiler may or may not generate the code directly.
While it's similar to that, apart from we will absolutely generate the assembly code, we won't compile
a symbol for the function name.
So that's native functions for you.
We'll discuss more about that later, but that's all you have to worry about for the function special
flags at the moment.
Okay, so that concludes our lecture.
I just felt it was necessary to go over the function structure with you so that you aren't confused
as we go further in this course and start implementing this.