This week's lab consists of practice and Q&A with the control flow aspects of intermediate code.
.first, .follow,
.onTrue, .onFalse
struct addr although you could
get away with an int (label #).
struct addr genlabel();denotes a function that returns a unique label each time it is called. Not sure if this should return a
struct addr, malloc and return a
pointer to a struct addr, or fill in a parameter that is a
pointer to a struct addr. Your choice.
int counter;
struct addr genlabel()
{
struct addr a;
a.region = R_LABEL;
a.offset = counter++;
return a;
}
void assign_first(struct tree *t)
{
int i;
for(i=0; i<t->nkids; i++) assign_first(t->kids[i]);
switch(t->prodrule) {
/* all switch cases that DO need a label: */
case THIS: case THAT: case THEOTHER:
t->first = genlabel();
}
}
.follow labels.
void assign_follow(struct tree *t)
{
int i;
switch(t->prodrule) {
case StmtSeqFromStatement1Statement2Prodrule: {
t->kids[0].follow = t->kids[1].first;
}
case IfThenStmtProdrule: {
t->kids[4].follow = t->follow;
}
/* ??? */
}
for(i=0; i<t->nkids; i++) assign_first(t->kids[i]);
}
.onTrue and
.onFalse labels.
.first and the .follow.
fun main()
{
var i : Int = 0;
while (i < 20) {
i = i * i + 1;
}
println("$i");
}
and if we managed that, extend it in various ways, enough to handle e.g.:
fun main()
{
var i : Int = 0;
while (i < 20 && i%3==1) {
i = i + 1;
}
println("$i");
}