/**
  * Updates the <code>node</code> to which <b>(OBJECT)</b> was applied previously.
  *
  * @param context the minimal typing proof context.
  * @param pNode the node to update according to <b>(OBJECT)</b>.
  */
 public void updateObject(MinimalTypingProofContext context, MinimalTypingProofNode pNode) {
   MinimalTypingExpressionProofNode node = (MinimalTypingExpressionProofNode) pNode;
   if (node.getFirstChild().isFinished()) {
     MinimalTypingExpressionProofNode child =
         (MinimalTypingExpressionProofNode) node.getFirstChild();
     TypeEnvironment environment = child.getEnvironment();
     Identifier self = new Identifier("self", Identifier.Set.SELF); // $NON-NLS-1$
     ObjectType objectType = (ObjectType) environment.get(self);
     RowType type = (RowType) objectType.getPhi();
     RowType type2 = (RowType) child.getType();
     try {
       // check type <: type2 and type2 <: type
       // if both true type = type2
       subtypeInternal(type, type2);
       subtypeInternal(type2, type);
     } catch (Exception e) {
       throw new RuntimeException(
           MessageFormat.format(
               Messages.getString("MinimalTypingException.7"),
               node.getExpression().toString())); // $NON-NLS-1$
     }
     ObjectType object = new ObjectType(type);
     // set the type of this node
     context.setNodeType(node, object);
   }
 }
 /**
  * Updates the <code>node</code> to which <b>(DUPL-SUBSUME)</b> was applied previously.
  *
  * @param context the minimal typing proof context.
  * @param pNode the node to update according to <b>(DUPL-SUBSUME)</b>.
  */
 public void updateDuplSubsume(MinimalTypingProofContext context, MinimalTypingProofNode pNode) {
   MinimalTypingExpressionProofNode node = (MinimalTypingExpressionProofNode) pNode;
   Duplication duplication = (Duplication) node.getExpression();
   if (node.getChildCount() == 1 && node.getLastChild().isFinished()) {
     // generate new child node
     context.addProofNode(node, node.getEnvironment(), duplication.getExpressions()[0]);
   } else if (node.getChildCount() > 1 && node.getLastChild().isFinished()) {
     // check if a:tau und e:tau' tau'<: tau
     TypeEnvironment environment = node.getEnvironment();
     Identifier id = duplication.getIdentifiers()[node.getChildCount() - 2];
     MonoType tau = null;
     try {
       tau = (MonoType) environment.get(id);
     } catch (Exception e) {
       throw new RuntimeException(
           MessageFormat.format(
               Messages.getString("MinimalTypingException.9"), id.toString())); // $NON-NLS-1$
     }
     MonoType tau2 = node.getLastChild().getType();
     if (tau == null || tau2 == null)
       throw new RuntimeException(
           MessageFormat.format(
               Messages.getString("MinimalTypingException.2"),
               "self")); //$NON-NLS-1$ //$NON-NLS-2$
     try {
       subtypeInternal(tau, tau2);
       subtypeInternal(tau2, tau);
     } catch (Exception e) {
       throw new RuntimeException(
           MessageFormat.format(
               Messages.getString("MinimalTypingException.2"),
               "self")); //$NON-NLS-1$ //$NON-NLS-2$
     }
   }
   if (node.getChildCount() == duplication.getIdentifiers().length + 1) {
     // set the type of this node
     context.setNodeType(node, node.getFirstChild().getType());
     // all childs added, so nothing more to do
     return;
   }
   // generate new child node
   context.addProofNode(
       node, node.getEnvironment(), duplication.getExpressions()[node.getChildCount() - 1]);
 }
 /**
  * Applies the <b>(OBJECT)</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 applyObject(MinimalTypingProofContext context, MinimalTypingProofNode pNode) {
   MinimalTypingExpressionProofNode node = (MinimalTypingExpressionProofNode) pNode;
   ObjectExpr object = (ObjectExpr) node.getExpression();
   MonoType tau = object.getTau();
   // check if user entered type for self
   if (tau == null) {
     throw new RuntimeException(
         MessageFormat.format(
             Messages.getString("MinimalTypingException.2"), "self")); // $NON-NLS-1$ //$NON-NLS-2$
   }
   // if type is a rec type, unfold to get a object type
   if (tau instanceof RecType) {
     RecType rec = (RecType) tau;
     tau = rec.getTau().substitute(rec.getTypeName(), rec);
   }
   TypeEnvironment environment = node.getEnvironment();
   environment = environment.star();
   // generate new child node
   context.addProofNode(node, environment.extend(object.getId(), tau), object.getRow());
 }
 /**
  * Updates the <code>node</code> to which <b>(ATTR)</b> was applied previously.
  *
  * @param context the minimal typing proof context.
  * @param pNode the node to update according to <b>(ATTR)</b>.
  */
 public void updateAttr(MinimalTypingProofContext context, MinimalTypingProofNode pNode) {
   MinimalTypingExpressionProofNode node = (MinimalTypingExpressionProofNode) pNode;
   if (node.getChildCount() == 1 && node.getFirstChild().isFinished()) {
     Row rowExpression = (Row) node.getExpression();
     Attribute attr = (Attribute) rowExpression.getExpressions()[0];
     TypeEnvironment environment = node.getEnvironment();
     // Create the tailRow and add it as Expression of a new Child
     Expression[] expressions = ((Row) node.getExpression()).getExpressions();
     Expression[] tailRow = new Expression[expressions.length - 1];
     for (int i = 1; i < expressions.length; i++) {
       tailRow[i - 1] = expressions[i];
     }
     Row row = new Row(tailRow);
     // generate new child node
     context.addProofNode(
         node, environment.extend(attr.getId(), node.getFirstChild().getType()), row);
   }
   if (node.getChildCount() == 2 && node.getChildAt(1).isFinished()) {
     // set the type of this node
     context.setNodeType(node, node.getChildAt(1).getType());
   }
 }