/**
  * Applies the <b>(SEND)</b> rule to the <code>pNode</code> using the <code>pContext</code>.
  *
  * @param pContext The big step proof pContext.
  * @param pNode The node to apply the <b>(SEND)</b> rule to.
  */
 public void applySend(BigStepProofContext pContext, BigStepProofNode pNode) {
   Send send = (Send) pNode.getExpression();
   if (send.getE() instanceof Row) {
     throw new IllegalArgumentException("Can not apply SEND"); // $NON-NLS-1$
   }
   pContext.addProofNode(pNode, send.getE());
 }
 /**
  * Updates the <code>node</code> to which <b>(SEND)</b> was applied previously.
  *
  * @param pContext The big step proof context.
  * @param pNode The node to update according to <b>(SEND)</b>.
  */
 public void updateSend(BigStepProofContext pContext, BigStepProofNode pNode) {
   if ((pNode.getChildCount() == 1) && (pNode.getChildAt(0).isProven())) {
     Send send = (Send) pNode.getExpression();
     ObjectExpr objectExpr = (ObjectExpr) pNode.getChildAt(0).getResult().getValue();
     Row row = objectExpr.getRow();
     Expression newRow;
     newRow = row.substitute(objectExpr.getId(), objectExpr);
     pContext.addProofNode(pNode, new Send(newRow, send.getId()));
   } else if ((pNode.getChildCount() == 2)
       && (pNode.getChildAt(0).isProven())
       && (pNode.getChildAt(1).isProven())) {
     pContext.setProofNodeResult(pNode, pNode.getChildAt(1).getResult());
   }
 }
 /**
  * Applies the <b>(SEND-ATTR)</b> rule to the <code>pNode</code> using the <code>pContext</code>.
  *
  * @param pContext The big step proof pContext.
  * @param pNode The node to apply the <b>(SEND-ATTR)</b> rule to.
  */
 public void applySendAttr(BigStepProofContext pContext, BigStepProofNode pNode) {
   Send send = (Send) pNode.getExpression();
   Row row = (Row) send.getE();
   if (!row.isValue()) {
     throw new IllegalArgumentException("Can not apply SEND-ATTR"); // $NON-NLS-1$
   }
   Expression[] rowExpressions = row.getExpressions();
   Attribute attribute = (Attribute) rowExpressions[0];
   Expression[] newRowExpressions = new Expression[row.getExpressions().length - 1];
   for (int i = 0; i < newRowExpressions.length; i++) {
     newRowExpressions[i] = rowExpressions[i + 1].substitute(attribute.getId(), attribute.getE());
   }
   pContext.addProofNode(pNode, new Send(new Row(newRowExpressions), send.getId()));
 }
 /**
  * Applies the <b>(SEND-EXEC)</b> rule to the <code>pNode</code> using the <code>pContext</code>.
  *
  * @param pContext The big step proof pContext.
  * @param pNode The node to apply the <b>(SEND-EXEC)</b> rule to.
  */
 public void applySendExec(BigStepProofContext pContext, BigStepProofNode pNode) {
   Send send = (Send) pNode.getExpression();
   Row row = (Row) send.getE();
   if (!row.isValue()) {
     throw new IllegalArgumentException("Can not apply SEND-EXEC"); // $NON-NLS-1$
   }
   Expression[] rowExpressions = row.getExpressions();
   Identifier methodName;
   Expression methodExpression;
   if (rowExpressions[0] instanceof Method) {
     Method method = (Method) rowExpressions[0];
     methodExpression = method.getE();
     methodName = method.getId();
   } else if (rowExpressions[0] instanceof CurriedMethod) {
     CurriedMethod curriedMethod = (CurriedMethod) rowExpressions[0];
     methodExpression = curriedMethod.getE();
     Identifier[] identifiers = curriedMethod.getIdentifiers();
     MonoType[] types = curriedMethod.getTypes();
     for (int i = identifiers.length - 1; i > 0; i--) {
       methodExpression = new Lambda(identifiers[i], types[i], methodExpression);
     }
     methodName = identifiers[0];
   } else {
     throw new IllegalArgumentException("Can not apply SEND-EXEC"); // $NON-NLS-1$
   }
   if (!(send.getId().equals(methodName))) {
     throw new IllegalArgumentException("Can not apply SEND-EXEC"); // $NON-NLS-1$
   }
   boolean definedLater = false;
   for (int i = 1; i < row.getExpressions().length; i++) {
     Expression rowChild = rowExpressions[i];
     if ((rowChild instanceof Method) && (((Method) rowChild).getId().equals(send.getId()))) {
       definedLater = true;
       break;
     } else if ((rowChild instanceof CurriedMethod)
         && (((CurriedMethod) rowChild).getIdentifiers()[0].equals(send.getId()))) {
       definedLater = true;
       break;
     }
   }
   if (!definedLater) {
     pContext.addProofNode(pNode, methodExpression);
   } else {
     throw new IllegalArgumentException("Can not apply SEND-EXEC"); // $NON-NLS-1$
   }
 }
 /**
  * Updates the <code>node</code> to which <b>(SEND)</b> was applied previously.
  *
  * @param context the minimal typing proof context.
  * @param pNode the node to update according to <b>(SEND)</b>.
  */
 public void updateSend(
     @SuppressWarnings("unused") MinimalTypingProofContext context, MinimalTypingProofNode pNode) {
   MinimalTypingExpressionProofNode node = (MinimalTypingExpressionProofNode) pNode;
   Send send = (Send) node.getExpression();
   if (node.getFirstChild().isFinished()) {
     ObjectType object = (ObjectType) node.getFirstChild().getType();
     RowType row = (RowType) object.getPhi();
     Identifier id = send.getId();
     int index = row.getIndexOfIdentifier(id);
     // check if identifier of send is in the row type
     if (index < 0)
       throw new RuntimeException(
           MessageFormat.format(
               Messages.getString("MinimalTypingException.6"),
               node.getExpression().toString())); // $NON-NLS-1$
     // set the type of this node
     context.setNodeType(node, row.getTypes()[index]);
   }
 }
 /**
  * Applies the <b>(SEND-SKIP)</b> rule to the <code>pNode</code> using the <code>pContext</code>.
  *
  * @param pContext The big step proof pContext.
  * @param pNode The node to apply the <b>(SEND-SKIP)</b> rule to.
  */
 public void applySendSkip(BigStepProofContext pContext, BigStepProofNode pNode) {
   Send send = (Send) pNode.getExpression();
   Row row = (Row) send.getE();
   if (!row.isValue()) {
     throw new IllegalArgumentException("Can not apply SEND-SKIP"); // $NON-NLS-1$
   }
   Expression[] rowExpressions = row.getExpressions();
   Identifier methodName;
   if (rowExpressions[0] instanceof Method) {
     Method method = (Method) rowExpressions[0];
     methodName = method.getId();
   } else if (rowExpressions[0] instanceof CurriedMethod) {
     CurriedMethod curriedMethod = (CurriedMethod) rowExpressions[0];
     methodName = curriedMethod.getIdentifiers()[0];
   } else {
     throw new IllegalArgumentException("Can not apply SEND-SKIP"); // $NON-NLS-1$
   }
   boolean definedLater = false;
   for (int i = 1; i < row.getExpressions().length; i++) {
     Expression rowChild = rowExpressions[i];
     if ((rowChild instanceof Method) && (((Method) rowChild).getId().equals(send.getId()))) {
       definedLater = true;
       break;
     } else if ((rowChild instanceof CurriedMethod)
         && (((CurriedMethod) rowChild).getIdentifiers()[0].equals(send.getId()))) {
       definedLater = true;
       break;
     }
   }
   if ((definedLater) || (!(send.getId().equals(methodName)))) {
     pContext.addProofNode(pNode, new Send(row.tailRow(), send.getId()));
   } else {
     throw new IllegalArgumentException("Can not apply SEND-SKIP"); // $NON-NLS-1$
   }
 }
 /**
  * Applies the <b>(SEND)</b> rule to the
  * <code>node</node> using the <code>context</code>.
  *
  * @param context the minimal typing proof context.
  * @param pNode the minimal typing proof node.
  */
 public void applySend(MinimalTypingProofContext context, MinimalTypingProofNode pNode) {
   MinimalTypingExpressionProofNode node = (MinimalTypingExpressionProofNode) pNode;
   Send send = (Send) node.getExpression();
   // generate new child node
   context.addProofNode(node, node.getEnvironment(), send.getE());
 }