public static ForwardChainingIndex createForwardChainingIndex(Proposition goal, Proposition masterforall) {
    { ForwardChainingIndex index = ForwardChainingIndex.newForwardChainingIndex();
      KeyValueMap mapping = KeyValueMap.newKeyValueMap();
      Proposition forallcopy = Proposition.copyProposition(masterforall, mapping);
      Stella_Object goalcopy = mapping.lookup(goal);

      forallcopy = Proposition.substituteProposition(forallcopy, ((Proposition)(goalcopy)), Logic.TRUE_PROPOSITION);
      { Vector iovariables = ((Vector)(KeyValueList.dynamicSlotValue(forallcopy.dynamicSlots, Logic.SYM_LOGIC_IO_VARIABLES, null)));
        Cons iovariablenames = null;
        List goalvariablelist = List.list(Stella.NIL);
        Cons goalvariablenames = Stella.NIL;
        Cons existvariablenames = Stella.NIL;
        Cons querybody = null;
        Cons consequenttree = null;

        { Cons value000 = null;
          Stella_Object value001 = null;
          Cons value002 = null;

          { Object [] caller_MV_returnarray = new Object[2];

            value000 = Logic.deconstructForallTree(((Cons)(Proposition.generateProposition(forallcopy))), caller_MV_returnarray);
            value001 = ((Stella_Object)(caller_MV_returnarray[0]));
            value002 = ((Cons)(caller_MV_returnarray[1]));
          }
          {
            iovariablenames = value000;
            querybody = ((Cons)(value001));
            consequenttree = value002;
          }
        }
        Logic.collectFreeVariables(goal, goalvariablelist, List.list(Stella.NIL), List.list(Stella.NIL));
        { Cons value003 = Stella.NIL;

          { Stella_Object arg = null;
            Cons iter000 = goalvariablelist.theConsList;
            Cons collect000 = null;

            for (;!(iter000 == Stella.NIL); iter000 = iter000.rest) {
              arg = iter000.value;
              if (collect000 == null) {
                {
                  collect000 = Cons.cons(((PatternVariable)(arg)).skolemName, Stella.NIL);
                  if (value003 == Stella.NIL) {
                    value003 = collect000;
                  }
                  else {
                    Cons.addConsToEndOfConsList(value003, collect000);
                  }
                }
              }
              else {
                {
                  collect000.rest = Cons.cons(((PatternVariable)(arg)).skolemName, Stella.NIL);
                  collect000 = collect000.rest;
                }
              }
            }
          }
          goalvariablenames = value003;
        }
        { Stella_Object v = null;
          Cons iter001 = iovariablenames;
          int i = Stella.NULL_INTEGER;
          int iter002 = 0;
          Cons collect001 = null;

          for (;!(iter001 == Stella.NIL); iter001 = iter001.rest, iter002 = iter002 + 1) {
            v = iter001.value;
            i = iter002;
            if (!Stella_Object.searchConsTreeP(consequenttree, v)) {
              (iovariables.theArray)[i] = null;
              if (collect001 == null) {
                {
                  collect001 = Cons.cons(v, Stella.NIL);
                  if (existvariablenames == Stella.NIL) {
                    existvariablenames = collect001;
                  }
                  else {
                    Cons.addConsToEndOfConsList(existvariablenames, collect001);
                  }
                }
              }
              else {
                {
                  collect001.rest = Cons.cons(v, Stella.NIL);
                  collect001 = collect001.rest;
                }
              }
            }
          }
        }
        iovariablenames = iovariablenames.subtract(existvariablenames);
        iovariables = Logic.removeNullsInVariablesVector(iovariables);
        KeyValueList.setDynamicSlotValue(forallcopy.dynamicSlots, Logic.SYM_LOGIC_IO_VARIABLES, iovariables, null);
        index.consequent = Proposition.constructDescriptionFromForallProposition(forallcopy, Logic.KWD_HEAD);
        existvariablenames = existvariablenames.subtract(goalvariablenames);
        if (!(existvariablenames == Stella.NIL)) {
          querybody = Cons.list$(Cons.cons(Logic.SYM_STELLA_EXISTS, Cons.cons(existvariablenames, Cons.cons(Cons.cons(querybody, Stella.NIL), Stella.NIL))));
        }
        iovariablenames = goalvariablenames.concatenate(iovariablenames, Stella.NIL);
        index.ioVariables = iovariablenames;
        index.queryBody = querybody;
        { Cons value004 = Stella.NIL;

          { Stella_Object v = null;
            Cons iter003 = iovariablenames;
            Cons collect002 = null;

            for (;!(iter003 == Stella.NIL); iter003 = iter003.rest) {
              v = iter003.value;
              if (v != null) {
                if (collect002 == null) {
                  {
                    collect002 = Cons.cons(null, Stella.NIL);
                    if (value004 == Stella.NIL) {
                      value004 = collect002;
                    }
                    else {
                      Cons.addConsToEndOfConsList(value004, collect002);
                    }
                  }
                }
                else {
                  {
                    collect002.rest = Cons.cons(null, Stella.NIL);
                    collect002 = collect002.rest;
                  }
                }
              }
            }
          }
          index.inputBindings = value004;
        }
      }
      index.forwardGoal = goal;
      index.masterRule = masterforall;
      index.cacheId = Stella.gensym("FWD-QUERY");
      return (index);
    }
  }