BacktickInstr.java

  1. package org.jruby.ir.instructions;

  2. import org.jruby.RubyBasicObject;
  3. import org.jruby.RubyString;
  4. import org.jruby.ir.IRVisitor;
  5. import org.jruby.ir.Operation;
  6. import org.jruby.ir.operands.Operand;
  7. import org.jruby.ir.operands.Variable;
  8. import org.jruby.ir.transformations.inlining.CloneInfo;
  9. import org.jruby.parser.StaticScope;
  10. import org.jruby.runtime.DynamicScope;
  11. import org.jruby.runtime.ThreadContext;
  12. import org.jruby.runtime.builtin.IRubyObject;

  13. import java.util.ArrayList;
  14. import java.util.List;
  15. import java.util.Map;

  16. // This represents a backtick string in Ruby
  17. // Ex: `ls .`; `cp #{src} #{dst}`
  18. //
  19. // NOTE: This operand is only used in the initial stages of optimization.
  20. // Further down the line, this string operand could get converted to calls
  21. public class BacktickInstr extends Instr implements ResultInstr {
  22.     private Variable result;
  23.     private List<Operand> pieces;

  24.     public BacktickInstr(Variable result, Operand val) {
  25.         super(Operation.BACKTICK_STRING);
  26.         this.result = result;
  27.         pieces = new ArrayList<Operand>();
  28.         pieces.add(val);
  29.     }

  30.     public BacktickInstr(Variable result, List<Operand> pieces) {
  31.         super(Operation.BACKTICK_STRING);
  32.         this.result = result;
  33.         this.pieces = pieces;
  34.     }

  35.     @Override
  36.     public Variable getResult() {
  37.         return result;
  38.     }

  39.     public List<Operand> getPieces() {
  40.         return pieces;
  41.     }

  42.     @Override
  43.     public void updateResult(Variable v) {
  44.         this.result = v;
  45.     }

  46.     @Override
  47.     public Operand[] getOperands() {
  48.         return pieces.toArray(new Operand[pieces.size()]);
  49.     }

  50.     @Override
  51.     public void simplifyOperands(Map<Operand, Operand> valueMap, boolean force) {
  52.         List<Operand> newPieces = new ArrayList<Operand>();
  53.         for (Operand p : pieces) {
  54.             newPieces.add(p.getSimplifiedOperand(valueMap, force));
  55.         }

  56.        pieces = newPieces;
  57.     }

  58.     @Override
  59.     public Instr clone(CloneInfo ii) {
  60.         List<Operand> newPieces = new ArrayList<Operand>();
  61.         for (Operand p : pieces) {
  62.             newPieces.add(p.cloneForInlining(ii));
  63.         }

  64.         return new BacktickInstr(ii.getRenamedVariable(result), newPieces);
  65.     }

  66.     @Override
  67.     public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
  68.         RubyString newString = context.runtime.newString();

  69.         for (Operand p: pieces) {
  70.             RubyBasicObject piece = (RubyBasicObject) p.retrieve(context, self, currScope, currDynScope, temp);
  71.             newString.append((piece instanceof RubyString) ? (RubyString) piece : piece.to_s());
  72.         }

  73.         newString.setFrozen(true);

  74.         return self.callMethod(context, "`", newString);
  75.     }

  76.     @Override
  77.     public void visit(IRVisitor visitor) {
  78.         visitor.BacktickInstr(this);
  79.     }

  80.     @Override
  81.     public String toString() {
  82.         return result + " = `" + (pieces == null ? "[]" : pieces) + "`";
  83.     }
  84. }