/**
   * @param hop
   * @param vars
   * @throws DMLRuntimeException
   */
  protected static void rReplaceLiterals(Hop hop, LocalVariableMap vars)
      throws DMLRuntimeException {
    if (hop.getVisited() == VisitStatus.DONE) return;

    if (hop.getInput() != null) {
      // indexed access to allow parent-child modifications
      for (int i = 0; i < hop.getInput().size(); i++) {
        Hop c = hop.getInput().get(i);
        Hop lit = null;

        // conditional apply of literal replacements
        lit = (lit == null) ? replaceLiteralScalarRead(c, vars) : lit;
        lit = (lit == null) ? replaceLiteralValueTypeCastScalarRead(c, vars) : lit;
        lit = (lit == null) ? replaceLiteralValueTypeCastLiteral(c, vars) : lit;
        lit = (lit == null) ? replaceLiteralDataTypeCastMatrixRead(c, vars) : lit;
        lit = (lit == null) ? replaceLiteralValueTypeCastRightIndexing(c, vars) : lit;
        lit = (lit == null) ? replaceLiteralFullUnaryAggregate(c, vars) : lit;
        lit = (lit == null) ? replaceLiteralFullUnaryAggregateRightIndexing(c, vars) : lit;

        // replace hop w/ literal on demand
        if (lit != null) {
          // replace hop c by literal, for all parents to prevent (1) missed opportunities
          // because hop c marked as visited, and (2) repeated evaluation of uagg ops

          if (c.getParent().size() > 1) { // multiple parents
            ArrayList<Hop> parents = new ArrayList<Hop>(c.getParent());
            for (Hop p : parents) {
              int pos = HopRewriteUtils.getChildReferencePos(p, c);
              HopRewriteUtils.removeChildReferenceByPos(p, c, pos);
              HopRewriteUtils.addChildReference(p, lit, pos);
            }
          } else { // current hop is only parent
            HopRewriteUtils.removeChildReferenceByPos(hop, c, i);
            HopRewriteUtils.addChildReference(hop, lit, i);
          }
        }
        // recursively process children
        else {
          rReplaceLiterals(c, vars);
        }
      }
    }

    hop.setVisited(VisitStatus.DONE);
  }