/** Cache the values entered by the user in VEPs dynamically-displayed on VM start. */
  void cacheArgumentValues() {

    // Collect the value entry panels which correspond to target arguments in the TableTop
    List<ValueEditor> argPanels = getArgumentPanels();

    List<Gem.PartInput> argParts = targetDisplayedGem.getTargetArguments();
    int numArgs = argParts.size();

    // sanity check
    if (numArgs != argPanels.size()) {
      throw new IllegalStateException(
          "Programming Error: matching "
              + numArgs
              + " arguments and "
              + argPanels.size()
              + " argument panels.");
    }

    for (int i = 0; i < numArgs; i++) {
      Gem.PartInput argPart = argParts.get(i);
      ValueEditor argPanel = argPanels.get(i);
      ValueNode argNode = argPanel.getValueNode();
      gemCutter.getTableTop().cacheArgValue(argPart, argNode);
    }
  }
  /**
   * Determine if the current target Gem only has arguments that we can provide editors for.
   *
   * @return boolean true if we can provide all the arguments, false if we can't
   */
  private boolean targetHasProvidableArgs() {
    // Get the target's arguments first
    List<Gem.PartInput> args = targetDisplayedGem.getTargetArguments();

    // If we have no arguments, then we at least have providable args (we can easily
    // provided none at all!)
    if (args == null) {
      return true;
    }

    // Check all the argument types for being ones that we can provide
    int numArgs = args.size();
    Gem.PartInput sinkPart;
    for (int i = 0; i < numArgs; i++) {
      // Get this part
      sinkPart = args.get(i);

      // Can we deal with this type?
      if (!valueEditorHierarchyManager
          .getValueEditorManager()
          .canInputDefaultValue(sinkPart.getType())) {
        // Oops, can't provide an editor for this type
        return false;
      }
    }

    // If we haven't found any dodgy ones, then we can provide all of them!
    return true;
  }
  /**
   * Display execution results. Call this to display the results of the run when execution
   * terminates. Note: the runtime must still be available
   */
  private void displayResults() {

    int messageIcon = -1;
    String messageTitle = null;
    String errorMessage = null;

    // Set up the icon and the title
    if (error == null) {
      messageIcon = JOptionPane.INFORMATION_MESSAGE;
      messageTitle = GemCutter.getResourceString("GemResults");
      errorMessage = null;
    } else {
      errorMessage = error.getMessage();
      CALExecutorException.Type resultStatus = error.getExceptionType();
      if (resultStatus == CALExecutorException.Type.PRIM_THROW_FUNCTION_CALLED) {
        messageIcon = JOptionPane.ERROR_MESSAGE;
        messageTitle = GemCutter.getResourceString("GemError");

      } else if (resultStatus
          == CALExecutorException.Type.FOREIGN_OR_PRIMITIVE_FUNCTION_EXCEPTION) {
        messageIcon = JOptionPane.ERROR_MESSAGE;
        messageTitle = GemCutter.getResourceString("ForeignFunctionError");

      } else if (resultStatus == CALExecutorException.Type.ERROR_FUNCTION_CALL) {
        messageIcon = JOptionPane.ERROR_MESSAGE;
        messageTitle = GemCutter.getResourceString("GemError");

      } else if (resultStatus == CALExecutorException.Type.PATTERN_MATCH_FAILURE) {
        messageIcon = JOptionPane.ERROR_MESSAGE;
        messageTitle = GemCutter.getResourceString("PatternMatchFailure");

      } else if (resultStatus == CALExecutorException.Type.INTERNAL_RUNTIME_ERROR) {
        messageIcon = JOptionPane.ERROR_MESSAGE;
        messageTitle = GemCutter.getResourceString("RuntimeError");

      } else if (resultStatus == CALExecutorException.Type.USER_TERMINATED) {
        messageIcon = JOptionPane.INFORMATION_MESSAGE;
        messageTitle = GemCutter.getResourceString("GemResults");
      } else {
        throw new IllegalStateException("Unrecognized execution result status: " + resultStatus);
      }
    }

    if (executionResult != null) {
      try {
        executionResult.toString();
      } catch (Exception e) {
        executionResult = null;
        if (errorMessage == null) {
          errorMessage = "Error trying to display result value.";
        }
      }
    }

    // If we're not in debug output mode, and there's no scary weirdness, then we use the
    // value entry mechanism.  Else, just use the debug output.
    if (!gemCutter.isDebugOutputMode() // && (numValues > 0) //&& !programmaticErrorFlagged
    /*&& valueNodeBuilderHelper.isConstructorNodeArgumentStackEmpty()*/ ) {

      // If there's an extra message, print it out.
      ValueNode vn = getOutputValueNode();
      if (executionResult == null) {

        // If we got a null result and no error, check for the case where the null represents a null
        // foreign value.

        // foreignTypeConsApp will hold the TypeConsApp for the output value
        // if the value is a foreign value and the result is null.
        TypeConsApp foreignTypeConsApp = null;
        if (errorMessage == null && vn != null) {
          TypeConsApp typeConsApp = vn.getTypeExpr().rootTypeConsApp();
          if (typeConsApp != null && typeConsApp.getForeignTypeInfo() != null) {
            foreignTypeConsApp = typeConsApp;
          }
        }

        if (foreignTypeConsApp != null) {
          // Make sure that the value node is a ForeignValueNode.

          // An example of a problem this prevents:
          //   The ColorValueNode is encapsulates a foreign Java value java.awt.Color, and so has a
          // foreign type.
          //   However, the color output editor may assume that it has a non-null editor.
          if (!(vn instanceof ForeignValueNode)) {
            vn = new ForeignValueNode(null, foreignTypeConsApp);
          }
          vn.setOutputJavaValue(null);

        } else {
          vn = null;
        }

      } else {
        vn.setOutputJavaValue(executionResult);
      }

      // Make sure target is visible before we display results
      gemCutter
          .getTableTop()
          .getTableTopPanel()
          .scrollRectToVisible(targetDisplayedGem.getBounds());
      gemCutter.displayOutput(vn, targetDisplayedGem, messageTitle, errorMessage);

    } else {
      // The main return is the 0th output value
      String message =
          (executionResult != null)
              ? executionResult.toString()
              : GemCutter.getResourceString("NoResults");

      // Display the output, debug style.
      JOptionPane.showMessageDialog(gemCutter, message, messageTitle, messageIcon);
    }
  }
 /**
  * Set the displayed gem being run by this target runner.
  *
  * @param targetDisplayedGem the displayed gem to run.
  * @param targetModule the module in which the target exists.
  */
 void setTargetDisplayedGem(DisplayedGem targetDisplayedGem, ModuleName targetModule) {
   setTarget(targetDisplayedGem.getTarget(), targetModule);
   this.targetDisplayedGem = targetDisplayedGem;
 }
 /**
  * Determine if the current target Gem has any arguments.
  *
  * @return boolean whether the current target has any arguments.
  */
 private boolean targetHasArgs() {
   return (!targetDisplayedGem.getTargetArguments().isEmpty());
 }
  /**
   * Returns whether the target's output type can be handled.
   *
   * @return boolean
   */
  private boolean targetHasHandleableOutput() {

    TypeExpr outputTypeExpr = targetDisplayedGem.getGem().getResultType();
    return ValueNodeBuilderHelper.canHandleOutput(outputTypeExpr);
  }