}
case DVARNODE: {
return new StringLiteral("local-variable");
}
case BACKREFNODE: {
return buildDefinitionCheck(s, new BackrefIsMatchDataInstr(s.getNewTemporaryVariable()), "global-variable");
}
case DREGEXPNODE:
case DSTRNODE: {
Operand v = super.buildVersionSpecificGetDefinitionIR(node, s);
Label doneLabel = s.getNewLabel();
Variable tmpVar = getValueInTemporaryVariable(s, v);
s.addInstr(BNEInstr.create(tmpVar, manager.getNil(), doneLabel));
s.addInstr(new CopyInstr(tmpVar, new StringLiteral("expression")));
s.addInstr(new LabelInstr(doneLabel));
return tmpVar;
}
case NOTNODE: {
Operand v = buildGetDefinitionBase(((NotNode)node).getConditionNode(), s);
Label doneLabel = s.getNewLabel();
Variable tmpVar = getValueInTemporaryVariable(s, v);
s.addInstr(BEQInstr.create(tmpVar, manager.getNil(), doneLabel));
s.addInstr(new CopyInstr(tmpVar, new StringLiteral("method")));
s.addInstr(new LabelInstr(doneLabel));
return tmpVar;
}
case NTHREFNODE: {
// SSS FIXME: Is there a reason to do this all with low-level IR?
// Can't this all be folded into a Java method that would be part
// of the runtime library, which then can be used by buildDefinitionCheck method above?
// This runtime library would be used both by the interpreter & the compiled code!
/* -------------------------------------------------------------------------------------
* We have to generate IR for this:
* v = backref; (!(v instanceof RubyMatchData) || v.group(n).nil?) ? nil : "global-variable"
*
* which happens to be identical to: (where nthRef implicitly fetches backref again!)
* v = backref; (!(v instanceof RubyMatchData) || nthRef(n).nil?) ? nil : "global-variable"
*
* I am using the second form since it let us encode it in fewer IR instructions.
* But, note that this second form is not as clean as the first one plus it fetches backref twice!
* ------------------------------------------------------------------------------------- */
int n = ((NthRefNode) node).getMatchNumber();
Label undefLabel = s.getNewLabel();
Variable tmpVar = s.getNewTemporaryVariable();
s.addInstr(new BackrefIsMatchDataInstr(tmpVar));
s.addInstr(BEQInstr.create(tmpVar, manager.getFalse(), undefLabel));
// SSS FIXME:
// - Can/should I use BEQInstr(new NthRef(n), manager.getNil(), undefLabel)? instead of .nil? & compare with flag?
// - Or, even create a new IsNilInstr and NotNilInstr to represent optimized scenarios where
// the nil? method is not monkey-patched?