Question

I am writing a simple program interpreter in c++. When I am building the internal representation of the program and I get a break statement, how do I determine the encompassing loops target location?

void Imp::whilestmt()
{
    Expr *pExpr;
    accept(Token::WHILE);
    expr(pExpr);
    WhileStmt *pwhilestmt = new WhileStmt(pExpr,vm.getLocationCounter);
    vm.add(pwhilestmt);
    accept(Token::LOOP);
    stmtlist();
    pwhilestmt->setTarget(vm.getLocationCounter);
    accept(Token::END);
    accept(Token::LOOP);
    vm.add(new EndLoopStmt);
}

My break statement object is going to take the the while statement's target as a parameter, how can I determine this?

Était-ce utile?

La solution 2

I think the solution is to add a forward reference that is resolved (by looking up the location of the end of the loop) when all the code for that level of loop has been produced.

In other words, when generating the code for the loop, you need to form a "jump" instruction, which has it's target set to somewhere you don't know where it is yet. The solution is to have a jump with an unknown destination (set the "destination" to instruction 0 or -1 or 0xdeaddead or something else that can be easily identified for debugging purposes later - because the best way to avoid getting bugs of "I didn't fix it up properly" is to make it easy to identify those places - bugs only occur in things that are hard to identify, just like it never rains when you carry an umbrella), and keep a fixup list of such jumps until you have generated the entire loop, then work your way through that fixup list, and fill in the relevant address that you now know is "here" (the next instruction after the loop). I suspect you also need something similar for the condition of the loop itself - if that's false, then you need to continue "after" the loop.

Autres conseils

I'd consider building a kind of execution tree/pipeline. Every LOOP/WHILE would be a new branch (similarily to every function) so when you encounter END/BREAK instruction you just revert to the branches origin point and continue down the line.

I added setTarget as a virtual function of Stmt.

I stored the start location in the part that handles the if statements and then checked if I had any break stmts from the start location to the current location, and if I did I set the target to the current location.

really messy way to do it, but it works for now

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top