}
private Node currentBodyNode;
public void compileDefn(Node node, BodyCompiler context, boolean expr) {
final DefnNode defnNode = (DefnNode) node;
final ArgsNode argsNode = defnNode.getArgsNode();
CompilerCallback body = new CompilerCallback() {
public void call(BodyCompiler context) {
if (defnNode.getBodyNode() != null) {
Node oldBodyNode = currentBodyNode;
currentBodyNode = defnNode.getBodyNode();
if (defnNode.getBodyNode() instanceof RescueNode) {
// if root of method is rescue, compile as a light rescue
compileRescueInternal(defnNode.getBodyNode(), context, true);
} else {
compile(defnNode.getBodyNode(), context, true);
}
currentBodyNode = oldBodyNode;
} else {
context.loadNil();
}
}
};
CompilerCallback args = new CompilerCallback() {
public void call(BodyCompiler context) {
compileArgs(argsNode, context, true);
}
};
// inspect body and args
ASTInspector inspector = new ASTInspector();
// check args first, since body inspection can depend on args
inspector.inspect(defnNode.getArgsNode());
// if body is a rescue node, inspect its pieces separately to avoid it disabling all optz
// TODO: this is gross.
if (defnNode.getBodyNode() instanceof RescueNode) {
RescueNode rescueNode = (RescueNode)defnNode.getBodyNode();
inspector.inspect(rescueNode.getBodyNode());
inspector.inspect(rescueNode.getElseNode());
inspector.inspect(rescueNode.getRescueNode());
} else {
inspector.inspect(defnNode.getBodyNode());
}
context.defineNewMethod(
defnNode.getName(), defnNode.getArgsNode().getArity().getValue(),
defnNode.getScope(), body, args, null, inspector, isAtRoot,
defnNode.getPosition().getFile(), defnNode.getPosition().getStartLine(),
RuntimeHelpers.encodeParameterList(argsNode));
// TODO: don't require pop
if (!expr) context.consumeCurrentValue();
}