case SELFNODE:
return new StringLiteral("self");
case VCALLNODE:
{
Variable tmp = s.getNewTemporaryVariable();
s.addInstr(new JRubyImplCallInstr(tmp, new MethAddr("getMetaClass"), getSelf(s), NO_ARGS));
Variable tmpVar = s.getNewTemporaryVariable();
StringLiteral mName = new StringLiteral(((VCallNode) node).getName());
s.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("isMethodBound"), tmp, new Operand[]{mName, BooleanLiteral.FALSE}));
buildDefinitionCheck(s, tmpVar, "method");
return tmpVar;
}
case CONSTNODE:
{
Variable tmpVar = s.getNewTemporaryVariable();
StringLiteral mName = new StringLiteral(((ConstNode) node).getName());
s.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("threadContext_getConstantDefined"), null, new Operand[]{mName}));
buildDefinitionCheck(s, tmpVar, "constant");
return tmpVar;
}
case GLOBALVARNODE:
{
Variable tmpVar = s.getNewTemporaryVariable();
StringLiteral mName = new StringLiteral(((GlobalVarNode) node).getName());
s.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("runtime_isGlobalDefined"), null, new Operand[]{mName}));
buildDefinitionCheck(s, tmpVar, "global-variable");
return tmpVar;
}
case INSTVARNODE:
{
Variable tmpVar = s.getNewTemporaryVariable();
StringLiteral mName = new StringLiteral(((GlobalVarNode) node).getName());
s.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("self_hasInstanceVariable"), getSelf(s), new Operand[]{mName}));
buildDefinitionCheck(s, tmpVar, "instance-variable");
return tmpVar;
}
case YIELDNODE:
{
Variable tmpVar = s.getNewTemporaryVariable();
s.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("block_isGiven"), null, NO_ARGS));
buildDefinitionCheck(s, tmpVar, "yield");
return tmpVar;
}
case FCALLNODE:
{
Variable tmpVar = s.getNewTemporaryVariable();
s.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("getMetaClass"), getSelf(s), NO_ARGS));
Label undefLabel = s.getNewLabel();
Label defLabel = s.getNewLabel();
StringLiteral mName = new StringLiteral(((FCallNode)node).getName());
Instr callInstr = new JRubyImplCallInstr(tmpVar, new MethAddr("isMethodBound"), tmpVar, new Operand[]{mName, BooleanLiteral.FALSE});
s.addInstr(callInstr);
s.addInstr(new BEQInstr(tmpVar, BooleanLiteral.FALSE, undefLabel));
s.addInstr(new CopyInstr(tmpVar, buildGetArgumentDefinition(((FCallNode) node).getArgsNode(), s, "method")));
s.addInstr(new JumpInstr(defLabel));
s.addInstr(new LABEL_Instr(undefLabel));
s.addInstr(new CopyInstr(tmpVar, Nil.NIL));
s.addInstr(new LABEL_Instr(defLabel));
return tmpVar;
}
case COLON3NODE:
case COLON2NODE:
{
final Colon3Node iVisited = (Colon3Node) node;
final String name = iVisited.getName();
// store previous exception for restoration if we rescue something
Variable errInfo = s.getNewTemporaryVariable();
s.addInstr(new JRubyImplCallInstr(errInfo, new MethAddr("threadContext_stashErrInfo"), null, NO_ARGS));
CodeBlock protectedCode = new CodeBlock() {
public Object run(Object[] args) {
IRScope m = (IRScope)args[0];
Node n = (Node)args[1];
String name = (String)args[2];
Variable tmpVar = m.getNewTemporaryVariable();
Operand v;
if (n instanceof Colon2Node) {
v = build(((Colon2Node) n).getLeftNode(), m);
} else {
m.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("runtime_getObject"), null, NO_ARGS));
v = tmpVar;
}
m.addInstr(new JRubyImplCallInstr(tmpVar, new MethAddr("getDefinedConstantOrBoundMethod"), null, new Operand[]{v, new StringLiteral(name)}));
return tmpVar;
}
};
// rescue block
CodeBlock rescueBlock = new CodeBlock() {
public Object run(Object[] args) {
// Nothing to do -- ignore the exception, and restore stashed error info!
// SSS FIXME: Is this correct? Or, do we compare against a specific exception type?
IRScope m = (IRScope)args[0];
m.addInstr(new JRubyImplCallInstr(null, new MethAddr("threadContext_restoreErrInfo"), null, new Operand[]{(Variable)args[1]}));
return Nil.NIL;
}
};
return protectCodeWithRescue(s, protectedCode, new Object[]{s, iVisited, name}, rescueBlock, new Object[] {s, errInfo});