public static int propositionHashIndex(Proposition self, KeyValueMap mapping, boolean derefsurrogatesP) {
    { boolean mappedP = mapping != null;
      int code = (self.operator).hashCode();
      Vector arguments = self.arguments;
      Stella_Object functionoutput = ((mappedP &&
          (self.kind == Logic.KWD_FUNCTION)) ? arguments.last() : ((Stella_Object)(null)));
      Stella_Object priorarg = null;
      int argcode = 0;
      boolean commutativeP = false;

      { Keyword testValue000 = self.kind;

        if ((testValue000 == Logic.KWD_AND) ||
            ((testValue000 == Logic.KWD_OR) ||
             (testValue000 == Logic.KWD_EQUIVALENT))) {
          commutativeP = true;
        }
        else {
        }
      }
      { Stella_Object arg = null;
        Vector vector000 = arguments;
        int index000 = 0;
        int length000 = vector000.length();

        for (;index000 < length000; index000 = index000 + 1) {
          arg = (vector000.theArray)[index000];
          if (mappedP) {
            if (Stella_Object.eqlP(arg, functionoutput)) {
              arg = null;
            }
            else {
              arg = Logic.mappedValueOf(arg, mapping, false);
            }
          }
          if ((((QueryIterator)(Logic.$QUERYITERATOR$.get())) != null) &&
              Logic.variableP(arg)) {
            { Stella_Object temp000 = PatternVariable.safeBoundTo(((PatternVariable)(arg)));

              arg = ((temp000 != null) ? temp000 : arg);
            }
          }
          if (arg == null) {
            argcode = Logic.SGT_LOGIC_SKOLEM.hashCode();
          }
          else {
            { Surrogate testValue001 = Stella_Object.safePrimaryType(arg);

              if (Surrogate.subtypeOfP(testValue001, Logic.SGT_LOGIC_PROPOSITION)) {
                { Proposition arg000 = ((Proposition)(arg));

                  argcode = Proposition.propositionHashIndex(arg000, mapping, derefsurrogatesP);
                }
              }
              else if (Surrogate.subtypeOfP(testValue001, Logic.SGT_LOGIC_NAMED_DESCRIPTION)) {
                { NamedDescription arg000 = ((NamedDescription)(arg));

                  argcode = arg000.hashCode();
                }
              }
              else if (Surrogate.subtypeOfP(testValue001, Logic.SGT_LOGIC_DESCRIPTION)) {
                { Description arg000 = ((Description)(arg));

                  argcode = Proposition.propositionHashIndex(arg000.proposition, mapping, derefsurrogatesP);
                }
              }
              else if (Surrogate.subtypeOfP(testValue001, Logic.SGT_LOGIC_PATTERN_VARIABLE)) {
                { PatternVariable arg000 = ((PatternVariable)(arg));

                  argcode = Logic.SGT_LOGIC_PATTERN_VARIABLE.hashCode();
                }
              }
              else if (Surrogate.subtypeOfP(testValue001, Logic.SGT_LOGIC_SKOLEM)) {
                { Skolem arg000 = ((Skolem)(arg));

                  { Proposition definingprop = arg000.definingProposition;

                    if ((definingprop != null) &&
                        (!(definingprop == self))) {
                      argcode = Proposition.propositionHashIndex(definingprop, mapping, derefsurrogatesP);
                    }
                    else {
                      argcode = Logic.SGT_LOGIC_SKOLEM.hashCode();
                    }
                  }
                }
              }
              else if (Surrogate.subtypeOfSurrogateP(testValue001)) {
                { Surrogate arg000 = ((Surrogate)(arg));

                  if (derefsurrogatesP) {
                    arg000 = ((Surrogate)(arg000.surrogateValue));
                  }
                  argcode = arg000.hashCode_();
                }
              }
              else if (Surrogate.subtypeOfWrapperP(testValue001)) {
                { Wrapper arg000 = ((Wrapper)(arg));

                  argcode = arg000.hashCode_();
                }
              }
              else {
                argcode = arg.hashCode();
              }
            }
          }
          if ((priorarg == null) ||
              ((!commutativeP) ||
               Stella_Object.eqlP(arg, priorarg))) {
            code = (((code & 1) == 0) ? (code >>> 1) : (((code >> 1)) | Stella.$INTEGER_MSB_MASK$));
          }
          code = (code ^ argcode);
          priorarg = arg;
        }
      }
      return (code);
    }
  }