Example #1
0
  public void outALookupswitchStatement(ALookupswitchStatement node) {
    List lookupValues = new ArrayList();
    List targets = new ArrayList();
    UnitBox defaultTarget = null;

    if (node.getCaseStmt() != null) {
      int size = node.getCaseStmt().size();

      for (int i = 0; i < size; i++) {
        Object valueTargetPair = mProductions.removeLast();
        if (valueTargetPair instanceof UnitBox) {
          if (defaultTarget != null)
            throw new RuntimeException("error: can't ;have more than 1 default stmt");

          defaultTarget = (UnitBox) valueTargetPair;
        } else {
          Object[] pair = (Object[]) valueTargetPair;

          lookupValues.add(0, pair[0]);
          targets.add(0, pair[1]);
        }
      }
    } else {
      throw new RuntimeException("error: switch stmt has no case stmts");
    }

    Value key = (Value) mProductions.removeLast();
    Unit switchStmt = Jimple.v().newLookupSwitchStmt(key, lookupValues, targets, defaultTarget);

    mProductions.addLast(switchStmt);
  }
Example #2
0
  private void insertAfter(JPegStmt node, JPegStmt after) {
    // System.out.println("node: "+node);
    // System.out.println("after: "+after);
    //		System.out.println("succs of node: "+getSuccsOf(node));

    // this must be done first because the succs of node will be chanaged lately
    List succOfAfter = new ArrayList();
    succOfAfter.addAll(getSuccsOf(node));
    unitToSuccs.put(after, succOfAfter);

    Iterator succsIt = getSuccsOf(node).iterator();
    while (succsIt.hasNext()) {
      Object succ = succsIt.next();
      List pred = getPredsOf(succ);
      pred.remove(node);
      pred.add(after);
    }

    List succOfNode = new ArrayList();
    succOfNode.add(after);
    unitToSuccs.put(node, succOfNode);

    List predOfAfter = new ArrayList();
    predOfAfter.add(node);
    unitToPreds.put(after, predOfAfter);

    //	buildPredecessor(Chain pegChain);
  }
Example #3
0
  /*
    The purpose of this method is to replace the ASTIfElseNode
    given by the var nodeNumber with the new ASTIfNode
    and to add the remianing list of bodies after this ASTIfNode

    The new body is then returned;

  */
  public List<Object> createNewBody(List<Object> oldSubBody, int nodeNumber) {
    if (newIfNode == null) return null;

    List<Object> newSubBody = new ArrayList<Object>();

    if (oldSubBody.size() <= nodeNumber) {
      // something is wrong since the oldSubBody has lesser nodes than nodeNumber
      return null;
    }

    Iterator<Object> oldIt = oldSubBody.iterator();
    int index = 0;
    while (index != nodeNumber) {
      newSubBody.add(oldIt.next());
      index++;
    }

    // check to see that the next is an ASTIfElseNode
    ASTNode temp = (ASTNode) oldIt.next();
    if (!(temp instanceof ASTIfElseNode)) return null;

    newSubBody.add(newIfNode);

    newSubBody.addAll(remainingBody);

    // copy any remaining nodes
    while (oldIt.hasNext()) {
      newSubBody.add(oldIt.next());
    }

    return newSubBody;
  }
Example #4
0
  // Declared in AnonymousClasses.jrag at line 52
  private AnonymousDecl rewriteRule0() {
    {
      setModifiers(new Modifiers(new List().add(new Modifier("final"))));

      ConstructorDecl constructor = new ConstructorDecl();
      addBodyDecl(constructor);

      constructor.setModifiers((Modifiers) constructorDecl().getModifiers().fullCopy());
      String name = "Anonymous" + nextAnonymousIndex();
      setID(name);
      constructor.setID(name);

      List parameterList = new List();
      for (int i = 0; i < constructorDecl().getNumParameter(); i++) {
        parameterList.add(
            new ParameterDeclaration(
                constructorDecl().getParameter(i).type().createBoundAccess(),
                constructorDecl().getParameter(i).name()));
      }
      constructor.setParameterList(parameterList);

      List argList = new List();
      for (int i = 0; i < constructor.getNumParameter(); i++)
        argList.add(new VarAccess(constructor.getParameter(i).name()));
      constructor.setConstructorInvocation(
          new ExprStmt(new SuperConstructorAccess("super", argList)));
      constructor.setBlock(new Block());

      HashSet set = new HashSet();
      for (int i = 0; i < getNumBodyDecl(); i++) {
        if (getBodyDecl(i) instanceof InstanceInitializer) {
          InstanceInitializer init = (InstanceInitializer) getBodyDecl(i);
          set.addAll(init.exceptions());
        } else if (getBodyDecl(i) instanceof FieldDeclaration) {
          FieldDeclaration f = (FieldDeclaration) getBodyDecl(i);
          if (f.isInstanceVariable()) {
            set.addAll(f.exceptions());
          }
        }
      }
      List exceptionList = new List();
      for (Iterator iter = set.iterator(); iter.hasNext(); ) {
        TypeDecl exceptionType = (TypeDecl) iter.next();
        if (exceptionType.isNull()) exceptionType = typeNullPointerException();
        exceptionList.add(exceptionType.createQualifiedAccess());
      }
      constructor.setExceptionList(exceptionList);
      return this;
    }
  }
Example #5
0
    /**
     * Returns a <code>ThrowableSet</code> representing the set of exceptions included in <code>
     * include</code> minus the set of exceptions included in <code>exclude</code>. Creates a new
     * <code>ThrowableSet</code> only if there was not already one whose contents correspond to
     * <code>include</code> - <code>exclude</code>.
     *
     * @param include A set of {@link RefLikeType} objects representing exception types included in
     *     the result; may be <code>null</code> if there are no included types.
     * @param exclude A set of {@link AnySubType} objects representing exception types excluded from
     *     the result; may be <code>null</code> if there are no excluded types.
     * @return a <code>ThrowableSet</code> representing the set of exceptions corresponding to
     *     <code>include</code> - <code>exclude</code>.
     */
    private ThrowableSet registerSetIfNew(Set include, Set exclude) {
      if (INSTRUMENTING) {
        registrationCalls++;
      }
      if (include == null) {
        include = Collections.EMPTY_SET;
      }
      if (exclude == null) {
        exclude = Collections.EMPTY_SET;
      }
      int size = include.size() + exclude.size();
      Integer sizeKey = new Integer(size);

      List sizeList = (List) sizeToSets.get(sizeKey);
      if (sizeList == null) {
        sizeList = new LinkedList();
        sizeToSets.put(sizeKey, sizeList);
      }
      for (Iterator i = sizeList.iterator(); i.hasNext(); ) {
        ThrowableSet set = (ThrowableSet) i.next();
        if (set.exceptionsIncluded.equals(include) && set.exceptionsExcluded.equals(exclude)) {
          return set;
        }
      }
      if (INSTRUMENTING) {
        registeredSets++;
      }
      ThrowableSet result = new ThrowableSet(include, exclude);
      sizeList.add(result);
      return result;
    }
Example #6
0
  public List getUseBoxes() {
    List useBoxes = new ArrayList();

    useBoxes.addAll(opBox.getValue().getUseBoxes());
    useBoxes.add(opBox);

    return useBoxes;
  }
Example #7
0
 public void convertToBaf(JimpleToBafContext context, List<Unit> out) {
   Unit u = Baf.v().newLoadInst(getType(), context.getBafLocalOfJimpleLocal(this));
   out.add(u);
   Iterator it = context.getCurrentUnit().getTags().iterator();
   while (it.hasNext()) {
     u.addTag((Tag) it.next());
   }
 }
  public Object clone() {
    List argList = new ArrayList(getArgCount());

    for (int i = 0; i < getArgCount(); i++) {
      argList.add(i, Jimple.cloneIfNecessary(getArg(i)));
    }

    return new JInterfaceInvokeExpr(Jimple.cloneIfNecessary(getBase()), methodRef, argList);
  }
Example #9
0
  private void addBoxToPatch(String aLabelName, UnitBox aUnitBox) {
    List patchList = (List) mLabelToPatchList.get(aLabelName);
    if (patchList == null) {
      patchList = new ArrayList();
      mLabelToPatchList.put(aLabelName, patchList);
    }

    patchList.add(aUnitBox);
  }
  public List getUseBoxes() {
    List list = new ArrayList();

    for (int i = 0; i < argBoxes.size(); i++) {
      list.addAll(getArg(i).getUseBoxes());
      list.add(getArgBox(i));
    }

    return list;
  }
Example #11
0
  /** Returns a list of subinterfaces of c, including itself. */
  public List<SootClass> getSubinterfacesOfIncluding(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (!c.isInterface()) throw new RuntimeException("interface needed!");

    List<SootClass> l = new ArrayList<SootClass>();
    l.addAll(getSubinterfacesOf(c));
    l.add(c);

    return Collections.unmodifiableList(l);
  }
Example #12
0
  /** Returns a list of direct subclasses of c, including c. */
  public List<SootClass> getDirectSubclassesOfIncluding(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (c.isInterface()) throw new RuntimeException("class needed!");

    checkState();

    List<SootClass> l = new ArrayList<SootClass>();
    l.addAll(classToDirSubclasses.get(c));
    l.add(c);

    return Collections.unmodifiableList(l);
  }
 private static List<Unit> searchIfStmts(Body b) {
   List<Unit> searchResult = new ArrayList<Unit>();
   PatchingChain<Unit> statements = b.getUnits();
   Iterator<Unit> unitIt = statements.iterator();
   // iterate through the Units of the body
   while (unitIt.hasNext()) {
     Unit tempUnit = unitIt.next();
     // if the unit is a "if statement"
     if (tempUnit instanceof soot.jimple.internal.JIfStmt) searchResult.add(tempUnit);
   }
   return searchResult;
 }
Example #14
0
 private List createVariableDeclarationList() {
   List varList = new List();
   for (int j = 0; j < getNumVariableDecl(); j++) {
     VariableDeclaration v =
         getVariableDecl(j)
             .createVariableDeclarationFrom(
                 (Modifiers) getModifiers().fullCopy(), (Access) getTypeAccess().fullCopy());
     if (j == 0) v.setStart(start);
     varList.add(v);
   }
   return varList;
 }
Example #15
0
  public void outADeclaration(ADeclaration node) {
    List localNameList = (List) mProductions.removeLast();
    Type type = (Type) mProductions.removeLast();
    Iterator it = localNameList.iterator();
    List localList = new ArrayList();

    while (it.hasNext()) {
      Local l = Jimple.v().newLocal((String) it.next(), type);
      mLocals.put(l.getName(), l);
      localList.add(l);
    }
    mProductions.addLast(localList);
  }
Example #16
0
  public void convertToBaf(JimpleToBafContext context, List<Unit> out) {
    ((ConvertToBaf) getOp()).convertToBaf(context, out);

    Unit u;
    out.add(u = Baf.v().newThrowInst());

    Unit currentUnit = this;

    Iterator it = currentUnit.getTags().iterator();
    while (it.hasNext()) {
      u.addTag((Tag) it.next());
    }
  }
Example #17
0
  /*
    throws_clause =
    throws class_name_list;
  */
  public void outAThrowsClause(AThrowsClause node) {
    List l = (List) mProductions.removeLast();

    Iterator it = l.iterator();
    List exceptionClasses = new ArrayList(l.size());

    while (it.hasNext()) {
      String className = (String) it.next();

      exceptionClasses.add(mResolver.makeClassRef(className));
    }

    mProductions.addLast(exceptionClasses);
  }
Example #18
0
  private void buildHeadsAndTails() {

    List tailList = new ArrayList();
    List headList = new ArrayList();

    // Build the sets
    {
      Iterator unitIt = mainPegChain.iterator();

      while (unitIt.hasNext()) {
        JPegStmt s = (JPegStmt) unitIt.next();

        List succs = unitToSuccs.get(s);
        if (succs.size() == 0) tailList.add(s);
        if (!unitToPreds.containsKey(s)) {
          System.err.println("unitToPreds does not contain key: " + s);
          System.exit(1);
        }
        List preds = unitToPreds.get(s);
        if (preds.size() == 0) headList.add(s);
        // System.out.println("head is:");
      }
    }
    tails = (List) tailList;
    heads = (List) headList;
    //	tails = Collections.unmodifiableList(tailList);
    // heads = Collections.unmodifiableList(headList);

    Iterator tmpIt = heads.iterator();

    while (tmpIt.hasNext()) {
      Object temp = tmpIt.next();
      // System.out.println(temp);
    }

    buildPredecessor(mainPegChain);
  }
Example #19
0
  private void insertBefore(JPegStmt node, JPegStmt enter) {

    // build preds of before

    List predOfBefore = new ArrayList();
    predOfBefore.addAll(getPredsOf(node));
    unitToPreds.put(enter, predOfBefore);

    //	System.out.println("put into unitToPreds enter: "+enter);
    //	System.out.println("put into unitToPreds value: "+predOfBefore);
    Iterator predsIt = getPredsOf(node).iterator();

    // build succs of former preds of node
    while (predsIt.hasNext()) {
      Object pred = predsIt.next();

      List succ = getSuccsOf(pred);
      succ.remove(node);
      succ.add(enter);
      //	    System.out.println("in unitToPred pred: "+pred);
      //	    System.out.println("in unitToPred value is: "+succ);
    }

    List succOfBefore = new ArrayList();
    succOfBefore.add(node);
    unitToSuccs.put(enter, succOfBefore);
    //	System.out.println("put into unitToSuccs enter: "+enter);
    // System.out.println("put into unitToSuccs value: "+succOfBefore);

    List predOfNode = new ArrayList();
    predOfNode.add(enter);
    unitToPreds.put(node, predOfNode);
    // System.out.println("put into unitToPreds enter: "+node);
    // System.out.println("put into unitToPreds value: "+predOfNode);
    // buildPreds();

  }
  public void convertToBaf(JimpleToBafContext context, List out) {
    for (int i = 0; i < argBoxes.size(); i++) {
      ((ConvertToBaf) (getArg(i))).convertToBaf(context, out);
    }

    Unit u;
    out.add(u = Baf.v().newStaticInvokeInst(methodRef));

    Unit currentUnit = context.getCurrentUnit();

    Iterator it = currentUnit.getTags().iterator();
    while (it.hasNext()) {
      u.addTag((Tag) it.next());
    }
  }
Example #21
0
  private boolean removeBeginNode() {
    List heads = getHeads();
    if (heads.size() != 1) {
      // System.out.println("heads: "+heads);
      // System.out.println("Error: the size of heads is not equal to 1!");
      return false;
      //	    System.exit(1);
    } else {
      JPegStmt head = (JPegStmt) heads.get(0);
      // System.out.println("test head: "+head);
      if (!head.getName().equals("begin")) {
        System.err.println("Error: the head is not begin node!");
        System.exit(1);
      }
      // remove begin node from heads list
      heads.remove(0);
      // set the preds list of the succs of head to a new list and put succs of head into heads
      Iterator succOfHeadIt = getSuccsOf(head).iterator();
      while (succOfHeadIt.hasNext()) {

        JPegStmt succOfHead = (JPegStmt) succOfHeadIt.next();

        unitToPreds.put(succOfHead, new ArrayList());
        // put succs of head into heads
        heads.add(succOfHead);
      }
      // remove begin node from inlinee Peg
      if (!mainPegChain.remove(head)) {
        System.err.println("fail to remove begin node in from mainPegChain!");
        System.exit(1);
      }
      if (!allNodes.contains(head)) {
        System.err.println("fail to find begin node in FlowSet allNodes!");
        System.exit(1);
      } else {
        allNodes.remove(head);
      }

      // remove begin node from unitToSuccs
      if (unitToSuccs.containsKey(head)) {
        unitToSuccs.remove(head);
      }
    }

    return true;
  }
  public static void main(String args[]) {
    // Set classPath
    String exemplePath = "/Users/gamyot/Documents/workspace/Soot_Exemples/src/";
    String objectPath = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar";
    String tracePath = "/Users/gamyot/Documents/workspace/SootInstrumenter/src/";

    Scene.v().setSootClassPath(".:" + objectPath + ":" + exemplePath + ":" + tracePath);

    Scene.v().loadClassAndSupport("java.lang.Object");
    Scene.v().loadClassAndSupport("java.lang.System");

    // Set up the class we’re working with
    SootClass c = Scene.v().loadClassAndSupport("MyExemples.ExempleBasic");
    c.setApplicationClass();

    // Get methods
    Iterator<SootMethod> methodIterator = c.methodIterator();
    while (methodIterator.hasNext()) methodList.add(methodIterator.next());
    // Iterate through the method list
    for (SootMethod m : methodList) {
      Body body = m.retrieveActiveBody();
      PatchingChain<Unit> unitList = body.getUnits();
      // get the all the "if statements" Units
      List<Unit> ifStmtList = searchIfStmts(body);

      // for each "if statement" unit, instrument and add the instrumentation code right after
      for (Unit ifStmtUnit : ifStmtList) {
        // Chain<Unit> instrumentedChain = generateInstrumentationUnits(ifStmtUnit, body);
        // unitList.insertAfter(instrumentedChain, ifStmtUnit);
        Chain<Unit> testChain = generateInstrumentationUnits(ifStmtUnit, body);
        unitList.insertAfter(testChain, ifStmtUnit);
      }
      // Output all the units for this method on terminal
      String methodName = m.getName();
      System.out.println(
          "____Method: \"" + methodName + "\"__________________________________________________");
      LoadAndGenerate.printAllUnits(body);
    }

    try {
      LoadAndGenerate.outputClassToBinary(c);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 // Declared in VariableDeclaration.jrag at line 135
 private List rewriteTypeDecl_getBodyDecl() {
   {
     List varList = new List();
     for (int j = 0; j < getNumVariableDecl(); j++) {
       FieldDeclaration f =
           getVariableDecl(j)
               .createFieldDeclarationFrom(
                   (Modifiers) getModifiers().fullCopy(), (Access) getTypeAccess().fullCopy());
       if (j == 0) f.setStart(start);
       else {
         f.getModifiersNoTransform().clearLocations();
         f.getTypeAccessNoTransform().clearLocations();
       }
       f.setFieldDecl(this);
       varList.add(f);
     }
     return varList;
   }
 }
Example #24
0
  public void outAMultiNewExpr(AMultiNewExpr node) {

    LinkedList arrayDesc = node.getArrayDescriptor();

    int descCnt = arrayDesc.size();
    List sizes = new LinkedList();

    Iterator it = arrayDesc.iterator();
    while (it.hasNext()) {
      AArrayDescriptor o = (AArrayDescriptor) it.next();
      if (o.getImmediate() != null) sizes.add(0, (Value) mProductions.removeLast());
      else break;
    }

    Type type = (Type) mProductions.removeLast();
    ArrayType arrayType = ArrayType.v(type, descCnt);

    mProductions.addLast(Jimple.v().newNewMultiArrayExpr(arrayType, sizes));
  }
Example #25
0
  public void outATableswitchStatement(ATableswitchStatement node) {
    List targets = new ArrayList();
    UnitBox defaultTarget = null;

    int lowIndex = 0, highIndex = 0;

    if (node.getCaseStmt() != null) {
      int size = node.getCaseStmt().size();

      for (int i = 0; i < size; i++) {
        Object valueTargetPair = mProductions.removeLast();
        if (valueTargetPair instanceof UnitBox) {
          if (defaultTarget != null)
            throw new RuntimeException("error: can't ;have more than 1 default stmt");

          defaultTarget = (UnitBox) valueTargetPair;
        } else {
          Object[] pair = (Object[]) valueTargetPair;

          if ((i == 0 && defaultTarget == null) || (i == 1 && defaultTarget != null))
            highIndex = ((IntConstant) pair[0]).value;
          if (i == (size - 1)) lowIndex = ((IntConstant) pair[0]).value;

          targets.add(0, pair[1]);
        }
      }
    } else {
      throw new RuntimeException("error: switch stmt has no case stmts");
    }

    Value key = (Value) mProductions.removeLast();
    Unit switchStmt =
        Jimple.v().newTableSwitchStmt(key, lowIndex, highIndex, targets, defaultTarget);

    mProductions.addLast(switchStmt);
  }
Example #26
0
  /*
    arg_list =
    {single} immediate |
    {multi}  immediate comma arg_list;
  */
  public void outASingleArgList(ASingleArgList node) {
    List l = new ArrayList();

    l.add((Value) mProductions.removeLast());
    mProductions.addLast(l);
  }
Example #27
0
  /** Constructs a hierarchy from the current scene. */
  public Hierarchy() {
    this.sc = Scene.v();
    state = sc.getState();

    // Well, this used to be describable by 'Duh'.
    // Construct the subclasses hierarchy and the subinterfaces hierarchy.
    {
      Chain allClasses = sc.getClasses();

      classToSubclasses = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToSubinterfaces =
          new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f);

      classToDirSubclasses = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToDirSubinterfaces = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToDirImplementers = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);

      Iterator classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.isInterface()) {
          interfaceToDirSubinterfaces.put(c, new ArrayList());
          interfaceToDirImplementers.put(c, new ArrayList());
        } else classToDirSubclasses.put(c, new ArrayList());
      }

      classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.hasSuperclass()) {
          if (c.isInterface()) {
            Iterator subIt = c.getInterfaces().iterator();

            while (subIt.hasNext()) {
              SootClass i = (SootClass) subIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              List<SootClass> l = interfaceToDirSubinterfaces.get(i);
              l.add(c);
            }
          } else {
            List<SootClass> l = classToDirSubclasses.get(c.getSuperclass());
            l.add(c);

            Iterator subIt = c.getInterfaces().iterator();

            while (subIt.hasNext()) {
              SootClass i = (SootClass) subIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              l = interfaceToDirImplementers.get(i);
              l.add(c);
            }
          }
        }
      }

      // Fill the directImplementers lists with subclasses.
      {
        classesIt = allClasses.iterator();
        while (classesIt.hasNext()) {
          SootClass c = (SootClass) classesIt.next();
          if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
          if (c.isInterface()) {
            List<SootClass> imp = interfaceToDirImplementers.get(c);
            Set<SootClass> s = new ArraySet();

            Iterator<SootClass> impIt = imp.iterator();
            while (impIt.hasNext()) {
              SootClass c0 = impIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              s.addAll(getSubclassesOfIncluding(c0));
            }

            imp.clear();
            imp.addAll(s);
          }
        }
      }

      classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.isInterface()) {
          interfaceToDirSubinterfaces.put(
              c, Collections.unmodifiableList(interfaceToDirSubinterfaces.get(c)));
          interfaceToDirImplementers.put(
              c, Collections.unmodifiableList(interfaceToDirImplementers.get(c)));
        } else
          classToDirSubclasses.put(c, Collections.unmodifiableList(classToDirSubclasses.get(c)));
      }
    }
  }
Example #28
0
 public void outAMultiLocalNameList(AMultiLocalNameList node) {
   List l = (List) mProductions.removeLast();
   l.add(0, (String) mProductions.removeLast());
   mProductions.addLast(l);
 }
Example #29
0
 public void outASingleLocalNameList(ASingleLocalNameList node) {
   List l = new ArrayList();
   l.add((String) mProductions.removeLast());
   mProductions.addLast(l);
 }
Example #30
0
 public void outAMultiArgList(AMultiArgList node) {
   List l = (List) mProductions.removeLast();
   l.add(0, (Value) mProductions.removeLast());
   mProductions.addLast(l);
 }