package de.fuberlin.projecta.analysis.ast;
import de.fuberlin.commons.lexer.TokenType;
import de.fuberlin.commons.parser.ISyntaxTree;
import de.fuberlin.projecta.codegen.LLVM;
public class IfElse extends Statement {
private Block block;
@Override
public String genCode() {
String ret = "";
block = getHighestBlock();
if (block != null) {
boolean not = false;
if(getChild(0) instanceof UnaryOp){
AbstractSyntaxTree uOp = (AbstractSyntaxTree) getChild(0);
while (uOp instanceof UnaryOp) {
if (((UnaryOp) uOp).getOp() == TokenType.OP_NOT) {
not = !not;
}
uOp = (AbstractSyntaxTree) uOp.getChild(0);
}
}
int label = block.getNewVar();
this.setBeginLabel(label);
ret += "br label %" + label + "\n\n";
ret += "; <label> %" + label + "\n";
if(!(getChild(0) instanceof Id)){
ret += ((AbstractSyntaxTree) getChild(0)).genCode();
ret += LLVM.genBranch(this, ((AbstractSyntaxTree) getChild(1)),
((AbstractSyntaxTree) getChild(2)), not, false);
} else {
Id id = (Id) getChild(0);
int tmp1 = block.getNewVar();
ret += "%" + tmp1 + " = load i1* %" + id.getValue() + "\n";
int tmp2 = block.getNewVar();
ret += "%" + tmp2 + " = icmp ne i1 %" + tmp1 + ", 0\n";
ret += LLVM.genBranch(this, ((AbstractSyntaxTree) getChild(1)),
((AbstractSyntaxTree) getChild(2)), not, false);
}
}
return ret;
}
protected boolean hasReturnStatement() {
return ifBranchHasReturnStatement() && elseBranchHasReturnStatement();
}
protected boolean couldAmmendReturnStatement() {
boolean ifWentWell = true;
if (!ifBranchHasReturnStatement())
ifWentWell = ammendReturnOnIf();
if (!elseBranchHasReturnStatement()) {
ISyntaxTree elseBranch = this.getChild(2);
if (elseBranch instanceof Block) {
System.out.println("It is a block! Hooray!");
return ((Block) elseBranch).couldAmmendReturnStatement();
} else if (elseBranch instanceof Do) {
return ((Do) elseBranch).couldAmmendReturnStatement();
} else if (elseBranch instanceof IfElse) {
return ((IfElse) elseBranch).couldAmmendReturnStatement();
} else if (elseBranch instanceof BinaryOp) {
BinaryOp binOp = (BinaryOp) elseBranch;
if (binOp.getOp() == TokenType.OP_ASSIGN) {
// first child has to be an identifier. This is checked
// beforehand!
this.removeChild(this.getChildrenCount() - 1);
Return r = new Return();
r.addChild(binOp.getChild(0));
Block block = new Block();
block.addChild(binOp);
block.addChild(r);
this.addChild(block);
return true;
} // it is an operation. A return statement will be created with
// this operation
} else if (elseBranch instanceof Break
|| elseBranch instanceof Print || elseBranch instanceof If
|| elseBranch instanceof While) {
return false;
} else {
Return r = new Return();
r.addChild(elseBranch);
this.removeChild(this.getChildrenCount() - 1);
this.addChild(r);
}
}
// For we know at this point that else went well :-)
return ifWentWell;
}
private boolean ammendReturnOnIf() {
ISyntaxTree ifBranch = this.getChild(1);
if (ifBranch instanceof Block) {
return ((Block) ifBranch).couldAmmendReturnStatement();
} else if (ifBranch instanceof Do) {
return ((Do) ifBranch).couldAmmendReturnStatement();
} else if (ifBranch instanceof IfElse) {
return ((IfElse) ifBranch).couldAmmendReturnStatement();
} else if (ifBranch instanceof BinaryOp) {
BinaryOp binOp = (BinaryOp) ifBranch;
if (binOp.getOp() == TokenType.OP_ASSIGN) {
// first child has to be an identifier. This is checked
// beforehand!
ISyntaxTree elseBranch = this.removeChild(2);
this.removeChild(1);
Block block = new Block();
block.addChild(binOp);
Return r = new Return();
r.addChild(binOp.getChild(0));
block.addChild(r);
this.addChild(block);
this.addChild(elseBranch);
return true;
} // it is an operation. A return statement will be created with
// this operation
} else if (ifBranch instanceof Break || ifBranch instanceof Print
|| ifBranch instanceof If || ifBranch instanceof While) {
return false;
}
Return r = new Return();
r.addChild(ifBranch);
this.removeChild(this.getChildrenCount() - 1);
return true;
}
private boolean ifBranchHasReturnStatement() {
ISyntaxTree ifBranch = this.getChild(1);
if (ifBranch instanceof Block) {
return ((Block) ifBranch).hasReturnStatement();
} else if (ifBranch instanceof Do) {
return ((Do) ifBranch).hasReturnStatement();
} else if (ifBranch instanceof IfElse) {
return ((IfElse) ifBranch).hasReturnStatement();
} else if (ifBranch instanceof Return) {
return true;
}
return false;
}
private boolean elseBranchHasReturnStatement() {
ISyntaxTree elseBranch = this.getChild(2);
if (elseBranch instanceof Block) {
return ((Block) elseBranch).hasReturnStatement();
} else if (elseBranch instanceof Do) {
return ((Do) elseBranch).hasReturnStatement();
} else if (elseBranch instanceof IfElse) {
return ((IfElse) elseBranch).hasReturnStatement();
} else if (elseBranch instanceof Return) {
return true;
}
return false;
}
}