Hello and welcome everybody to part three of implementing structures.
I appreciate we've had quite a hard time to get to this point, but now we're here.
We can finally finish implementing the structures.
As I'm sure you will appreciate, there was a lot of things we needed to do before that would work successfully.
Now we can finally finish implementing these structures.
Okay, so let's just remind you of where we left off, because it's been a couple of lectures since
we've done this.
So we were implementing the parsing of structures and unions and yeah, essentially, if you remember
in our past verbal functional struct union function, we check if the data type is a structure or union
and then we call PA struct or union to handle that.
Right.
That's what we were doing.
So on this line, we're still not finished.
There's still a bunch of other stuff we need to do, such as registering it with the symbol resolver
and so on, the structure we've parsed.
I mean, however, we'll get to that.
We're now going to focus on actually implementing the paths struct, no new scope which is currently
empty.
So just head there and we're going to start filling that in.
And obviously, as you know, we've already parsed the structure dog or whatever it might be called
part of this structure already, which is why we have a data type.
So we're now focused on parsing the actual body and providing certain flags.
That's what we're going to be doing now.
Okay.
So the very first thing we need to do, we need to create a new function argument here.
We're going to call it pull is forward declaration, because if it's a forward declaration, we need
to handle this differently.
So we're just going to pass in the is forward declaration variable that we we handled on line 954 here.
Okay.
So if that's true, then it's a forward declaration.
In other words, we're doing something like struct dog semicolon rather than struct dog brackets.
Okay.
I expect you all to know what a full declaration is to be on this course if you don't just Google it
and read about that before continuing here.
So we're going to start by creating a null body node, then a body variable size.
And now we're just going to say if it's not a forward declaration, then parse the body, because obviously
it has a body because it's not a function, it's not a structured declaration.
So we're going to pass in the body variable size and we're going to go history begin and then we're
going to say history, flag inside structure.
Okay.
So remember what I was saying about that history flag inside structure when we are making the bodies,
you know, you can see that we check that that flag when we call the scope offset function.
And if that flag is set, then we know we're parsing a structure offset, basically an offset inside
a structure.
So that's why we're passing the flag there.
So the parse body, when it goes to calculate the scope offset, it'll pass that flag along and obviously
then we'll search upwards because we're searching from inside a structure body.
Okay, so now we're just going to go body node equals no pop.
All right.
Now I'll obviously pop off the actual node that we passed here when we go parse body.
So it's popping off the body node and now we just want to head over to Node C because we want to create
a function for creating structure nodes.
So just buy here and make body node.
We're going to go void make struct node that's going to take in a crunch char of a type string and it's
going to take in a body node.
So now just by here, we're going to say in it, flags equals zero.
If the body node is null, then flags or equal, no flag is forward declaration.
And we don't yet we haven't yet defined that.
And then we're just going to go node create ampersand struct node dot type equals node type struct dot
underscore struct dot body n equals body node dot underscore struct dot name equals type string.
So that's the actual structure name.
You know what we'll even call it name.
Actually, just keep things simple.
So basically that's the name after the struct keyword.
Okay.
And guys, we need a comma by that as well, right.
Just after the struct body, body and node and then just put a dot underscore struct name equals a name
like that.
Finally we're going to say flags equals flags.
So that is to create our node type struct.
And that looks absolutely fine to me.
So copy and paste this string that we've written here because we're going to need to go and put that
in compilers.
It's just got to compile that heat search for no flag.
We'll see no flag inside expression.
Just paste that in.
Copy and paste the binary number and move the one one place to the left.
Just like that.
Okay, nice.
So now if that flag is set, then we know there's a there's a four declaration.
Okay, let's copy and paste the function prototype name and we're going to put that in the header file
as well so that there's a way to access it.
So let's now head over to POSIX C and just under this if statement, we're going to say make struct
node, we're going to say D type type string.
So in that way, if they if there was like a dog, obviously the type string will be dog and that'll
be passed to the make struct node.
Right.
Second argument will be the body node that we just parsed.
NULL is perfectly acceptable.
If if null was provided, then obviously the flag node flag is for declaration will be set because obviously
if it has no body node, it's a forward declaration.
So now we're just going to pop off that struct node
and we're going to say if there was a body node, then the D type size is now equal to the body node,
body size, which makes sense because structures are basically storage containers.
So of course their size should equal the sum of all of their body.
So that's why we do that.
So now here we're going to say D type node equals struct node.
And now what if someone was to do something like this?
Obviously they've declared a variable called ABC of type dog.
So we need to deal with that scenario.
So we're going to check for that next.
So if token peak next type is token type identifier,
then pop off the var name
and then we need to set a flag.
But let's just go to compile that to actually create the flag.
So just by here, we're going to say no flag has variable combined, which basically means there's a
variable combined with whatever entity this is.
And again, shift the one one place to the left back to dot.
See we're going to say struct nodes, flags or equals node flag has variable combined.
So we're now going to say is we're going to say if D type flags ampersand data type flagged struc union
no name, then this will mean no name was provided.
So what we're saying with this F statement is if there is no name for this structure, then we'll need
to deal with it.
Okay.
So if you remember, if we just search that here, you can see that when we are parsing the types couple
lectures ago, we checked to see if there's no name and if there is and we generate one.
Remember we were doing that.
So this is because, as I've said before, it's possible to do something like this where we don't actually
even have a structure name.
So that's why we check for that scenario.
Right?
So if that is the case and we've been provided a variable, so it looks something like that struct ABC
like that, then we're going to say D type type string equals var name s file.
We're then going to take off the data type flag struct union, no name bit.
And then we're then going to update the structure node structure name to equal the var name.
So what this will basically do and it might not be the best design, we might come back and change it,
but what it'll do is essentially if we did something like this, it'll take the variable name and it
will basically make it like this to understand.
So the struct contains that name.
Now, this can be a problem in some cases.
Like if we had something like struct dog and then we had dog here and then we have to structures of
dogs, right.
So we will need to combat something like that later on.
But for now, we're going to keep it like that.
To keep it simple.
Simple.
And we'll test later on to see if this is going to be a problem for us.
But right now, I just want to make it as easy as possible for us, the engineers, to be able to identify
the structures we're creating because the structures do need a name, but no pressure.
We're just going to keep this like this for now because it makes our life easier.
And if it is a problem later on, we'll just we'll come back and change this.
But this code is fine for now.
So now just by here, I'm going to say make variable node and register.
We're going to say history begin zero.
We're going to say D type.
We're going to save our name and we're going to say null just like that.
So obviously make variable node and register will essentially make a variable node.
It'll pop it off, it'll calculate scope offset, push to the scope and push it back to the stack.
So that's what's going on there.
And obviously the reason we're making a variable node and registering it is because the moment someone
did something like this,
they've essentially created a variable called Hello that has a type of Z.
Okay.
So obviously we need to then register that variable node.
Hello, which is essentially struct Z.
Hello.
And Stan, which is why we're registering it by the.
Okay, cool.
So then obviously we need to say struck node underscore struct dot var equals no pop because we're popping
off the variable node we just created by here you c make variable node our popping that off the one
that was pushed on 671 cool.
And we set the actual structure var here so that anyone who has access to that structure knows that
it has an associated registered variable with it.
Okay, so all structures must end with semicolons.
So we're going to check for semicolon
and then we're going to push the struct node to our stack.
We are done creating the structure.
All structures and with semicolons call.
Nice.
Okay, so we're pretty much done with that actual function.
I know we haven't implemented unions yet.
They can come later.
It's just check everything.
Now we should see that everything.
So k c everything looks fine to me.
So what we're going to have to do now is we're going to need to go back to the past variable functional
struct union.
We're just going to finish this on the line 1 to 6.
So if you remember correctly, we essentially check to see if the data type is a structure or union.
And then we check to see if there's a body symbol, a left bracket indicating a new body.
And if that's the case, then we pass the structure or union.
Okay.
So we're going to say struct nodes, askew node.
What's the assuming structure union?
We don't know if it's a structure, a union.
We know one of them is being parsed, so we'll call it an S node.
As for structure, you've union so in a pop it off.
Okay.
And now that we've popped it off, we now need to call a function in the same resolver.
The problem is we haven't actually exported any functions since the header file here, so just copy
and paste this.
The same resolver build for node prototype and we're going to put that in the compiler H file just so
we have access to it.
So I'm just going to put it by there and then we can call it then from parsed.
C Okay.
So once you've done that back to the dot C, we're going to see some resolver build for Node.
We're going to pass in the current process and the SEU note.
So as you know, the SIM resolve above for no function will basically register it.
And just going over to refresh your memory because it's been a while so you can see when this is called,
it'll check to see if it's a node type structure and if it is, it'll build it for a structure node
which are not yet implemented.
So it's a good job.
I did just show you that because we're going to have to come back and implement that in a moment.
So anyway, back to paths dot C, we do symbols or above for node and then we're going to push the node
back to the stack because obviously we've popped it off.
Now that we've dealt with it, we need to push it back.
Finally, we're going to call return because we don't want any of this code running down here if that's
the case.
And I don't like to use too many else because it can get very messy if we do things like else and we
have nested if statements, it makes more sense to just use a go to or return whichever one is most
appropriate.
Okay.
So that is it for the parsing of structures.
Congratulations.
We do need to now finish up and then symbols are built for node.
So let's just head there in the in the build for structure.
We're going to get rid of this compiler error because now we're obviously going to start implementing
it.
So essentially we're going to first check to see if there's a flag.
Okay, the forward declaration flag.
No flag is forward declaration.
If that flag is there, then we just return because we do not register forward declarations.
Otherwise we're going to say sym resolver, register, symbol, process, symbol, name, node, struct,
name, type, or B symbol type node.
And the actual data will be the node itself.
So as we've already explained, the symbol resolver exist so that we can register things in the system
that should only really exist once and also things that we can look up later on.
So if someone wants to do struct dog
ABC, we know to look up the dog structure in the symbol resolver.
Okay.
So yeah, that's how that's working.
We register for function nodes, union nodes and structure nodes.
I know I've already explained this to you, but we're going over it again just briefly.
So.
So your memory can refresh.
So I hope that makes sense.
Let me know if you're a little still confused about that.
Okay, guys.
So that's going to be it for this lecture.
We haven't yet finished implementing the structures because we still need to do the initialization.
So if we just search for data type, expect struct.
You can see here we have compiler error structure and union types are not yet supported.
So in the next few lectures we're going to have to finish implementing that so that they are supported
and can be initialized.
And when we reach that point, we will then have the ability to basically declare structure variables
such as struct dog ABC.
So it's going to be exciting.
So yeah, I hope that made sense.
And thank you very much for watching.