package de.fuberlin.projecta.analysis.ast;
import de.fuberlin.commons.parser.ISyntaxTree;
import de.fuberlin.projecta.analysis.SemanticException;
import de.fuberlin.projecta.codegen.LLVM;
public class Return extends Statement {
public Expression getArgument() {
if (getChildrenCount() == 0)
return null;
return (Expression) getChild(0);
}
@Override
public String genCode() {
String ret = "";
Expression argument = getArgument();
if (argument == null) {
getHighestBlock().getNewVar();
return "br label %return\n";
} else {
ret += LLVM.loadType(argument);
ret += "store " + getParentFunction().fromTypeStringToLLVMType()
+ " %" + LLVM.getMem(argument) + ", "
+ getParentFunction().fromTypeStringToLLVMType() + "* %1\n"
+ "br label %return\n";
getHighestBlock().getNewVar();
}
return ret;
}
@Override
public void checkTypes() {
String funcType = getParentFunction().toTypeString();
if (this.getChildrenCount() == 0) {
// return type must be void!
if (!funcType.equals(BasicType.TYPE_VOID_STRING))
throw new SemanticException("Missing return value in non-void function", this);
} else {
String returnType = getArgument().toTypeString();
if (!funcType.equals(returnType))
throw new SemanticException(
"Incompatible arguments: Function declared with return type "
+ funcType + " but returned " + returnType, this);
}
}
private FuncDef getParentFunction() {
ISyntaxTree func = this;
do {
func = func.getParent();
} while (!(func instanceof FuncDef));
return (FuncDef) func;
}
}