public static Description copyDescription(Description self, KeyValueMap parentmapping, boolean addbacklinksP) {
    { Object old$Context$000 = Stella.$CONTEXT$.get();
      Object old$Module$000 = Stella.$MODULE$.get();

      try {
        Native.setSpecial(Stella.$CONTEXT$, self.homeContext);
        Native.setSpecial(Stella.$MODULE$, ((Context)(Stella.$CONTEXT$.get())).baseModule);
        { Description copy = Logic.createDescription(Stella.NULL_INTEGER, false);
          KeyValueMap mapping = KeyValueMap.newKeyValueMap();

          if (parentmapping != null) {
            { Stella_Object k = null;
              Stella_Object v = null;
              DictionaryIterator iter000 = ((DictionaryIterator)(parentmapping.allocateIterator()));

              while (iter000.nextP()) {
                k = iter000.key;
                v = iter000.value;
                if (Stella_Object.isaP(k, Logic.SGT_LOGIC_PATTERN_VARIABLE)) {
                  mapping.insertAt(k, v);
                }
              }
            }
          }
          copy.ioVariables = Logic.copyVariablesVector(self.ioVariables, mapping);
          copy.internalVariables = Logic.copyVariablesVector(self.internalVariables, mapping);
          if (((Vector)(KeyValueList.dynamicSlotValue(self.dynamicSlots, Logic.SYM_LOGIC_EXTERNAL_VARIABLES, null))) != null) {
            { Cons value000 = Stella.NIL;

              { PatternVariable var = null;
                Vector vector000 = ((Vector)(KeyValueList.dynamicSlotValue(self.dynamicSlots, Logic.SYM_LOGIC_EXTERNAL_VARIABLES, null)));
                int index000 = 0;
                int length000 = vector000.length();
                Cons collect000 = null;

                for (;index000 < length000; index000 = index000 + 1) {
                  var = ((PatternVariable)((vector000.theArray)[index000]));
                  if ((mapping.lookup(var) == null) ||
                      Logic.variableP(mapping.lookup(var))) {
                    if (collect000 == null) {
                      {
                        collect000 = Cons.cons(var, Stella.NIL);
                        if (value000 == Stella.NIL) {
                          value000 = collect000;
                        }
                        else {
                          Cons.addConsToEndOfConsList(value000, collect000);
                        }
                      }
                    }
                    else {
                      {
                        collect000.rest = Cons.cons(var, Stella.NIL);
                        collect000 = collect000.rest;
                      }
                    }
                  }
                }
              }
              { Cons realexternalvars = value000;
                Vector externalvarscopy = null;

                if (((Vector)(KeyValueList.dynamicSlotValue(self.dynamicSlots, Logic.SYM_LOGIC_EXTERNAL_VARIABLES, null))).length() == realexternalvars.length()) {
                  externalvarscopy = Logic.copyVariablesVector(((Vector)(KeyValueList.dynamicSlotValue(self.dynamicSlots, Logic.SYM_LOGIC_EXTERNAL_VARIABLES, null))), mapping);
                }
                else {
                  if (!(realexternalvars == Stella.NIL)) {
                    externalvarscopy = Logic.copyVariablesVector(Logic.copyConsListToVariablesVector(realexternalvars), mapping);
                  }
                }
                KeyValueList.setDynamicSlotValue(copy.dynamicSlots, Logic.SYM_LOGIC_EXTERNAL_VARIABLES, externalvarscopy, null);
              }
            }
          }
          if (self.proposition != null) {
            { Object old$Boundtooffsetcounter$000 = Logic.$BOUNDTOOFFSETCOUNTER$.get();
              Object old$Evaluationmode$000 = Logic.$EVALUATIONMODE$.get();

              try {
                Native.setIntSpecial(Logic.$BOUNDTOOFFSETCOUNTER$, Stella.NULL_INTEGER);
                Native.setSpecial(Logic.$EVALUATIONMODE$, Logic.KWD_DESCRIPTION);
                copy.proposition = (addbacklinksP ? Proposition.recursivelyFastenDownPropositions(Proposition.copyProposition(self.proposition, mapping), false) : Proposition.copyProposition(self.proposition, mapping));

              } finally {
                Logic.$EVALUATIONMODE$.set(old$Evaluationmode$000);
                Logic.$BOUNDTOOFFSETCOUNTER$.set(old$Boundtooffsetcounter$000);
              }
            }
          }
          if (((BooleanWrapper)(KeyValueList.dynamicSlotValue(self.dynamicSlots, Logic.SYM_LOGIC_DONT_OPTIMIZEp, Stella.FALSE_WRAPPER))).wrapperValue) {
            KeyValueList.setDynamicSlotValue(copy.dynamicSlots, Logic.SYM_LOGIC_DONT_OPTIMIZEp, Stella.TRUE_WRAPPER, Stella.FALSE_WRAPPER);
          }
          mapping.free();
          return (copy);
        }

      } finally {
        Stella.$MODULE$.set(old$Module$000);
        Stella.$CONTEXT$.set(old$Context$000);
      }
    }
  }