public void start() {
    for (int i = 0; i < defs.length; i++) {
      OpDefNode def = defs[i];
      if (def.getSource() != def && !BBuiltInOPs.contains(def.getSource().getName())) {
        // instance
        String defName = def.getName().toString();

        if (def.getBody() instanceof SubstInNode) {
          String prefix = defName.substring(0, defName.lastIndexOf('!') + 1);
          def.setParams(generateNewParams(def.getParams()));
          ExprNode body;
          try {
            body = generateNewExprNode(def.getBody(), prefix);
          } catch (AbortException e) {
            throw new RuntimeException();
          }
          def.setBody(body);
        }
      }
    }
  }
  /**
   * @param n
   * @param prefix
   * @return
   * @throws AbortException
   */
  private ExprNode generateNewOpApplNode(OpApplNode n, String prefix) throws AbortException {
    switch (n.getOperator().getKind()) {
      case VariableDeclKind:
      case ConstantDeclKind:
        {
          ExprOrOpArgNode e = (ExprOrOpArgNode) n.getOperator().getToolObject(substitutionId);
          if (e != null) {
            if (e instanceof ExprNode) {
              // TODO newprefix, witout last prefix
              return generateNewExprNode((ExprNode) e, "");
            } else {
              OpArgNode opArg = (OpArgNode) e;
              while (opArg.getOp().getToolObject(substitutionId) != null) {
                opArg = (OpArgNode) opArg.getOp().getToolObject(substitutionId);
              }
              return new OpApplNode(
                  opArg.getOp(), generateNewArgs(n.getArgs(), prefix), n.getTreeNode(), null);
            }
          } else {
            return new OpApplNode(
                n.getOperator(), generateNewArgs(n.getArgs(), prefix), n.getTreeNode(), null);
          }
        }

      case FormalParamKind:
        {
          FormalParamNode f = (FormalParamNode) n.getOperator().getToolObject(substitutionId);
          if (f == null) {
            throw new RuntimeException();
          }
          return new OpApplNode(f, generateNewArgs(n.getArgs(), prefix), n.getTreeNode(), null);
        }

      case BuiltInKind:
        {
          return generateNewBuiltInNode(n, prefix);
        }

      case UserDefinedOpKind:
        {
          // in case of a call of a LetInNode
          OpDefNode letOp = (OpDefNode) n.getOperator().getToolObject(substitutionId);
          if (letOp != null) {
            return new OpApplNode(
                letOp, generateNewArgs(n.getArgs(), prefix), n.getTreeNode(), null);
          }

          // in case of a call of BBuiltInOp e.g. +, -
          if (BBuiltInOPs.contains(n.getOperator().getName())) {
            return new OpApplNode(
                n.getOperator(), generateNewArgs(n.getArgs(), prefix), n.stn, null);
          }

          // normal userdefined Operator
          String opName = prefix + n.getOperator().getName().toString();
          OpDefNode op = defsHash.get(opName);
          if (op == null) {
            throw new RuntimeException();
          }
          return new OpApplNode(op, generateNewArgs(n.getArgs(), prefix), n.getTreeNode(), null);
        }
    }
    throw new RuntimeException("OpApplkind not implemented jet");
  }