public static List computeStructuralFunctionEvaluationOrder(Description self) {
    { List structuralfunctions = List.newList();
      Vector iovariables = self.ioVariables;
      Vector internalvariables = self.internalVariables;
      HashSet candidates = HashSet.newHashSet();
      HashSet unboundinternals = HashSet.newHashSet();
      List sortedfunctions = List.newList();
      boolean progressP = true;

      Proposition.collectStructuralFunctions(self.proposition, structuralfunctions);
      { Proposition function = null;
        Cons iter000 = structuralfunctions.theConsList;

        for (;!(iter000 == Stella.NIL); iter000 = iter000.rest) {
          function = ((Proposition)(iter000.value));
          if (iovariables.memberP((function.arguments.theArray)[(function.arguments.length() - 1)]) ||
              internalvariables.memberP((function.arguments.theArray)[(function.arguments.length() - 1)])) {
            candidates.insert(function);
          }
        }
      }
      { PatternVariable var = null;
        Vector vector000 = internalvariables;
        int index000 = 0;
        int length000 = vector000.length();

        for (;index000 < length000; index000 = index000 + 1) {
          var = ((PatternVariable)((vector000.theArray)[index000]));
          unboundinternals.insert(var);
        }
      }
      while (progressP) {
        progressP = false;
        { Proposition candidate = null;
          DictionaryIterator iter001 = ((DictionaryIterator)(candidates.allocateIterator()));

          while (iter001.nextP()) {
            candidate = ((Proposition)(iter001.value));
            { boolean testValue000 = false;

              testValue000 = !unboundinternals.memberP((candidate.arguments.theArray)[(candidate.arguments.length() - 1)]);
              if (testValue000) {
                { boolean alwaysP000 = true;

                  { Stella_Object arg = null;
                    Vector vector001 = candidate.arguments;
                    int index001 = 0;
                    int length001 = vector001.length();
                    int i = Stella.NULL_INTEGER;
                    int iter002 = 2;
                    int upperBound000 = candidate.arguments.length();

                    loop004 : for (;(index001 < length001) &&
                              (iter002 <= upperBound000); index001 = index001 + 1, iter002 = iter002 + 1) {
                      arg = (vector001.theArray)[index001];
                      i = iter002;
                      if (!(!unboundinternals.memberP(arg))) {
                        alwaysP000 = false;
                        break loop004;
                      }
                    }
                  }
                  testValue000 = alwaysP000;
                }
              }
              if (testValue000) {
                sortedfunctions.push(candidate);
                candidates.remove(candidate);
                progressP = true;
              }
            }
          }
        }
        { Proposition candidate = null;
          DictionaryIterator iter003 = ((DictionaryIterator)(candidates.allocateIterator()));

          while (iter003.nextP()) {
            candidate = ((Proposition)(iter003.value));
            { boolean alwaysP001 = true;

              { Stella_Object arg = null;
                Vector vector002 = candidate.arguments;
                int index002 = 0;
                int length002 = vector002.length();
                int i = Stella.NULL_INTEGER;
                int iter004 = 2;
                int upperBound001 = candidate.arguments.length();

                loop006 : for (;(index002 < length002) &&
                          (iter004 <= upperBound001); index002 = index002 + 1, iter004 = iter004 + 1) {
                  arg = (vector002.theArray)[index002];
                  i = iter004;
                  if (!(!unboundinternals.memberP(arg))) {
                    alwaysP001 = false;
                    break loop006;
                  }
                }
              }
              if (alwaysP001) {
                sortedfunctions.push(candidate);
                candidates.remove(candidate);
                unboundinternals.remove(((PatternVariable)((candidate.arguments.theArray)[(candidate.arguments.length() - 1)])));
                progressP = true;
              }
            }
          }
        }
      }
      return (sortedfunctions.reverse());
    }
  }