Package PrologPlusCG.prolog

Source Code of PrologPlusCG.prolog.Resolution

/**********************************************************************
*
* Prolog+CG : Prolog with conceptual graphs
*
* Copyright (C) 2000-2005  Adil Kabbaj
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*
* Website
* =======
*
* Prolog+CG has a website here:
*
* http://prologpluscg.sourceforge.net/
*
*
* Contact
* =======
*
* Please DO NOT send email to Prof. Kabbaj.  Instead, all
* correspondence regarding Prolog+CG should be sent to the current
* maintainter:
*
* Ulrik Petersen  <ulrikp{t-a}users{dot}sourceforge{|dot|}net
*
* (Email obfuscated to foil spammers).
*
*
* NO SUPPORT
* ==========
*
* Note that NEITHER Prof. KABBAJ NOR ULRIK PETERSEN WILL GIVE
* SUPPORT!  No support is available.
*
* If you need help in using Prolog+CG, please check out the resources
* available at:
*
* http://prologpluscg.sourceforge.net/docs.html
*
* That page points to ample resources for learning Prolog+CG.
*
*
* Bugreports
* ==========
*
* Notwithstanding the lack of support, the maintainer will gladly
* receive bugreports and bugfixes.  Please feel free to send such
* bulletins to the address given above.
*
*
*/

package PrologPlusCG.prolog;

import java.lang.reflect.*;
import java.util.*;

import PrologPlusCG.cg.CG;
import PrologPlusCG.cg.CGMatchResult;
import PrologPlusCG.cg.CGOperation;
import PrologPlusCG.cg.Concept;
import PrologPlusCG.cg.Relation;

public class Resolution extends Thread implements DataTypes {
  ResolutionStack Exec_Stack = new ResolutionStack(); // Stack of
                            // TermToBeResolved
  ResolutionStack Return_Stack = new ResolutionStack(); // Stack of
                              // TermToBeResolved
  RuleVector pRules = null;
  // Hashtable globalPrlgPCGMM = new Hashtable(); // Not used
  Hashtable<String, PrologData> globalPrlgPCGObjs = new Hashtable<String, PrologData>();
  Random rndRandom = new Random();
  boolean programModified = false;
  int cptVarBid = 0;
  final String strEndOfPredefinedGoals = "$!$End%dnE$!$";
  final String[] PredefinedGoals = { "not", "findall", "/", "member",
      "length", "read", "read_sentence", "write", "writenl", "nl",
      "clearConsole", "asserta", "assertz", "retract", "suppress",
      "term_list", "free", "val", "sup", "inf", "eqv", "eq", "add",
      "sub", "mul", "dif", "div", "rnd", "seed", "concat",
      "stringToLetters", "identToLetters", "isSubType", "isSuperType",
      "subTypes", "superTypes", "minComSuperTypes", "minComSuperType",
      "maximalJoin", "generalize", "subsume", "addElemForAll",
      "createInstance", "fail", "concOfCG", "immediateSubTypes",
      "immediateSuperTypes", "exec", "execAndWait", "execMethod", "new",
      "destroy", "destroyAll", "get", "set", "set_list", "branchOfCG",
      "isInstance", "addInstance", "maxComSubTypes", "maxComSubType",
      "objectify", "shuffle",
      strEndOfPredefinedGoals };
  boolean bResolveWithInterface = true;

  private PPCGEnv env = null;

  public Resolution(PPCGEnv myenv, boolean mode) {
    env = myenv;
    bResolveWithInterface = mode;

    // Creation de la branche cadre ; elle sert pour la primitive branchOfCG
    // comme cela, on evitera de creer un CG a chaque iteration ...
    // La meme branchCadre sera utilise pour toutes les iterations
    // A tout moment on va la remplir
  }

  public void run() {
    if (bResolveWithInterface) {
      try {
        env.io.showWaitCursor();
        executeQuery();
      } catch (CompileException cpleExc) {
        env.io.showMessageDialog(cpleExc.getMessage(), "Warning");
      } catch (ExecException eexec) {
        if (eexec.getMessage().equals("program null")) {
          env.io.showMessageDialog(
              "Please, Compile your program first.", "Warning");
        } else {
          env.io.appendToConsole(eexec.getMessage() + "\n");
        }
      }

      env.io.showNormalCursor();

      env.io.showPrompt();
    } else { // Indirect resolution; without interface
      try {
        executeQuery();
      } catch (CompileException cpleExc) {
        String strMsg = "Compiler Warning : " + cpleExc.getMessage();
        if (env.bIsApplet) {
          env.recordErrorMessage(strMsg);
        } else {
          System.out.println(strMsg);
        }
      } catch (ExecException eexec) {
        String strMsg = "Execution Warning : " + eexec.getMessage();
        if (env.bIsApplet) {
          env.recordErrorMessage(strMsg);
        } else {
          System.out.println(strMsg);
        }
      }
    }
  }

  // The question has been compiled and its internal representation
  // can be found in pCurRule
  public void executeQuery() throws ExecException, CompileException {
    // The procedure of resolution.
    // The heart of the interpreter.
    boolean package_is_known = false;
    boolean unifiable = false;
    PrologDataIndexPair contr = null;
    TermToBeResolved TermRes = null;
    cptVarBid = 0; // Initialiser a 0 pour chaque nouvelle question

    env.unification.Unif_Stack.makeEmpty();
    Exec_Stack.makeEmpty();
    Return_Stack.makeEmpty();

    // Le niveau 0 ou on y mettra les variables de la question
    // Level 0, where one will put the variables of the question.
    env.unification.Unif_Stack.pushEmptyRecord();

    // Push dans Exec_Stack les buts de
    // la question. -1 car rien n'est dans la pile a ce stade
    // et une resatisfaction d'un cut dans la question implique l'arret
    // de la resolution.

    // Push the goals of the question onto Exec_Stack. -1 because
    // nothing is on the stack at this stage, and a resatisfaction
    // of a cut in a question implies a stop of the resolution.
    push_tail(env.pCurRule, 0, 0, -1);

    // Free the variable "env.pCurRule"
    env.pCurRule.removeAllElements();
    env.pCurRule = null;

    boolean finished = false;
    boolean solvable = false;
    programModified = false;

    while (!finished && !env.bStopExec) {
      // Fetch all the possible solutions to the question
      while (!Exec_Stack.isEmpty() && !env.bStopExec) {
        // Chercher une solution : Effacer ; r?soudre tous les buts
        // empiler dans la pile d'exec.

        // Fetch a solution: Erase; solve all the goals stacked up
        // in the Exec_Stack (Stack_Exec)

        // Consult the element at the top
        TermRes = Exec_Stack.getTop();

        // sans l'enlever de la pile
        unifiable = false;
        package_is_known = (TermRes.pos != 0);

        String IdVar = variable_goal(TermRes.pTerm);

        if (IdVar != null) {
          // package_is_known => une resatisfaction ; le paquet pour
          // le but
          // a t dj identifi.
          // c'est le cas o? le but est ? satisfaire pour la 1re fois
          // ET le but est une variable.
          // traiter comme si on a la r?gle : Var :- ValVar.
          // la variable ne doit pas etre remplacee definitivement par
          // sa valeur ; un retour-arriere peut amener une autre val.
          // pour la Var.
          if (!package_is_known) {
            PrologData valButVar = new PrologData(uVariable, IdVar);
            contr = env.unification.valueFromUnifStack(valButVar,
                TermRes.index);
            valButVar = null;

            if ((contr.pData == null)
                || ((contr.pData.typeOfData != uTerm) && (contr.pData.typeOfData != uCG))) {
              throw new ExecException("Error: The variable goal "
                  + IdVar
                  + " is free or it is not a term nor a CG. ");
            }

            if (contr.pData.typeOfData == uCG) {
              PrologTerm aTerm = new PrologTerm();
              aTerm.addData(contr.pData);
              contr.pData = new PrologData(uTerm, aTerm);
            }

            // Because the second round will pop an element
            // from Unif_Stack.
            env.unification.Unif_Stack.pushEmptyRecord();
            // The goal-variable is considered
            TermRes.indexInExecStack = Exec_Stack.indexOfTop();

            // alors comme un but defini qui sera remplace
            // par sa queue, suite a un retour arriere, tout
            // ce qui est relatif a cette queue devrait etre
            // elimine de la Exec_Stack on ne peut resatisfaire
            // un but-var, il faut poursuivre le retour-arriere

            // Then, as a definite goal which will be replaced
            // by its tail after a second round, all that
            // is relative to this tail will be eliminated
            // from Exec_Stack, one cannot resatisfy a
            // variable-goal, it is necessary to continue
            // the back-return. (BAAAD translation!)
            TermRes.pos = -1;

            // comme pour le cas de plusieurs buts primitifs
            // on depile le but var et on l'empile dans Return_Stack
            Return_Stack.push(Exec_Stack.pop());
            TermRes = new TermToBeResolved(
                (PrologTerm) contr.pData.data, contr.index, 0);
            Exec_Stack.push(TermRes); // et on empile cette valeur
                          // dans Exec_Stack (voir
                          // commentaire au debut de
                          // ce cas)

            IdVar = null; // pour rentrer dans le prochain if (IdVar
                    // == null) {..
          } else {
            TermRes.pos = 0; // suite au retour arriere, il faut
                      // laisser le but dans Exec_Stack
          }

          // et on aurait unifiable = false; incitant un retour
          // arriere .. comme pour un but non satisfait
        }

        // Is it a variable?
        if (IdVar == null) {
          // No, it isn't a variable.
          String IdPred = null;

          // Check whether this is an identifier
          if (TermRes.pTerm.getAt(0).typeOfData == uIdentifier) {
            // It was. Get its name
            IdPred = (String) TermRes.pTerm.getAt(0).data;
          }

          // Is it an identifier AND a predefined goal?
          if ((IdPred != null) && identifierIsPredefinedGoal(IdPred)) {
            // Yes, it was both an identifier
            // and a predefined goal.
            if (!package_is_known) {
              // The predefined goal is being met
              // for the first time.
              unifiable = satisfyPredicateGoal(TermRes, IdPred);
            } else {
              // The goal is to be resatisfied:
              // Is it finished or not?
              unifiable = resatisfyPredicateGoal(TermRes, IdPred);
            }
          } else {
            // The goal is not predefined, or it was not
            // an identifier, or both
            pRules = null;

            try {
              if (!package_is_known && (TermRes.pos > -1)) {
                // It is to be satisfied for the first time.

                // Localiser un paquet pour le but courant
                TermRes.Cle = env.compile.nameOfArgument(
                    TermRes.pTerm, TermRes.index);

                if (env.program.containsKey(TermRes.Cle)) {
                  // Il existe un paquet pour le but courant
                  // There exists a package
                  // for the current goal
                  pRules = (RuleVector) env.program
                      .get(TermRes.Cle);
                } else {
                  TermRes.pos = -2;

                  // depiler le but qui ne peut etre
                  // resolu ? :
                  // Exec_Stack.Pop();
                  // NON, il faut le laisser pour
                  // le satisfaire de nouveau suite a une
                  // resatisfaction des buts anterieurs
                }
              } else if (TermRes.pos > -1) {
                // .. il est ? resatisfaire => on
                // re-localise le paqute

                // It is to be resatisfied. That means,
                // we need to relocate the package.

                // et TermRes.Pos contient dj le pointeur
                // sur la prochaine r?gle du paquet
                // considrer.

                // And TermRes.Pos already contains the
                // pointer to the next rule to be
                // considered.
                pRules = (RuleVector) env.program
                    .get(TermRes.Cle);
              }
            } catch (NullPointerException ex) {
              if (env.program == null) {
                env.io
                    .showMessageDialog(
                        "No program has been loaded and compiled.\n Only predefined goal (except asserta/z, createInstance, \n retract and suppress) can be satisfied.",
                        "Warning");
                TermRes.pos = -1;
                Return_Stack.makeEmpty();
              }
            }
            IdPred = null;

            // int ancVal_TermResPos = TermRes.Pos;
            unifiable = isUnifiable(TermRes);

            if (!unifiable
                && (TermRes.pos != -1)
                && TermRes.Cle
                    .startsWith(env.compile.valSysCleBtCp)
                && (TermRes.Cle.length() != env.compile.valSysCleBtCp
                    .length())) { // il s'agit donc de
                            // B1::B2 et B1 est un
                            // term

              // 1. Chercher la regle de generalisation, si elle
              // existe,
              // pour cela, il faut determiner la cle de la regle
              // : valSysGEN + la signature
              // du but-term en question (voir la classe Compile)
              String ClePaquet = env.compile.valSysGEN
                  + TermRes.Cle
                      .substring(env.compile.valSysCleBtCp
                          .length());

              if (env.program.containsKey(ClePaquet)) {
                // localiser la regle de generalisation t1::x <-
                // t2::x, en tenant compte de la cle calculee
                RuleVector regles = (RuleVector) env.program
                    .get(ClePaquet);

                // 2. Unifier le but B1::B2 avec la tete t1::x
                // de la regle de generalisation
                env.unification.Unif_Stack.pushEmptyRecord(); // Push
                                        // la
                                        // structure
                                        // qui

                int TopOfUnification_Stack = env.unification.Unif_Stack
                    .indexOfTop();
                PrologData DonCple1 = new PrologData(uTerm,
                    TermRes.pTerm);
                PrologData DonCple2 = new PrologData(uTerm,
                    regles.getAt(0).getAt(0));
                unifiable = env.unification.unify(DonCple2,
                    TopOfUnification_Stack, DonCple1,
                    TermRes.index);

                if (unifiable) {
                  TermRes.indexInExecStack = Exec_Stack
                      .indexOfTop();
                  TermRes.pos = -1;
                  Return_Stack.push(Exec_Stack.pop());

                  // Push dans Exec_Stack un nouveau TermRes
                  // avec comme term t2::x; le membre droit de
                  // la regle de generalisation
                  Exec_Stack.push(new TermToBeResolved(regles
                      .getAt(0).getAt(1),
                      TopOfUnification_Stack, 0));
                } else {
                  env.unification.Unif_Stack.pop();
                  TermRes.pos = 0;
                }
              } else {
                TermRes.pos = 0; // dans le cas ou il n'y a pas
                          // de regle de
                          // generalisation
              }
            } else if (!unifiable) {
              // The current goal, including an unknown goal,
              // is left in Exec_Stack.

              // The goal is left in Exec_Stack with
              // TermRes.Pos = 0
              TermRes.pos = 0;
            }

            // Hoping that a resatisfaction of the preceding goal
            // could imply a satisfaction of the goal.
          } // end of else : The goal is not predefined, or
          // it is not an identifier, or both
        }

        if (!unifiable && theGoalBelowOnTheStackIsNot()) {
          Exec_Stack.pop(); // Depiler But de not(But) qui se trouvera
                    // alors au sommet de Exec_Stack

          TermToBeResolved unTermRes = Exec_Stack.getTop(); // unTermRes
                                    // contient
                                    // not(But)
          unTermRes.pos = -2;
          unTermRes.indexInExecStack = -1;
          env.unification.Unif_Stack.pushEmptyRecord(); // juste pour
                                  // garder
                                  // l'equilibre
                                  // car elle
                                  // sera
                                  // depile
                                  // lors d'un
                                  // retour-arriere
          Return_Stack.push(Exec_Stack.pop());
          unifiable = true;
        }

        if (!unifiable && Return_Stack.isEmpty()) {
          // rsolution du but courant
          // a chou et pile_retour_arriere est vide
          // => resolution terminee

          // Resolution of current goal failed, and
          // Return_Stack is empty.
          // => Resoultion has finished.
          Exec_Stack.makeEmpty(); // MakeEmpty le Exec_Stack
          env.unification.Unif_Stack.makeEmpty();

          if (!solvable) {
            if (bResolveWithInterface) {
              env.io.appendToConsole(" no.\n"); // on n'imprime
                                // pas no. s'il
                                // y avait des
                                // solutions
            } else {
              env.vctResult = null;
            }
          }

          env.compile.vctVariableIdentifiersInQuery
              .removeAllElements();
          finished = true;
        } else if (!unifiable) {
          // We could not unify, but Return_Stack was
          // NOT empty.

          // Le but courant B n'est pas satisfait,
          // The current goal B isn't satisfied
          backTrack();
        }
      } // fin de : while (! Exec_Stack.IsEmpty() ...)

      if (!Return_Stack.isEmpty() && !env.bStopExec) {
        // Print the result of the found answer and initialize
        // things for doing one more round, to fetch
        // another solution.
        solvable = true;
        env.printer.writeOrRecordResult(!env.bIsApplet);
        backTrack();
        if (!Exec_Stack.isEmpty()) {
          TermRes = Exec_Stack.getTop();
        }
      } else {
        finished = true;
      }
    } // fin de while (!finished) {...}

    env.unification.Unif_Stack.makeEmpty();

    if (env.bStopExec) {
      Exec_Stack.makeEmpty();
      Return_Stack.makeEmpty();
      env.bStopExec = false;
    }

    if (programModified) {
      env.bWriteToDebugTree = true;
      env.printer.alternatePrintString = "";
      env.printer.printPrologProgram(); // Ecriture dans
                        // alternatePrintString
      env.io.setProgramText(env.printer.alternatePrintString);
      env.printer.alternatePrintString = "";
      env.bWriteToDebugTree = false;
    }
  } // fin de ExecQuest ; l'interpreteur

  boolean isUnifiable(TermToBeResolved TermRes) throws ExecException {
    boolean unifiable = false;
    // Initialize to -3
    int taillePaq = -3;
    PrologData Donnee1 = null;

    if (TermRes.pos > -1) {
      taillePaq = pRules.size();
      Donnee1 = new PrologData(uTerm, TermRes.pTerm);
    }

    PrologRule pRegleLocal;

    while ((TermRes.pos < taillePaq) && (!unifiable)) {
      // parcourir le paquet courant pour localiser une r?gle
      // dont la t?te puisse s'unifier avec le but courant
      pRegleLocal = pRules.getAt(TermRes.pos);
      TermRes.pos++;

      // Preparer l'unification du but courant avec la tete
      // de la rgle courante pRegleLocal

      // Push la structure qui
      // recevra le vctResult de l'unification.

      // Prepare the unification of the current goal with the
      // head of the current rule pRegleLocal.

      // Push the structure which will receive the vctResult
      // of the unification.
      env.unification.Unif_Stack.pushEmptyRecord();
      int TopOfUnification_Stack = env.unification.Unif_Stack
          .indexOfTop();
      PrologData Donnee2 = new PrologData(uTerm, pRegleLocal.getAt(0));

      // unifier la tete de la regle choisie avec le term de la pileExec
      // unifier tient compte des indices de chaque term
      unifiable = env.unification.unify(Donnee2, TopOfUnification_Stack,
          Donnee1, TermRes.index);
      Donnee2 = null;

      if (unifiable) {
        // La tte de la rgle courante est unifiable :
        // Effectuer les trois actions de base de l'interp. :

        // memoriser la place du but dans Exec_Stack, pour qu'apres
        // un retour-arriere, on elimine de Exec_Stack tout ce
        // qui est relatif a la queue de la regle qui avait servie
        // pour la derniere satisfaction. On se retrouve ainsi
        // juste a l'etat avant la satisfaction du but.

        // Store the place of the goal in Exec_Stack, so that,
        // after a return-back, one can eliminate from Exec_Stack
        // all that which is relative to the tail of the rule
        // which had been useful for the last satisfaction.
        // One thus finds oneself just at the state before
        // the satisfaction of the goal.
        TermRes.indexInExecStack = Exec_Stack.indexOfTop();

        // The element popped off Exec_Stack is pushed onto
        // Return_Stack.
        Return_Stack.push(Exec_Stack.pop());
        push_tail(pRegleLocal, 1, TopOfUnification_Stack, Return_Stack
            .indexOfTop());

        // indice pour la tte de la regle vaut aussi pour sa queue
        // le 3 arg. sert a grer le cas du cut "/"
      } else {
        env.unification.Unif_Stack.pop(); // Eliminer de la pile
      }

      // d'unification la structure qui a ?t? utilis?e pour cet essai
      // ?chou?.
    } // fin de : while ((TermRes.Pos <= taillePaq) && (!unifiable))...

    pRegleLocal = null;
    Donnee1 = null;

    return unifiable;
  }

  public void backTrack() {
    TermToBeResolved TermRes = Return_Stack.getTop();
    String idPred = null;

    // If it is an identifier, get its identifier string in idPred
    if (TermRes.pTerm.getAt(0).typeOfData == uIdentifier) {
      idPred = (String) TermRes.pTerm.getAt(0).data;
    }

    // Is it a cut?
    if ((idPred != null) && idPred.equals("/")) {
      // Yes, it is a cut.

      // .. couper le retour-arri?re.

      // Cut the return-back (retour-arriere)

      // TermRes.Index represente dans ce cas l'indice
      // ds Return_Stack pour le term Tr
      // dont la regle empilee contient le cut.

      // TermRes.Index represents, in this case, the index
      // into Return_Stack for the term Tr,
      // whose pushed rule contains the cut.
      for (int i = Return_Stack.indexOfTop(); ((i > TermRes.index) && (i >= 0)); i--) {
        Return_Stack.pop(); // en depilant (afin de ne plus les
                  // considerer) les TermRes de PileRetour
        env.unification.Unif_Stack.pop(); // Implies that we must do the
                          // same with their
                          // UnificationRecord
      }

      // Il nous faut traiter a present le TermeRes Tr dont
      // la regle empilee contient le cut.
      // il faut le depiler de Pile_retour et l'empiler dans
      // Exec_Stack mais avec TermRes.Pos = taille du paquet
      // ainsi, sa resatisfaction serait impossible, impliquant
      // l'initialisation de TermRes.Pos a 0 et donc forcer un
      // retour arriere.
      if (TermRes.index != -1) { // TermRes.Index == -1 ; le cas de la
                    // question initiale qui contient le
                    // cut...
        TermRes = Return_Stack.getTop();

        while (Exec_Stack.indexOfTop() >= TermRes.indexInExecStack)
          // Depiler de Exec_Stack la queue de la regle
          // qui a ete utilise auparavant pour satisfaire le but.
          Exec_Stack.pop();

        // ainsi; il ne peut etre (re)satisfait
        // Thus; it cannot be (re)satisfied
        TermRes.pos = -1;
        Exec_Stack.push(Return_Stack.pop());

        env.unification.Unif_Stack.pop();
      } else {
        Exec_Stack.makeEmpty();
      }
    } else { // Is it a cut?
      // No, it is not a cut.
      if (TermRes.indexInExecStack >= 0) {
        // TermRes represente un but defini ou un but-var

        // TermRes represents a definite goal, or a
        // variable-goal.

        while (Exec_Stack.indexOfTop() >= TermRes.indexInExecStack) {
          // Depiler de Exec_Stack la queue de la regle
          // qui a ete utilise auparavant pour satisfaire le but.
          // On s'apprete a une nouvelle resatisfaction;
          // l'ancienne regle n'a plus d'utilite

          // Pop off of Exec_Stack the tail of the rule,
          // which was used before to satisfy the goal.
          // We will prepare ourselves for a new resatisfaction;
          // The old rule has no more utility.
          Exec_Stack.pop();
        }
      }

      // Pop something off the Return_Stack and
      // push it onto the Exec_Stack.
      Exec_Stack.push(Return_Stack.pop());

      // Pop something off of the unification stack.
      env.unification.Unif_Stack.pop();
    }

    idPred = null;
    TermRes = null;
  }

  public void push_tail(PrologRule pRegleLocal, int LimitIndex, int Niv,
      int TopOfReturnStack) {
    for (int i = (pRegleLocal.size() - 1); i >= LimitIndex; i--) {
      if ((pRegleLocal.getAt(i).getAt(0).typeOfData == uIdentifier)
          && ((String) pRegleLocal.getAt(i).getAt(0).data)
              .equals("/")) {
        // pour g?rer le cut lors d'un retour-arri?re

        // For managing the cut at the time of a
        // back-return (retour arrre).
        Exec_Stack.push(new TermToBeResolved(pRegleLocal.getAt(i),
            TopOfReturnStack, 0));
      } else {
        Exec_Stack.push(new TermToBeResolved(pRegleLocal.getAt(i), Niv,
            0));
      }
    }
  }

  // Helper methods
  public String variable_goal(PrologTerm pTerme) {
    // Does the goal correspond to a variable?
    if (pTerme.getAt(0).typeOfData == uVariable) {
      return ((String) pTerme.getAt(0).data);
    } else {
      return null;
    }
  }

  public boolean identifierIsPredefinedGoal(String IdPred) {
    for (int i = 0; true; i++) {
      if (PredefinedGoals[i].equals(IdPred)) {
        return true;
      } else if (PredefinedGoals[i].equals(strEndOfPredefinedGoals)) {
        break;
      }
    }

    return false;
  }

  boolean theGoalBelowOnTheStackIsNot() {
    boolean bFound = false;

    if (Exec_Stack.size() > 1) {
      TermToBeResolved unTermRes = (TermToBeResolved) Exec_Stack
          .elementAt(Exec_Stack.indexOfTop() - 1);

      if ((unTermRes.pTerm.getAt(0).typeOfData == uIdentifier)
          && ((String) unTermRes.pTerm.getAt(0).data).equals("not")
          && (unTermRes.pos == -1)) {
        bFound = true;
      }
    }

    return bFound;
  }

  void ASSERT(boolean cond, String msg) throws ExecException {
    if (!cond) {
      throw new ExecException(msg);
    }
  }

  boolean satisfyPredicateGoal(TermToBeResolved pTermRes, String IdPred)
      throws ExecException, CompileException {
    boolean resultat = false;
    PrologDataIndexPair Arg1;
    PrologDataIndexPair Arg2;
    RuleVector pRules;
    PrologList pLstPrlg;
    PrologTerm pTerme;

    if (IdPred.equals("/")) {
      env.unification.Unif_Stack.pushEmptyRecord(); // juste pour garder
                              // l'equilibre
      pTermRes.indexInExecStack = Exec_Stack.indexOfTop();

      Return_Stack.push(Exec_Stack.pop());

      // pTermRes.Pos = -1; // on n'a pas besoin car sa resatisfaction est
      // speciale
      resultat = true;
    } else if (IdPred.equals("maximalJoin") || IdPred.equals("generalize")
        || IdPred.equals("subsume")) {
      // CGOper(G1, C1, G2, C2, G3, C3) or subsume(G1, C1, G2, C2)
      // CGOper(G1, G2, G3) or subsume(G1, G2)
      CG G1;

      // CGOper(G1, C1, G2, C2, G3, C3) or subsume(G1, C1, G2, C2)
      // CGOper(G1, G2, G3) or subsume(G1, G2)
      CG G2;

      // CGOper(G1, C1, G2, C2, G3, C3) or subsume(G1, C1, G2, C2)
      // CGOper(G1, G2, G3) or subsume(G1, G2)
      CG G3 = null;
      int nivG1 = 0;
      int nivG2 = 0;
      Concept C1 = null;
      Concept C2 = null;
      PrologData DonRes = null;
      PrologData DonResBis = null;

      ASSERT(
          ((pTermRes.pTerm.size() == 7)
              || (pTermRes.pTerm.size() == 4)
              || ((pTermRes.pTerm.size() == 5) && IdPred
                  .equals("subsume")) || ((pTermRes.pTerm
              .size() == 3) && IdPred.equals("subsume"))),
          "Error: Wrong number of arguments for the CG operation.\n");

      if ((pTermRes.pTerm.size() == 7) || (pTermRes.pTerm.size() == 5)) {
        // presence des points d'entree
        Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm
            .getAt(1), pTermRes.index);
        ASSERT(
            ((Arg1.pData != null) && (Arg1.pData.typeOfData == uCG)),
            "Error: the first argument of the CG operation must be a CG.\n");
        G1 = (CG) Arg1.pData.data;
        nivG1 = Arg1.index;

        Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm
            .getAt(2), pTermRes.index);

        if ((Arg2.pData != null) && (Arg2.pData.typeOfData == uConcept)) {
          C1 = (Concept) Arg2.pData.data;
        } else {
          ASSERT(false,
              "Error: The second argument of the CG operation should be a concept.\n");
        }

        PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
            pTermRes.pTerm.getAt(3), pTermRes.index);
        ASSERT(
            ((Arg3.pData != null) && (Arg3.pData.typeOfData == uCG)),
            "Error: the third argument of the CG operation must be a CG.\n");
        G2 = (CG) Arg3.pData.data;
        nivG2 = Arg3.index;

        PrologDataIndexPair Arg4 = env.unification.valueFromUnifStack(
            pTermRes.pTerm.getAt(4), pTermRes.index);

        if ((Arg4.pData != null) && (Arg4.pData.typeOfData == uConcept)) {
          C2 = (Concept) Arg4.pData.data;
        } else {
          ASSERT(false,
              "Error: The fourth argument of the CG operation should be a concept.\n");
        }

        if (pTermRes.pTerm.size() == 7) {
          PrologDataIndexPair Arg5 = env.unification
              .valueFromUnifStack(pTermRes.pTerm.getAt(5),
                  pTermRes.index);
          ASSERT((Arg5.pData == null),
              "Error: the fifth argument of the CG operation must be a free variable.\n");
          G3 = new CG();
          DonRes = pTermRes.pTerm.getAt(5);

          PrologDataIndexPair Arg6 = env.unification
              .valueFromUnifStack(pTermRes.pTerm.getAt(6),
                  pTermRes.index);
          ASSERT((Arg6.pData == null),
              "Error: the sixth argument of the CG operation must be a free variable.\n");
          DonResBis = pTermRes.pTerm.getAt(6);
        }
      } else { // les cas : CGOper(G1, G2, G3) or subsume(G1, G2)
        Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm
            .getAt(1), pTermRes.index);
        ASSERT(
            ((Arg1.pData != null) && (Arg1.pData.typeOfData == uCG)),
            "Error: the first argument of the CG operation must be a CG.\n");
        G1 = (CG) Arg1.pData.data;
        nivG1 = Arg1.index;

        Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm
            .getAt(2), pTermRes.index);
        ASSERT(
            ((Arg2.pData != null) && (Arg2.pData.typeOfData == uCG)),
            "Error: the second argument of the CG operation must be a CG.\n");
        G2 = (CG) Arg2.pData.data;
        nivG2 = Arg2.index;

        if (pTermRes.pTerm.size() == 4) {
          PrologDataIndexPair Arg3 = env.unification
              .valueFromUnifStack(pTermRes.pTerm.getAt(3),
                  pTermRes.index);
          ASSERT((Arg3.pData == null),
              "Error: the third argument of the CG operation must be a free variable.\n");
          G3 = new CG();
          DonRes = pTermRes.pTerm.getAt(3);
        }
      }

      // Les arguments sont a present prets, en tenant compte des
      // differentes posibilites
      // Appel de l'operation de matching matchCG
      CGMatchResult resMatchCG = new CGMatchResult(G3, null);
      CGOperation uneOperGC = new CGOperation(env);
      resultat = uneOperGC.matchCG(CGOperation.convertToByte(IdPred, G3),
          C1, G1, nivG1, C2, G2, nivG2, resMatchCG);
      uneOperGC.corefMatchVec_MakeEmpty();
      uneOperGC = null;
      env.unification.Unif_Stack.pushEmptyRecord();

      if (resultat && (DonRes != null)) {
        PrologData donTmp = new PrologData(uCG, resMatchCG.G3);
        resultat = env.unification.unify(DonRes, pTermRes.index,
            donTmp, pTermRes.index);
      }

      if (resultat && (DonResBis != null)) {
        resultat = env.unification
            .unify(DonResBis, pTermRes.index, new PrologData(
                uConcept, resMatchCG.E3), pTermRes.index);
      }

      if (resultat) {
        pTermRes.pos = -1;

        Return_Stack.push(Exec_Stack.pop());
      } else {
        if (resMatchCG.G3 != null) {
          resMatchCG.G3.myDestroy();
        }

        if (resMatchCG.E3 != null) {
          resMatchCG.E3 = null;
        }

        env.unification.Unif_Stack.pop();
      }

      resMatchCG = null;
    } else if (IdPred.equals("length")) {
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: length takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(((Arg1.pData != null) && (Arg1.pData.typeOfData == uList)),
          "Error: The first argument of length must be a list.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData == null) || (Arg2.pData.typeOfData == uNumber)),
          "Error: The second argument of length must be an integer or a free variable.\n");
      pLstPrlg = (PrologList) Arg1.pData.data;

      int taille = 0;

      if (pLstPrlg != null) {
        taille = pLstPrlg.size();

        PrologDataIndexPair ValVarList = null;
        PrologData uneDonTmp = null;
        boolean finished = false;
        int Arg1Niv = Arg1.index;

        while (!finished) {
          try {
            uneDonTmp = (PrologData) pLstPrlg.lastElement();
          } catch (NoSuchElementException nsex) {
            // This could possibly happen
          }

          if (uneDonTmp.typeOfData == uVarList) {
            ValVarList = env.unification.valueFromUnifStack(
                uneDonTmp, Arg1Niv);
            Arg1Niv = ValVarList.index;

            if ((ValVarList.pData != null)
                && (ValVarList.pData.typeOfData != uList)) {
              throw new ExecException(
                  "The value of the variable after | should be a list.\n");
            } else if (ValVarList.pData != null) {
              pLstPrlg = (PrologList) ValVarList.pData.data;
              taille--; // decremente la taille de -1 car |x ne
                    // doit pas etre compte

              if (pLstPrlg == null) {
                finished = true;
              } else {
                taille = taille + pLstPrlg.size();
              }
            } else {
              throw new ExecException(
                  "Warning : The length of the list can not be determined since it is partially specified; the variable after | is free.\n");
            }
          } else {
            finished = true;
          }
        }
      }

      env.unification.Unif_Stack.pushEmptyRecord();
      resultat = env.unification.unify(new PrologData(uNumber,
          new Long(taille)), pTermRes.index, pTermRes.pTerm
          .getAt(2), pTermRes.index);

      if (resultat) {
        pTermRes.pos = -1;

        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("stringToLetters")
        || IdPred.equals("identToLetters")) {
      byte typeMot = 0;

      if (IdPred.equals("stringToLetters")) {
        typeMot = uString;
      } else {
        typeMot = uIdentifier;
      }

      ASSERT((pTermRes.pTerm.size() == 3), "Error: " + IdPred
          + " takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData == null) || (Arg1.pData.typeOfData == typeMot)),
          "Error: The first argument of " + IdPred
              + " must be a string/ident or a free variable.\n");

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData == null) || (Arg2.pData.typeOfData == uList)),
          "Error: The second argument of " + IdPred
              + " must be a list or a free variable.\n");
      ASSERT(((Arg1.pData != null) || (Arg2.pData != null)),
          "Error: At least one of the two arguments of " + IdPred
              + " must be bound.\n");

      if (Arg1.pData != null) { // le mot est fourni, passer au cars

        String mot = (String) Arg1.pData.data;

        // Construire la liste des lettres qui compose la chaine
        // String.valueOf(char) ==> String
        int tailleMot = mot.length();
        int i = 0;

        if (IdPred.equals("stringToLetters")) {
          // Ignorer les doubles quotes du string
          i++;
          tailleMot--;
        }

        String carToString = null;
        pLstPrlg = new PrologList();

        PrologData uneDon;

        for (; i < tailleMot; i++) {
          carToString = "\"" + String.valueOf(mot.charAt(i)) + "\"";
          uneDon = new PrologData(uString, carToString);
          pLstPrlg.addData(uneDon);
        }

        env.unification.Unif_Stack.pushEmptyRecord();
        uneDon = new PrologData(uList, pLstPrlg);
        resultat = env.unification.unify(uneDon, pTermRes.index,
            pTermRes.pTerm.getAt(2), pTermRes.index);
      } else { // le mot n'est pas fourni, le composer

        // La liste des cars est fournie
        // 1. Former un vecteur de char ? partir de la liste des
        // chaines/cars
        // 2. Former le mot ? partir du vecteur form? pr?c?demment
        pLstPrlg = (PrologList) Arg2.pData.data;
        pLstPrlg = copyAllOfTheListWithUnification(pLstPrlg, Arg2.index);

        int tailleVect = pLstPrlg.size();
        int i = 0;
        char[] vectCars = null;

        if (IdPred.equals("stringToLetters")) {
          tailleVect = tailleVect + 2;
          vectCars = new char[tailleVect];
          vectCars[0] = '\"';
          vectCars[tailleVect - 1] = '\"';
          i = 1;
        } else {
          vectCars = new char[tailleVect];
        }

        PrologData uneDon;
        String s = null;

        for (Enumeration<PrologData> e = pLstPrlg.elements(); e
            .hasMoreElements(); i++) {
          uneDon = (PrologData) e.nextElement();
          s = (String) uneDon.data;
          vectCars[i] = s.charAt(1);
        }

        String mot = new String(vectCars);
        uneDon = new PrologData(typeMot, mot);
        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(pTermRes.pTerm.getAt(1),
            pTermRes.index, uneDon, pTermRes.index);
      }

      if (resultat) {
        pTermRes.pos = -1;

        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("concat")) {
      ASSERT((pTermRes.pTerm.size() == 4), "Error: " + IdPred
          + " takes three arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData == null) || (typeIsPrimitive(Arg1.pData.typeOfData))),
          "Error: The first argument of " + IdPred
              + " must be a number, a boolean, an identifier, a string, or a free variable.\n");
      int nNoOfFreeArguments = 0;
      if (Arg1.pData == null) {
        nNoOfFreeArguments++;
      }

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData == null) || (typeIsPrimitive(Arg2.pData.typeOfData))),
          "Error: The second argument of " + IdPred
              + " must be a number, a boolean, an identifier, a string, or a free variable.\n");
      if (Arg2.pData == null) {
        nNoOfFreeArguments++;
      }

      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3), pTermRes.index);
      ASSERT(
          ((Arg3.pData == null) || (Arg3.pData.typeOfData == uString)),
          "Error: The third argument of " + IdPred
              + " must be a string or a free variable.\n");

      if (Arg3.pData == null) {
        nNoOfFreeArguments++;
      }

      ASSERT(
          (nNoOfFreeArguments == 1) || (nNoOfFreeArguments == 0),
          "Error: "
              + IdPred
              + " must have either two or three bound arguments.\n");

      if (Arg3.pData == null || nNoOfFreeArguments == 0) {
        // We are concat'ing the easy case of Arg1 + Arg2
        String s1 = primitiveTypeToString(Arg1.pData);
        String s2 = primitiveTypeToString(Arg2.pData);

        String s3 = "\"" + s1.substring(1, s1.length() - 1)
            + s2.substring(1, s2.length() - 1) + "\"";

        PrologData uneDon = new PrologData(uString, s3);

        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(uneDon, pTermRes.index,
            pTermRes.pTerm.getAt(3), pTermRes.index);

      } else if (Arg2.pData == null) {
        // Arg3 is not null, and nNoOfArguments == 1
        String s1 = primitiveTypeToString(Arg1.pData);
        String s3 = primitiveTypeToString(Arg3.pData);

        String s1stripped = s1.substring(1, s1.length() - 1);
        String s3stripped = s3.substring(1, s3.length() - 1);

        resultat = s3stripped.startsWith(s1stripped);
        if (!resultat) {
          env.unification.Unif_Stack.pushEmptyRecord();
        } else {
          int s1strippedLength = s1stripped.length();
          String s2 = "\""
              + s3stripped.substring(s1strippedLength, s3stripped
                  .length()) + "\"";

          PrologData uneDon = new PrologData(uString, s2);

          env.unification.Unif_Stack.pushEmptyRecord();
          resultat = env.unification.unify(uneDon, pTermRes.index,
              pTermRes.pTerm.getAt(2), pTermRes.index);
        }
      } else {
        // Arg1.pDonnee is null, and nNoOfFreeArguments == 1
        String s2 = primitiveTypeToString(Arg2.pData);
        String s3 = primitiveTypeToString(Arg3.pData);

        String s2stripped = s2.substring(1, s2.length() - 1);
        String s3stripped = s3.substring(1, s3.length() - 1);

        resultat = s3stripped.endsWith(s2stripped);
        if (!resultat) {
          env.unification.Unif_Stack.pushEmptyRecord();
        } else {
          int s2strippedLength = s2stripped.length();
          String s1 = "\""
              + s3stripped.substring(0, s3stripped.length()
                  - s2strippedLength) + "\"";

          PrologData uneDon = new PrologData(uString, s1);

          env.unification.Unif_Stack.pushEmptyRecord();
          resultat = env.unification.unify(uneDon, pTermRes.index,
              pTermRes.pTerm.getAt(1), pTermRes.index);
        }
      }

      if (resultat) {
        pTermRes.pos = -1;

        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("branchOfCG")) { // branchOfCG(CG_Branch, CG)

      // on le traitera de la meme maniere que member : on parcourt le CG,
      // similaire en cela a une liste de branchs
      // et on tentera d'unifier notre branch arg1 avec la branch courante
      // dans CG

      // branchOfCG must have two arguments
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: branchOfCG takes two arguments.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData != null) && (Arg2.pData.typeOfData == uCG)),
          "Error: The second argument of branchOfCG must be a CG.\n");

      CG unGC = (CG) Arg2.pData.data;
      Vector<Relation> vctRels = unGC.m_vctRelations;
      int nbreBranch = vctRels.size();

      while ((pTermRes.pos < nbreBranch) && !resultat) {
        env.unification.Unif_Stack.pushEmptyRecord();

        // Creer un CG a partir de la branche/relation courante dans le
        // CG arg2
        // Remplir branchCadre
        CG unGCBranch = createCGBranch((Relation) vctRels
            .elementAt(pTermRes.pos));

        // Inverser les arg de unifier comme pour la primitive "eq"
        resultat = env.unification.unify(
            new PrologData(uCG, unGCBranch), Arg2.index,
            pTermRes.pTerm.getAt(1), pTermRes.index);
        pTermRes.pos++;

        if (resultat) {
          Return_Stack.push(Exec_Stack.pop());
        } else {
          env.unification.Unif_Stack.pop();
        }
      }
    } else if (IdPred.equals("concOfCG")) { // concOfCG(ConceptOUVar, CG)
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: concOfCG takes two arguments.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData != null) && (Arg2.pData.typeOfData == uCG)),
          "Error: The second argument of concOfCG must be a CG.\n");

      CG unGC = (CG) Arg2.pData.data;
      Vector<Concept> vctConcepts = unGC.m_vctConcepts;
      int nbreConcs = vctConcepts.size();
      resultat = false;

      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);

      while ((pTermRes.pos < nbreConcs) && !resultat) {
        env.unification.Unif_Stack.pushEmptyRecord();

        Concept concCour = (Concept) vctConcepts
            .elementAt(pTermRes.pos);

        // Is Arg1 a free variable?
        if (Arg1.pData == null) {
          // Yes, it was a free variable.
          // Therefore, we don't transform it to a CG,
          // since otherwise, we will unify the whole CG.

          // Inverser les arg de unifier comme pour la primitive "eq"
          resultat = env.unification.unify(new PrologData(uConcept,
              concCour), Arg2.index, pTermRes.pTerm.getAt(1),
              pTermRes.index);
        } else {
          // No, it was not a free variable.
          // Therefore, there is no harm done in making it a CG.

          // Make a CG out of the concept.
          // This is because env.unification.unifier does not do the
          // special variable-substitution magic on uConcept.
          CG gTmp = new CG();
          gTmp.addConcept(concCour);

          // Inverser les arg de unifier comme pour la primitive "eq"
          resultat = env.unification
              .unify(new PrologData(uCG, gTmp), Arg2.index,
                  pTermRes.pTerm.getAt(1), pTermRes.index);
        }
        pTermRes.pos++;

        if (resultat) {
          Return_Stack.push(Exec_Stack.pop());
        } else {
          env.unification.Unif_Stack.pop();
        }
      }
    } else if (IdPred.equals("member")) {
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: member takes two arguments.\n"); // member doit
                                // avoir deux
                                // arg.

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData != null) && (Arg2.pData.typeOfData == uList)),
          "Error: The second argument of member must be a list.\n");

      // INUTIL : env.unification.Unif_Stack.addNewElement(); // pour la
      // forme initiale de membre
      pLstPrlg = (PrologList) Arg2.pData.data;

      /*
       * le parcourt de la liste a le recherche de l'element pourrait
       * impliquer, avec des VarList, des passages d'une liste a une
       * autre. Il faudrait alors savoir tj dans quelle liste on est. Pour
       * cela, la solution adoptee consiste a ajouter un arg a pTermRes,
       * lstMember, qui specifiera la liste courante***********
       */
      pTermRes.lstMember = null;
      pTermRes.indLstMember = 0;

      int Arg2Niv = Arg2.index;

      int dernierInd = pLstPrlg.size() - 1;
      boolean finished = false;

      while (!finished && !resultat) {
        while ((pTermRes.pos < dernierInd) && !resultat) {
          env.unification.Unif_Stack.pushEmptyRecord();

          /**
           * Si on arrive au dernier element de la liste et c'est une
           * VarList alors il faut chercher sa valeur et relancer le
           * membre ...
           */
          resultat = env.unification.unify(pTermRes.pTerm.getAt(1),
              pTermRes.index, pLstPrlg.getAt(pTermRes.pos),
              Arg2Niv);
          pTermRes.pos++;

          if (resultat) {
            Return_Stack.push(Exec_Stack.pop());
          } else {
            env.unification.Unif_Stack.pop();
          }
        }

        if (!resultat && (pTermRes.pos == dernierInd)) {
          // avec la condition pTermRes.Pos == dernierInd, on traite
          // le cas o? la liste est vide
          if (pLstPrlg.getAt(dernierInd).typeOfData == uVarList) {
            PrologDataIndexPair contr = env.unification
                .valueFromUnifStack(pLstPrlg.getAt(dernierInd),
                    Arg2Niv);
            ASSERT((contr.pData != null)
                && (contr.pData.typeOfData == uList),
                "Error: The second argument of member should be a list.\n");
            pLstPrlg = (PrologList) contr.pData.data;
            Arg2Niv = contr.index;
            pTermRes.lstMember = pLstPrlg;
            pTermRes.indLstMember = contr.index;
            dernierInd = pLstPrlg.size() - 1;
            pTermRes.pos = 0;
          } else {
            env.unification.Unif_Stack.pushEmptyRecord(); // pour la
                                    // forme
                                    // instanciee
                                    // de
                                    // membre
            resultat = env.unification.unify(pTermRes.pTerm
                .getAt(1), pTermRes.index, pLstPrlg
                .getAt(dernierInd), Arg2Niv);
            pTermRes.pos++;

            if (resultat) {
              Return_Stack.push(Exec_Stack.pop());
            } else {
              env.unification.Unif_Stack.pop();
            }

            finished = true;
          }
        } else {
          finished = true;
        }
      }

      if (!resultat) {
        pTermRes.lstMember = null;
        pTermRes.indLstMember = 0;
        pTermRes.pos = 0;
      }
    } else if (IdPred.equals("not")) { // not(But)
      ASSERT((pTermRes.pTerm.size() == 2),
          "Error: not takes one argument.\n"); // not doit avoir 1
                              // arg.
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && ((Arg1.pData.typeOfData == uTerm)
              || (Arg1.pData.typeOfData == uIdentifier) || (Arg1.pData.typeOfData == uCG))),
          "Error: The not argument must be a term or a CG.\n");
      pTermRes.pos = -1; // not(But) reste dans la Exec_Stack
      pTermRes.indexInExecStack = Return_Stack.indexOfTop();

      // et on empile ensuite But
      PrologTerm aTrmtmp = null;

      if ((Arg1.pData.typeOfData == uIdentifier)
          || (Arg1.pData.typeOfData == uCG)) {
        aTrmtmp = new PrologTerm();
        aTrmtmp.addData(Arg1.pData);
      } else {
        aTrmtmp = (PrologTerm) Arg1.pData.data;
      }

      Exec_Stack.push(new TermToBeResolved(aTrmtmp, Arg1.index, 0));
      resultat = true;
    } else if (IdPred.equals("findall")) { // findall(Var, But, ListValVar)

      /*****
       * resolution de findall est traite comme suit : elle consiste ?
       * cr?er une liste L (listfindall), et faire comme si findall(X,B,L)
       * :- B, addElemForAll(..), fail. et donc : depiler findall pour
       * l'empiler dans Return_Stack et empiler dans Exec_Stack les buts :
       * But, addElemForAll(ValVar, ListValVar), fail . Le "fail" va
       * imposer des resatisfactions de But suivi de addElemForAll qui
       * mettera les valeurs de X dans ListValVar. Une fois But ?puis?,
       * l'interpreteur tentera de resatisfaire findall. On aura alors
       * dans la Exec_Stack : findall(), B, addElemForAll(..), fail. La
       * premi?re resatisfaction de findall consistera ? le depiler pour
       * l'empiler dans Return_Stack et a enlever les trois ?l?ments qui
       * se trouvent au sommet de la Exec_Stack (B, addElemForAll(..),
       * fail), comme si les trois buts n'ont jamais existe, et on
       * indiquera quelle est resatisfaite mais quelle ne peut plus etre
       * resatisfaite. d'autres aspects (detail mais important) se
       * retrouvent dans le code
       */
      ASSERT((pTermRes.pTerm.size() == 4),
          "Error: findall takes three arguments.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && ((Arg2.pData.typeOfData == uTerm)
              || (Arg2.pData.typeOfData == uIdentifier) || (Arg2.pData.typeOfData == uCG))),
          "Error: The second argument of findall must be a term or a CG.\n");

      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData == null)
              && ((pTermRes.pTerm.getAt(1).typeOfData == uVariable) || (pTermRes.pTerm
                  .getAt(1).typeOfData == uVarList)) && isVariableGoal(
              (String) pTermRes.pTerm.getAt(1).data, Arg2.pData)),
          "Error: The first argument of findall must be a free variable that is contained in the second argument.\n");

      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3), pTermRes.index);
      ASSERT(
          (Arg3.pData == null)
              && ((pTermRes.pTerm.getAt(3).typeOfData == uVariable) || (pTermRes.pTerm
                  .getAt(3).typeOfData == uVarList)),
          "Error: the third argument of findall must be a free variable.\n");

      // Creer la liste qui contiendra les valeurs possibles
      // de X; le premier arg de findall
      pTermRes.pos = -1; // findall(X,But,L) sera resatisfaite
      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pLstPrlg = new PrologList();

      PrologData nouvDon = new PrologData(uList, pLstPrlg);
      env.unification.unify(pTermRes.pTerm.getAt(3), pTermRes.index,
          nouvDon, pTermRes.index);
      pTermRes.lstMember = pLstPrlg;
      Return_Stack.push(Exec_Stack.pop()); // il s'agit du but findall(..)

      // Push le but fail
      PrologTerm aTrmTmp = new PrologTerm();
      nouvDon = new PrologData(uIdentifier, "fail");
      aTrmTmp.addData(nouvDon);
      nouvDon = null;
      Exec_Stack.push(new TermToBeResolved(aTrmTmp, pTermRes.index, 0));

      // Push le but inserer(ValVar, ListValVar)
      aTrmTmp = new PrologTerm();
      aTrmTmp.addData(new PrologData(uIdentifier, "addElemForAll"));
      aTrmTmp.addData(pTermRes.pTerm.getAt(1)); // on met la variable car
                            // sa valeur changera
      aTrmTmp.addData(pTermRes.pTerm.getAt(3));
      Exec_Stack.push(new TermToBeResolved(aTrmTmp, pTermRes.index, 0));

      // et on empile ensuite But
      if (Arg2.pData.typeOfData == uCG) {
        aTrmTmp = new PrologTerm();
        aTrmTmp.addData(Arg2.pData);
      } else {
        aTrmTmp = (PrologTerm) Arg2.pData.data;
      }

      Exec_Stack.push(new TermToBeResolved(aTrmTmp, Arg2.index, 0));

      aTrmTmp = null;
      resultat = true;
    } else if (IdPred.equals("set_list")) { // set_list(Ensemble, Liste)
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: set_list takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(((Arg1.pData == null) || (Arg1.pData.typeOfData == uSet)),
          "Error: the first argument of set_list must be a free variable or a set.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData == null) || (Arg2.pData.typeOfData == uList)),
          "Error: the second argument of set_list must be a free variable or a list.\n");
      ASSERT(((Arg1.pData != null) || (Arg2.pData != null)),
          "Error: the two arguments of set_list can not be two free variables.\n"); // on
                                                // ne
                                                // peut
                                                // avoir
                                                // deux
                                                // var.
                                                // libres

      if (Arg1.pData == null) { // Ensemble non connue, on le cr?e
        pLstPrlg = (PrologList) Arg2.pData.data;
        pLstPrlg = copyAllOfTheListWithUnification(pLstPrlg, Arg2.index);

        PrologData uneDon = new PrologData(uSet, pLstPrlg);
        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(pTermRes.pTerm.getAt(1),
            pTermRes.index, uneDon, pTermRes.index);
      } else { // Liste non connue, on la cree

        PrologData uneDon = Arg1.pData.myCopy();
        uneDon.typeOfData = uList; // On a transforme l'ensemble en une
                      // liste
        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(uneDon, pTermRes.index,
            pTermRes.pTerm.getAt(2), pTermRes.index);
      }

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("shuffle")) { // set_list(Input_List, Output_List)
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: shuffle takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT((Arg1.pData.typeOfData == uList),
          "Error: the first argument of shuffle must be a list.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT((Arg2.pData == null),
          "Error: the second argument of shuffle must be a free variable.\n");

      pLstPrlg = (PrologList) Arg1.pData.data;
      pLstPrlg = copyAllOfTheListWithUnification(pLstPrlg, Arg1.index);
      pLstPrlg.shuffle();

      PrologData uneDon = new PrologData(uList, pLstPrlg);
      env.unification.Unif_Stack.pushEmptyRecord();
      resultat = env.unification.unify(pTermRes.pTerm.getAt(2),
                       pTermRes.index, uneDon, pTermRes.index);

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("term_list")) { // term_list(Terme, Liste)
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: term_list takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(((Arg1.pData == null) || (Arg1.pData.typeOfData == uTerm)),
          "Error: the first argument of term_list must be a free variable or a term.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData == null) || (Arg2.pData.typeOfData == uList)),
          "Error: the second argument of term_list must be a free variable or a list.\n");
      ASSERT(((Arg1.pData != null) || (Arg2.pData != null)),
          "Error: the two arguments of term_list can not be two free variables.\n"); // on
                                                // ne
                                                // peut
                                                // avoir
                                                // deux
                                                // var.
                                                // libres

      if (Arg1.pData == null) { // Terme non connue, on le cr?e
        pLstPrlg = (PrologList) Arg2.pData.data;

        // Vector vct = (Vector) Arg2.pDonnee.Don; // Arg2..
        // retournerait en principe une PrologList
        ASSERT((pLstPrlg.size() != 0),
            "Error: the second argument of term_list can not be an empty list.\n");

        // Verifier que le 1er elem de la liste est un ident
        PrologDataIndexPair ArgTmp = env.unification
            .valueFromUnifStack((PrologData) pLstPrlg.elementAt(0),
                Arg2.index);
        ASSERT(
            ((ArgTmp.pData != null) && (ArgTmp.pData.typeOfData == uIdentifier)),
            "Error: the first element of the list (the second argument of term_list) must be an identifier.\n");

        // ******** IMPORTANT*********************////
        // *** A REVOIR**** touteLaListe ici ne constitue pas une
        // solution tres satisfaisante
        // car la valeur d'une variable peut etre une structure qui
        // contient elle
        // pLstPrlg = touteLaListe(pLstPrlg, Arg2.niv);
        // On conserve donc le probleme.. pour le cas ou le dernier elem
        // de la liste
        // est une VarListe ..... a traiter ce probleme par la suite,
        // une fois que
        // ********* le probleme d'indexation soit reglee
        pTerme = new PrologTerm();

        PrologData uneDon;

        for (Enumeration<PrologData> e = pLstPrlg.elements(); e
            .hasMoreElements();) {
          uneDon = (PrologData) e.nextElement();
          pTerme.addData(uneDon);
        }
        pTerme.setElementAt(ArgTmp.pData, 0); // remplacer son premier
                            // elem
        ArgTmp = null; // pour que ArgTmp soit eliminer localement et
                // correctement

        uneDon = new PrologData(uTerm, pTerme);
        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(pTermRes.pTerm.getAt(1),
            pTermRes.index, uneDon, pTermRes.index);
      } else { // Terme connu; construire ou tester la liste (2 arg)
        pTerme = (PrologTerm) Arg1.pData.data;
        pLstPrlg = new PrologList();

        PrologData uneDon = null;

        for (Enumeration<PrologData> e = pTerme.elements(); e
            .hasMoreElements();) {
          uneDon = (PrologData) e.nextElement();
          pLstPrlg.addData(uneDon);
        }

        uneDon = new PrologData(uList, pLstPrlg);
        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(uneDon, pTermRes.index,
            pTermRes.pTerm.getAt(2), pTermRes.index);
      }

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("read") || IdPred.equals("read_sentence")) {
      // We mustn't be an applet
      ASSERT(!env.bIsApplet,
          "Cannot use the 'read' or 'read_sentence' predicates in an applet!");
      if (IdPred.equals("read")) {
        ASSERT((pTermRes.pTerm.size() == 2),
            "Error: read takes one argument.\n"); // read doit avoir
                                // 1 arg.
      } else {
        ASSERT(
            ((pTermRes.pTerm.size() == 2) || (pTermRes.pTerm.size() == 3)),
            "Error: read_sentence takes one or two arguments.\n");
      }

      byte modeLecture = 0;

      if (pTermRes.pTerm.size() == 2) { // read(x) or read_sentence(L)
        Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm
            .getAt(1), pTermRes.index);
        ASSERT(
            ((Arg1.pData == null) && ((pTermRes.pTerm.getAt(1).typeOfData == uVariable) || (pTermRes.pTerm
                .getAt(1).typeOfData == uVarList))),
            "Error: the read and read_sentence/1 argument must be a free variable.\n");

        if (IdPred.equals("read")) {
          modeLecture = uReadData;
        } else {
          modeLecture = uReadSentence;
        }

        env.io.appendToConsole("|: ");
        env.io.readSomething(modeLecture);
      } else { // Le cas de read_sentence(String, List)
        modeLecture = uReadSentence;
        Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm
            .getAt(1), pTermRes.index);
        ASSERT(
            ((Arg1.pData != null) && (Arg1.pData.typeOfData == uString)),
            "Error: The first argument of read_sentence/2 must be a String.\n");

        Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm
            .getAt(2), pTermRes.index);
        ASSERT(
            ((Arg2.pData == null) && ((pTermRes.pTerm.getAt(2).typeOfData == uVariable) || (pTermRes.pTerm
                .getAt(2).typeOfData == uVarList))),
            "Error: The second argument of read_sentence/2 must be a free variable.\n");

        try {
          String sTmp = (String) Arg1.pData.data;
          env.compile.CompileTxt = sTmp.substring(1,
              sTmp.length() - 1); // Enlever les doubles quotes
          env.compile.textEndIndex = env.compile.CompileTxt.length();
          env.compile.curCharIndex = 0;
          env.compile.readChar();
          env.compile.vctUnitTyp.removeAllElements();
          env.compile.tSentence();
        } catch (CompileException e1) {
          if (!e1.getMessage().equals("End Of Text")
              || env.compile.vctUnitTyp.isEmpty()) {
            env.io.appendToConsole("\n Error in the given string.");
            env.compile.vctUnitTyp.removeAllElements();
          }
        }
      }

      if (!env.compile.vctUnitTyp.isEmpty() && (modeLecture == uReadData)) {
        PrologTerm trmTmp = new PrologTerm();

        try {
          env.compile.currElem = 0;
          env.compile.tPrologData(true, trmTmp);
        } catch (CompileException ce) {
          // This could possibly happen
        }

        PrologData donIn = trmTmp.getAt(0);
        trmTmp.removeAllElements();
        trmTmp = null;
        env.compile.vctUnitTyp.removeAllElements();

        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(donIn, pTermRes.index,
            pTermRes.pTerm.getAt(1), pTermRes.index);

        if (resultat) {
          pTermRes.pos = -1;
          Return_Stack.push(Exec_Stack.pop());
        } else { // {
          env.unification.Unif_Stack.pop();
        }

        // pTermRes.Pos = 0; inutil puisqu'il l'est au depart et il ne
        // change pas ici
        // }; // cela s'applique aussi pour les buts suivants
      } else if (!env.compile.vctUnitTyp.isEmpty()
          && (modeLecture == uReadSentence)) {
        // Cr?er la liste des mots composant la phrase
        PrologList LstPrlg = new PrologList();
        UnitType unitTyp = null;
        String sTmp = null;

        for (Enumeration<UnitType> e = env.compile.vctUnitTyp
            .elements(); e.hasMoreElements();) {
          unitTyp = (UnitType) e.nextElement();
          sTmp = '"' + unitTyp.unit.toString() + '"';
          LstPrlg.addData(new PrologData(uString, sTmp));
        }

        env.compile.vctUnitTyp.removeAllElements();

        // Unifier la liste ainsi cr?e avec l'argument correspondant de
        // read_sentence
        env.unification.Unif_Stack.pushEmptyRecord();

        PrologData donTmp = new PrologData(uList, LstPrlg);
        int indArg = 0;

        if (pTermRes.pTerm.size() == 2) {
          indArg = 1;
        } else {
          indArg = 2;
        }

        resultat = env.unification.unify(donTmp, pTermRes.index,
            pTermRes.pTerm.getAt(indArg), pTermRes.index);
        donTmp = null;

        if (resultat) {
          pTermRes.pos = -1;
          Return_Stack.push(Exec_Stack.pop());
        } else {
          env.unification.Unif_Stack.pop();
        }
      } else {
        throw new ExecException("Error while reading data.");
      }
    } else if (IdPred.equals("addElemForAll")) {
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      pLstPrlg = (PrologList) Arg2.pData.data;

      if ((pLstPrlg.size() == 0)
          || (Arg1.pData != ((PrologData) pLstPrlg.lastElement()))) {
        pLstPrlg.addData(Arg1.pData);
      }

      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("write")) {
      ASSERT((pTermRes.pTerm.size() == 2),
          "Error: write takes one argument.\n"); // write doit avoir 1
                              // arg.
      // if (env.bIsApplet) {
      // PrologPlusCGFrame.pCurPrologTextArea =
      // PrologPlusCGApplet.webConsoleArea;
      // } else {
      // PrologPlusCGFrame.pCurPrologTextArea =
      // PrologPlusCGFrame.consoleArea;
      // }
      env.printer.indVar = 0;
      env.printer.printPrologData(pTermRes.pTerm.getAt(1),
          pTermRes.index, true);
      env.printer.flush();
      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("writenl")) {
      ASSERT((pTermRes.pTerm.size() == 2),
          "Error: writenl takes one argument.\n"); // writenl doit
                                // avoir 1 arg.
      // if (env.bIsApplet) {
      // PrologPlusCGFrame.pCurPrologTextArea =
      // PrologPlusCGApplet.webConsoleArea;
      // } else {
      // PrologPlusCGFrame.pCurPrologTextArea =
      // PrologPlusCGFrame.consoleArea;
      // }
      env.printer.indVar = 0;
      env.printer.printPrologData(pTermRes.pTerm.getAt(1),
          pTermRes.index, true);
      env.printer.flush();
      env.io.appendToConsole("\n");
      env.unification.Unif_Stack.pushEmptyRecord(); // Even if there was
                              // no unification;
                              // for homogenizing
                              // with
                              // RetourArriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("clearConsole")) {
      // clearConsole must have no arguments
      ASSERT((pTermRes.pTerm.size() == 1),
          "Error: clearConsole takes no arguments.\n");

      // Clear the web console area
      env.io.clearConsole();

      // Set everything OK
      env.unification.Unif_Stack.pushEmptyRecord(); // Even if there was
                              // no unification;
                              // for homogenizing
                              // with
                              // RetourArriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("nl")) {
      // nl must have no arguments
      ASSERT((pTermRes.pTerm.size() == 1),
          "Error: nl takes no arguments.\n");

      // Clear the web console area
      env.io.appendToConsole("\n");

      // Set everything OK
      env.unification.Unif_Stack.pushEmptyRecord(); // Even if there was
                              // no unification;
                              // for homogenizing
                              // with
                              // RetourArriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("exec") || IdPred.equals("execAndWait")) {
      ASSERT((pTermRes.pTerm.size() == 2), "Error: " + IdPred
          + " takes one argument.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && (Arg1.pData.typeOfData == uString)),
          "Error: the second argument of  " + IdPred
              + " must be an executable file.\n");

      Process unProcess = null;

      try {
        unProcess = Runtime.getRuntime().exec((String) Arg1.pData.data);
      } catch (SecurityException sex) {
        // This could possibly happen
      } catch (java.io.IOException ioex) {
        // This could possibly happen
      }

      try {
        if (IdPred.equals("execAndWait")) {
          unProcess.waitFor();
        }
      } catch (InterruptedException intEx) {
        // This could possibly happen
      }

      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("destroyAll")) { // destroyAll
      ASSERT((pTermRes.pTerm.size() == 1),
          "Error: destroyAll has no argument.\n");
      clear_globalPrlgPCGObjs();
      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("destroy")) { // destroy(IdObj)
      ASSERT((pTermRes.pTerm.size() == 2),
          "Error: destroy takes one argument.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && (Arg1.pData.typeOfData == uIdentifier)),
          "Error: the first argument of destroy must be an identifier.\n");

      String IdObj = (String) Arg1.pData.data;
      ASSERT((globalPrlgPCGObjs.get(IdObj) != null),
          "Error : Object unknown.");
      globalPrlgPCGObjs.remove(IdObj);
      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("objectify")) { // objectify(_variable, IdObj)
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: objectify takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && (Arg1.pData.typeOfData == uObject)),
          "Error: the first argument of objectify must be an object.\n");

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && (Arg2.pData.typeOfData == uIdentifier)),
          "Error: the second argument of objectify must be an identifier.\n");

      String IdObj = (String) Arg2.pData.data;
      ASSERT((globalPrlgPCGObjs.get(IdObj) == null),
      "Error : Object already exists.");
     
      // Rentrer l'association <IdObj, nouvObj> dans la table des
      // "donneesGlobales"
      globalPrlgPCGObjs.put(IdObj, new PrologData(uObject, Arg1.pData.data));

      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
      // no unification:
      // For homogenizing
      // with
      // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("get") || IdPred.equals("set")) { // get(Data,
                                  // Attribute,
                                  // IdObject)
      ASSERT((pTermRes.pTerm.size() == 4), "Error: " + IdPred
          + " takes three arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData == null) || typeIsPrimitive(Arg1.pData.typeOfData)),
          "Error: the first argument of " + IdPred
              + " must be a variable or an elementary data.\n");

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && (Arg2.pData.typeOfData == uString)),
          "Error: the second argument of " + IdPred
              + " must be a string (an attribute identifier).\n");

      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3), pTermRes.index);
      ASSERT(
          ((Arg3.pData != null) && (Arg3.pData.typeOfData == uIdentifier)),
          "Error: the third argument of "
              + IdPred
              + " must be an identifier (an object identifier).\n");

      // Chercher l'objet et sa classe
      String IdObj = (String) Arg3.pData.data;
      PrologData donTmp = (PrologData) globalPrlgPCGObjs.get(IdObj);
      ASSERT(((donTmp != null) && (donTmp.typeOfData == uObject)),
          "Error : Only a Java Object can be considered.\n");

      Object obj = donTmp.data;
      Class<? extends Object> classDeObj = obj.getClass();

      // Localiser l'attribut (arg 2 de get/set) pour la classe
      String NomAttr = (String) Arg2.pData.data;
      NomAttr = NomAttr.substring(1, NomAttr.length() - 1); // enlever les
                                  // entre-guillemets

      Field attr = null;

      try {
        attr = classDeObj.getField(NomAttr);
      } catch (NoSuchFieldException nsfexe) {
        throw new ExecException("Error: " + NomAttr
            + " is not a field in the class : "
            + classDeObj.getName());
      } catch (SecurityException sex) {
        throw new ExecException("Security Error: in trying to locate "
            + NomAttr + " as a field in the class : "
            + classDeObj.getName());
      }

      // Chercher la valeur de l'attribut si c'est get
      // .. ou lui affecter une valeur si c'est set
      Object valAttr = null;

      try {
        if (IdPred.equals("set")) {
          valAttr = Arg1.pData.data;
          attr.set(obj, valAttr);
        } else {
          valAttr = attr.get(obj);
        }
      } catch (IllegalAccessException iaex) {
        throw new ExecException(
            "Illegal Access Error : The underlying constructor of "
                + obj.toString() + " is inaccessible.");
      } catch (IllegalArgumentException iaex) {
        throw new ExecException(
            "Illegal Argument Error : The given value is not conform to the type of "
                + NomAttr);
      } catch (NullPointerException npex) {
        throw new ExecException("Null Pointer Error.");
      } catch (ExceptionInInitializerError exInInitErr) {
        throw new ExecException("Error during initialization.");
      }

      // si le but est get; Unifier cette valeur avec le premier arg du
      // but get(...)
      env.unification.Unif_Stack.pushEmptyRecord();

      if (IdPred.equals("set")) {
        resultat = true;
      } else {
        byte typeValAttr = typeFromClass(valAttr.getClass());
        PrologData donRes = new PrologData(typeValAttr, valAttr);
        resultat = env.unification.unify(donRes, pTermRes.index,
            pTermRes.pTerm.getAt(1), pTermRes.index);
      }

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("new")) { // new(IdObj, NomClass,
                      // ListeArgsConstr)
      ASSERT((pTermRes.pTerm.size() == 4),
          "Error: new takes three arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && (Arg1.pData.typeOfData == uIdentifier)),
          "Error: the first argument of new must be an identifier.\n");

      String IdObj = (String) Arg1.pData.data;

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && (Arg2.pData.typeOfData == uString)),
          "Error: the second argument of new must be a string (a class name).\n");

      String NomClass = (String) Arg2.pData.data;
      NomClass = NomClass.substring(1, NomClass.length() - 1);

      Class<? extends Object> classDeNouvObj = null;

      try {
        classDeNouvObj = Class.forName(NomClass);
      } catch (ClassNotFoundException clNtFdEx) {
        throw new ExecException("Error: the specified class "
            + NomClass + " is not found.\n");
      }

      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3), pTermRes.index);
      ASSERT(
          ((Arg3.pData != null) && (Arg3.pData.typeOfData == uList)),
          "Error: the third argument of new must be a list; the arguments list for the constructor.\n");

      // 3bis determiner le type des arguments et former
      // le vecteur Class[] vectTypArgs
      // 3bis2. Construire le vecteurs des objets qui seront les arguments
      // du constructeur
      PrologList listArgsMetd = (PrologList) Arg3.pData.data;

      int nbreArgs = 0;
      Object[] vectObjsArgs = null;
      Class[] vectTypArgs = null;

      if ((listArgsMetd != null) && !listArgsMetd.isEmpty()) {
        listArgsMetd = copyAllOfTheListWithUnification(listArgsMetd,
            Arg3.index);
        nbreArgs = listArgsMetd.size();
        vectObjsArgs = new Object[nbreArgs];
        vectTypArgs = new Class[nbreArgs];

        int i = 0;
        PrologData uneDon;

        for (Enumeration<PrologData> e = listArgsMetd.elements(); e
            .hasMoreElements(); i++) {
          uneDon = (PrologData) e.nextElement();

          if (uneDon.typeOfData == uString) {
            String st = (String) uneDon.data;
            vectObjsArgs[i] = st.substring(1, st.length() - 1);
          } else {
            vectObjsArgs[i] = uneDon.data;
          }
          vectTypArgs[i] = uneDon.data.getClass();
        }
      }

      // Creer le Constructeur
      Constructor constrClass = null;

      try {
        constrClass = classDeNouvObj.getConstructor(vectTypArgs);
      } catch (NoSuchMethodException nsmex) {
        throw new ExecException("Error: the specified class "
            + NomClass + " has not the specified constructor.\n");
      }

      // Creer l'objet
      Object nouvObj = null;

      try {
        nouvObj = constrClass.newInstance(vectObjsArgs);
      } catch (IllegalAccessException ilAcExe) {
        throw new ExecException(
            "Illegal Access Error: the specified class " + NomClass
                + " is not found.\n");
      } catch (InstantiationException instExe) {
        throw new ExecException(
            "Instantiation Error: the specified class " + NomClass
                + " is not found.\n");
      } catch (InvocationTargetException invTrgtExe) {
        throw new ExecException(
            "Instantiation Error: Target invocation error during instantiation of the class "
                + NomClass + " .\n");
      }

      ASSERT((globalPrlgPCGObjs.get(IdObj) == null),
          "Error : Object already exists.");

      // Rentrer l'association <IdObj, nouvObj> dans la table des
      // "donneesGlobales"
      globalPrlgPCGObjs.put(IdObj, new PrologData(uObject, nouvObj));

      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("execMethod")) { // execMethod(Data,
                          // ClassNameOrObjId,
                          // MethodName,
                          // ParametersList)

      // ou bien execMethod(Data, TypeOfData, ClassNameOrObjId,
      // MethodName, ParametersList)
      // TypeOfData peut etre specifie entre double quote ou non
      // si la methode ne retourne rien, il faut specifier void comme Arg1
      // de execMethod
      ASSERT(
          ((pTermRes.pTerm.size() == 5) || (pTermRes.pTerm.size() == 6)),
          "Error: execMethod takes four or five arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData == null) || typeIsPrimitive(Arg1.pData.typeOfData)),
          "Error: the first argument of execMethod must be a variable, an elementary data or the key word void.\n");

      String typeRetSpec = null;
      int i = 0;

      if (pTermRes.pTerm.size() == 6) {
        i++; // incrementer l'indice de l'arg courant de pTermRes.pTerm

        PrologDataIndexPair Arg1Bis = env.unification
            .valueFromUnifStack(pTermRes.pTerm.getAt(2),
                pTermRes.index);
        typeRetSpec = (String) Arg1Bis.pData.data;

        if (typeRetSpec.charAt(0) == '"') {
          typeRetSpec = typeRetSpec.substring(1,
              typeRetSpec.length() - 1);
        }

        ASSERT(((Arg1Bis.pData != null) && (typeRetSpec
            .equals("Long")
            || typeRetSpec.equals("Double")
            || typeRetSpec.equals("Boolean") || typeRetSpec
            .equals("String"))),
            "Error: the second argument of execMethod must be an elementary data.\n");
      }

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm
          .getAt(2 + i), pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && ((Arg2.pData.typeOfData == uString) || (Arg2.pData.typeOfData == uIdentifier))),
          "Error: argument inconsistent with the signature of execMethod.\n");

      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3 + i), pTermRes.index);
      ASSERT(
          ((Arg3.pData != null) && (Arg3.pData.typeOfData == uString)),
          "Error: argument inconsistent with the signature of execMethod.\n");

      PrologDataIndexPair Arg4 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(4 + i), pTermRes.index);
      ASSERT(((Arg4.pData != null) && (Arg4.pData.typeOfData == uList)),
          "Error: argument inconsistent with the signature of execMethod.\n");

      // 1. Determiner le nom de la classe (ou de l'objet) ? partir du
      // second arg.
      Class classDeMethod = null;
      String NomClassOuObj = (String) Arg2.pData.data;
      Object obj = null;

      if (Arg2.pData.typeOfData == uIdentifier) {
        // A partir de l'ident de l'objet, chercher l'objet et sa classe
        PrologData donTmp = (PrologData) globalPrlgPCGObjs
            .get(NomClassOuObj);
        ASSERT(((donTmp != null) && (donTmp.typeOfData == uObject)),
            "Error : Object unknown.\n");
        obj = donTmp.data;
        classDeMethod = obj.getClass();
      } else {
        NomClassOuObj = NomClassOuObj.substring(1, NomClassOuObj
            .length() - 1);

        try {
          classDeMethod = Class.forName(NomClassOuObj);
        } catch (ClassNotFoundException clNtFdEx) {
          throw new ExecException("Error: the specified class "
              + NomClassOuObj + " is not found.\n");
        }
      }

      // 2. determiner ? partir de arg3 le nom de la m?thode appel?
      String nomMethod = (String) Arg3.pData.data;
      nomMethod = nomMethod.substring(1, nomMethod.length() - 1);

      // 3bis determiner le type des arguments de la m?thode et former
      // le vecteur Class[] vectTypArgs
      // 3bis2. Construire le vecteurs des objets qui seront les arguments
      // de la methode
      PrologList listArgsMetd = (PrologList) Arg4.pData.data;
      int nbreArgs = 0;
      Object[] vectObjsArgs = null;
      Class[] vectTypArgs = null;

      if ((listArgsMetd != null) && !listArgsMetd.isEmpty()) {
        listArgsMetd = copyAllOfTheListWithUnification(listArgsMetd,
            Arg4.index);
        nbreArgs = listArgsMetd.size();
        vectObjsArgs = new Object[nbreArgs];
        vectTypArgs = new Class[nbreArgs];
        i = 0; // nouvelle utilisation de i

        PrologData uneDon;

        for (Enumeration<PrologData> e = listArgsMetd.elements(); e
            .hasMoreElements(); i++) {
          uneDon = (PrologData) e.nextElement();

          if (uneDon.typeOfData == uString) {
            String st = (String) uneDon.data;
            vectObjsArgs[i] = st.substring(1, st.length() - 1);
          } else {
            vectObjsArgs[i] = uneDon.data;
          }

          vectTypArgs[i] = uneDon.data.getClass();
        }
      }

      // 4. Chercher la m?thode, de la classe ou de l'objet, ? partir de
      // son nom et les classes de ses arg
      Method methodRecherchee = null;

      try {
        methodRecherchee = classDeMethod.getMethod(nomMethod,
            vectTypArgs);
      } catch (NoSuchMethodException nsmex) {
        Method[] vctMtds = classDeMethod.getMethods();
        int tailleVctMtds = vctMtds.length;
        boolean mtdTrouve = false;

        for (int j = 0; (!mtdTrouve && (j < tailleVctMtds)); j++) {
          methodRecherchee = vctMtds[j];

          if (methodRecherchee.getName().equals(nomMethod)) {
            mtdTrouve = true;
          }
        }

        if (!mtdTrouve) {
          throw new ExecException(
              "Error: "
                  + nomMethod
                  + " is not a method of the specified class or object.\n");
        }
      } catch (SecurityException sex) {
        throw new ExecException(
            "Error: "
                + nomMethod
                + " is not a method of the specified class or object.\n");
      }

      // 5. Determiner le type/class de la valeur qui sera retourn?e
      Class classReturnType = methodRecherchee.getReturnType();

      // 6. Invoker la methode et saisir la valeur retourn?e
      Object objRet = null;

      try {
        objRet = methodRecherchee.invoke(obj, vectObjsArgs);
      } catch (InvocationTargetException invTrgtEx) {
        throw new ExecException(
            "Error: problem in the invocation of the method "
                + nomMethod + " .\n");
      } catch (IllegalAccessException illAcEx) {
        throw new ExecException(
            "Error: illegal access during the invocation of the method "
                + nomMethod + " .\n");
      }

      // 7. Traiter l'objet retourn? selon que la m?thode est de type void
      // ;
      // elle ne retourne pas de valeur ou quelle retourne une valeur
      if (objRet == null) { // La methode est de type void

        // Verifier que le programmeur a bien fourni "void" comme Arg1
        // de execMethod
        env.unification.Unif_Stack.pushEmptyRecord();

        if ((Arg1.pData != null)
            && (Arg1.pData.typeOfData == uIdentifier)) {
          String str = (String) Arg1.pData.data;
          resultat = str.equals("void");
          ASSERT(resultat, "Error : The type of the method is void");
        } else {
          ASSERT(false,
              "Error : the method does not return a value; its type is void");
        }
      } else { // Creer une donnee Prolog pour "wrapper" l'objet retourn?

        byte typeDonRet = 0;

        if (typeRetSpec == null) {
          typeDonRet = typeFromClass(classReturnType);
        } else {
          typeDonRet = typeFromString(typeRetSpec);
        }

        PrologData donRes = new PrologData(typeDonRet, objRet);

        // Unifier cette donnee avec le permier argument Arg1
        env.unification.Unif_Stack.pushEmptyRecord();
        resultat = env.unification.unify(donRes, pTermRes.index,
            pTermRes.pTerm.getAt(1), pTermRes.index);
      }

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("createInstance")) { // createInstance(Ident,
                            // Terme);
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: createInstance takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && ((Arg1.pData.typeOfData == uIdentifier) || (Arg1.pData.typeOfData == uString))),
          "Error: the first argument of createInstance must be an identifier.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData != null) && (Arg2.pData.typeOfData == uTerm)),
          "Error: the second argument of createInstance must be a term.\n");

      if (env.program == null) {
        env.io
            .showMessageDialog(
                "No program has been loaded and compiled.\n Only predefined goal (except asserta/z, createInstance, retract and suppress) can be satisfied.",
                "Warning");
        Return_Stack.makeEmpty();

        return resultat;
      }

      PrologRule pRegle = new PrologRule();

      // Par ailleurs, la regle Ident <- Terme sera transformee en :
      // Ident::valSysIdVar <- Terme::valSysIdVar,
      // l'ajout de la variable des deux cotes va nous permettre de
      // resoudre correctement l'heritage...
      // a. transformer Ident en Ident::valSysIdVar; valSysCleBtCp(Ident,
      // valSysIdVar)
      PrologTerm aCple = new PrologTerm();
      PrologData uneDonId = new PrologData(uIdentifier,
          env.compile.valSysCleBtCp);
      aCple.addData(uneDonId); // construction de valSysCleBtCp(

      PrologTerm aTerm1 = new PrologTerm();
      aTerm1.addData(Arg1.pData); // mettre Ident en un Terme

      String ClePaquet = env.compile.valSysGEN
          + env.compile.nameOfArgument(aTerm1, -1);

      aCple.addData(new PrologData(uTerm, aTerm1)); // construction de
                              // valSysCleBtCp(Ident,

      PrologData uneDonVr = new PrologData(uVariable,
          env.compile.valSysIdVar);
      aCple.addData(uneDonVr); // construction de valSysCleBtCp(Ident,
                    // valSysIdVar)
      pRegle.addTerm(aCple);

      // b. remplacer dans pCurRule t2 par t2::valSysIdVar;
      // valSysCleBtCp(t2, valSysIdVar)
      aCple = new PrologTerm();
      aCple.addData(uneDonId);
      aCple.addData(Arg2.pData);
      aCple.addData(uneDonVr);
      pRegle.addTerm(aCple);
      pRules = (RuleVector) env.program.get(ClePaquet);

      if (pRules != null) {
        pRules.addRule(pRegle);
      } else { // un nouveau paquet
        pRules = new RuleVector();
        pRules.addRule(pRegle);
        env.program.put(ClePaquet, pRules);
      }

      programModified = true;
      pRules = null;
      ClePaquet = null;
      pRegle = null;
      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("asserta") || IdPred.equals("assertz")) {
      // asserta/z(Terme, ListeTermes); la liste souvent vide
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: asserta/z takes two arguments.\n"); // asserta/z
                                // doit avoir
                                // deux arg.
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(Arg1.pData != null,
          "Error: the first argument of asserta/z must be bound.\n");

      if ((Arg1.pData.typeOfData == uIdentifier)
          || (Arg1.pData.typeOfData == uCG)) { // Il faut le
                              // transformer en un
                              // term

        PrologTerm unTrm = new PrologTerm();
        unTrm.addData(Arg1.pData);
        Arg1.pData = new PrologData(uTerm, unTrm);
      } else {
        ASSERT(Arg1.pData.typeOfData == uTerm,
            "Error: the first argument of asserta/z must be a term or a CG.\n");
      }

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData != null) && (Arg2.pData.typeOfData == uList)),
          "Error: the second argument of asserta/z must be a list.\n");

      if (env.program == null) {
        String strMessage = "No program has been loaded and compiled.\n Only predefined goal (except asserta/z, createInstance, retract and suppress) can be satisfied.";
        if (!env.bIsApplet) {
          env.io.showMessageDialog(strMessage, "Warning");
        } else {
          env.recordErrorMessage(strMessage);
        }

        Return_Stack.makeEmpty();
        return false;
      }

      PrologRule pRule = new PrologRule();
      pRule.addTerm(assertTerm((PrologTerm) Arg1.pData.data, Arg1.index));
      pLstPrlg = (PrologList) Arg2.pData.data;

      // ******* IMPORTANT : Comme pour term_list; touteLaListe n'est pas
      // appropriee
      // ***** ici; car il faut garder les variables et traiter les
      // structures contenant les variables ..
      // ****** A REVOIR ***************//
      // pLstPrlg = touteLaListe(pLstPrlg, Arg2.niv);
      PrologData uneDon;
      PrologTerm unTrm;

      for (Enumeration<PrologData> e = pLstPrlg.elements(); e.hasMoreElements();) {
        uneDon = (PrologData) e.nextElement();

        if ((uneDon.typeOfData == uIdentifier)
            || (uneDon.typeOfData == uCG)
            || (uneDon.typeOfData == uVariable)) { // Il faut le
                                // transformer
                                // en un term
          unTrm = new PrologTerm();
          unTrm.addData(uneDon);
          pRule.addTerm(assertTerm(unTrm, Arg2.index));
        } else {
          ASSERT((uneDon.typeOfData == uTerm),
              "Error: the second argument of asserta/z must be a list of terms or CG.\n");
          pRule.addTerm(assertTerm((PrologTerm) uneDon.data,
              Arg2.index));
        }
      }

      pLstPrlg = null;
      uneDon = null;

      String ClePaquet = env.compile.nameOfArgument(pRule.getAt(0),
          Arg1.index);
      pRules = (RuleVector) env.program.get(ClePaquet);

      if (pRules != null) {
        if (IdPred.equals("asserta")) { // ajouter au debut du paquet

          try {
            pRules.insertElementAt(pRule, 0);
          } catch (java.lang.ArrayIndexOutOfBoundsException exp) {
            // This could possibly happen
          }
        } else { // ajouter a la fin du paquet
          pRules.addRule(pRule);
        }
      } else { // un nouveau paquet
        pRules = new RuleVector();
        pRules.addRule(pRule);
        env.program.put(ClePaquet, pRules);
      }

      programModified = true;
      pRules = null;
      ClePaquet = null;
      pRule = null;
      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("retract")) { // retract(Terme); eliminer toute
                        // regle dont la tete puisse
                        // s'unifier...
      ASSERT((pTermRes.pTerm.size() == 2),
          "Error: retract takes one argument.\n"); // retract doit
                                // avoir 1 arg.
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(Arg1.pData != null,
          "Error: the argument of retract must be bound.\n");

      if ((Arg1.pData.typeOfData == uIdentifier)
          || (Arg1.pData.typeOfData == uCG)) { // Il faut le
                              // transformer en un
                              // term

        PrologTerm unTrm = new PrologTerm();
        unTrm.addData(Arg1.pData);
        Arg1.pData = new PrologData(uTerm, unTrm);
      } else {
        ASSERT((Arg1.pData.typeOfData == uTerm),
            "Error: the argument of retract must be a term.\n");
      }

      String IdCle = env.compile.nameOfArgument(
          (PrologTerm) Arg1.pData.data, Arg1.index);

      if (env.program == null) {
        env.io
            .showMessageDialog(
                "No program has been loaded and compiled.\n Only predefined goal (except asserta/z, createInstance, retract and suppress) can be satisfied.",
                "Warning");
        Return_Stack.makeEmpty();

        return resultat;
      }

      pRules = (RuleVector) env.program.get(IdCle);

      if (pRules != null) {
        // //env.unification.Unif_Stack.addNewElement(); // une pour la
        // forme initiale
        PrologData Donnee2;
        PrologRule uneRegle;
        int indRegle = 0;

        for (Enumeration<PrologRule> e = pRules.elements(); (e.hasMoreElements() && !resultat);) {
          uneRegle = (PrologRule) e.nextElement();
          env.unification.Unif_Stack.pushEmptyRecord(); // une pour la
                                  // forme
                                  // instanciee

          int TopOfUnification_Stack = env.unification.Unif_Stack
              .indexOfTop();

          Donnee2 = new PrologData(uTerm, uneRegle.getAt(0));
          resultat = env.unification.unify(Donnee2,
              TopOfUnification_Stack, Arg1.pData, Arg1.index);

          if (resultat) {
            pTermRes.pos = -1;
            Return_Stack.push(Exec_Stack.pop());
            uneRegle.myDestroy();
            uneRegle = null;
            pRules.removeElementAt(indRegle);

            if (pRules.isEmpty()) {
              env.program.remove(IdCle);
            }

            programModified = true;
          } else {
            env.unification.Unif_Stack.pop();
            indRegle++;
          }
        } // fin du for (...

        Donnee2 = null;
        uneRegle = null;
      } else {
        resultat = false;
      }

      IdCle = null;
    } else if (IdPred.equals("suppress")) { // suppress(Ident, Nbre), Nbre
                        // designe le nbre d'arg

      // suppress elimine tout le paquet
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: suppress takes two arguments.\n"); // suppress doit
                                // avoir deux
                                // arg.
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && (Arg1.pData.typeOfData == uIdentifier)),
          "Error: the first argument of suppress must be an identifier.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && (Arg2.pData.typeOfData == uNumber)),
          "Error: the second argument of suppress must be an integer.\n");

      if (env.program == null) {
        env.io
            .showMessageDialog(
                "No program has been loaded and compiled.\n Only predefined goal (except asserta/z, createInstance, retract and suppress) can be satisfied.",
                "Warning");
        Return_Stack.makeEmpty();

        return resultat;
      }

      String Strg = env.compile.getTermSlashNumberOfArgumentsString(
          (String) Arg1.pData.data, ((Long) Arg2.pData.data)
              .intValue());
      pRules = (RuleVector) env.program.get(Strg);

      PrologRule uneRegle;

      if (pRules != null) {
        for (Enumeration<PrologRule> e = pRules.elements(); e.hasMoreElements();) {
          uneRegle = (PrologRule) e.nextElement();
          uneRegle.myDestroy();
          uneRegle = null;
        }

        pRules.removeAllElements();
        env.program.remove(Strg);
        programModified = true;
        resultat = true;
        env.unification.Unif_Stack.pushEmptyRecord(); // even if there
                                // was no
                                // unification:
                                // For
                                // homogenizing
                                // with
                                // Retour_Arriere
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      }
    } else if (IdPred.equals("isInstance")) {
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: instance takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && ((Arg1.pData.typeOfData == uIdentifier) || (Arg1.pData.typeOfData == uString))),
          "Error : the first argument of isInstance should be an identifier or a string.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && (Arg2.pData.typeOfData == uIdentifier)),
          "Error : the second argument of isInstance should be an identifier.\n");

      try {
        UnifyCG aUnifyCG = new UnifyCG(env);
        resultat = aUnifyCG.conform(pTermRes.pTerm.getAt(1),
            pTermRes.index, (String) Arg2.pData.data);
      } catch (ExecException exex) {
        resultat = false;
      }

      if (resultat) {
        env.unification.Unif_Stack.pushEmptyRecord(); // even if there
                                // was no
                                // unification:
                                // For
                                // homogenizing
                                // with
                                // Retour_Arriere
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      }
    } else if (IdPred.equals("addInstance")) {
      if (env.typeHierarchy == null) {
        throw new ExecException(
            "Error : No type hierarchy is specified.");
      }

      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: addInstance takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && ((Arg1.pData.typeOfData == uIdentifier) || (Arg1.pData.typeOfData == uString))),
          "Error : the first argument of addInstance should be an identifier or a string.\n");
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && (Arg2.pData.typeOfData == uIdentifier)),
          "Error : the second argument of addInstance should be an identifier.\n");

      env.typeHierarchy.addInstance((String) Arg1.pData.data,
          (String) Arg2.pData.data);
      resultat = true;
      programModified = true;
      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
    } else if (IdPred.equals("free")) { // free(DonneePrlg)
      ASSERT((pTermRes.pTerm.size() == 2),
          "Error: free takes one argument.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      resultat = (Arg1.pData == null);

      if (resultat) {
        env.unification.Unif_Stack.pushEmptyRecord(); // even if there
                                // was no
                                // unification:
                                // For
                                // homogenizing
                                // with
                                // Retour_Arriere
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      }
    } else if (IdPred.equals("val")) { // val(VarLibre, ExpressionPrefixe)
                      // ou

      // val(VarLibre, IdObjet) ou val(IdObj, Expr)
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: val takes two arguments.\n"); // val doit avoir 2
                              // arg.

      // ASSERT((pTermRes.pTerm.getS(1).typDon == uVariable),
      // "Error: the first argument of val must be a free variable.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData == null) || (pTermRes.pTerm.getAt(1).typeOfData == uIdentifier)),
          "Error: the first argument of val must be a free variable or an object identifier.\n");

      PrologData donTmp = null;

      if (pTermRes.pTerm.getAt(2).typeOfData == uIdentifier) {
        String IdObj = (String) pTermRes.pTerm.getAt(2).data;
        donTmp = (PrologData) globalPrlgPCGObjs.get(IdObj);
        ASSERT((donTmp != null), "Error : The object " + IdObj
            + " is unknown.\n");
      } else {
        donTmp = evalExpr(pTermRes.pTerm.getAt(2), pTermRes.index);

        // donTmp = new PrologData(uNumber, nbreRes);
      }

      env.unification.Unif_Stack.pushEmptyRecord();

      if (pTermRes.pTerm.getAt(1).typeOfData == uVariable) {
        resultat = env.unification.unify(pTermRes.pTerm.getAt(1),
            pTermRes.index, donTmp, pTermRes.index);
      } else {
        String IdObj = (String) pTermRes.pTerm.getAt(1).data;
        globalPrlgPCGObjs.put(IdObj, donTmp);
        resultat = true;
      }

      ASSERT((resultat == true),
          "Error: the two arguments of val should be unified");
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
    } else if (IdPred.equals("sup") || IdPred.equals("inf")
        || IdPred.equals("eqv")) {
      ASSERT((pTermRes.pTerm.size() == 3), "Error: " + IdPred
          + " takes two arguments.\n");

      PrologData uneDonTrans1 = evalExpr(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((uneDonTrans1 != null) && (uneDonTrans1.typeOfData == uNumber)),
          "Error : the expression should return a number.");

      Number val1 = (Number) uneDonTrans1.data;

      PrologData uneDonTrans2 = evalExpr(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((uneDonTrans2 != null) && (uneDonTrans2.typeOfData == uNumber)),
          "Error : the expression should return a number.");

      Number val2 = (Number) uneDonTrans2.data;

      if (IdPred.equals("sup")) {
        resultat = val1.doubleValue() > val2.doubleValue();
      } else if (IdPred.equals("inf")) {
        resultat = val1.doubleValue() < val2.doubleValue();
      } else if (IdPred.equals("eqv")) {
        resultat = val1.doubleValue() == val2.doubleValue();
      }

      if (resultat) {
        env.unification.Unif_Stack.pushEmptyRecord(); // even if there
                                // was no
                                // unification:
                                // For
                                // homogenizing
                                // with
                                // Retour_Arriere
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      }
    } else if (IdPred.equals("seed")) {
      ASSERT((pTermRes.pTerm.size() == 2), "Error: " + IdPred
          + " takes one argument.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && (Arg1.pData.typeOfData == uNumber)),
          "Error: the argument of  "
              + IdPred
              + " must be a number between 0 and 2,100,000,000.\n");

      Number val1 = (Number) Arg1.pData.data;
      long val1Long = val1.longValue();
      ASSERT(
          val1Long >= 0 && val1Long <= 2100000000L,
          "Error: the argument of  "
              + IdPred
              + " must be a number between 0 and 2,100,000,000.\n");

      rndRandom.setSeed(val1Long);

      env.unification.Unif_Stack.pushEmptyRecord(); // even if there was
                              // no unification:
                              // For homogenizing
                              // with
                              // Retour_Arriere
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("rnd")) {
      ASSERT((pTermRes.pTerm.size() == 4), "Error: " + IdPred
          + " takes three arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT(
          ((Arg1.pData != null) && (Arg1.pData.typeOfData == uNumber)),
          "Error: the first argument of  "
              + IdPred
              + " must be a number between 0 and 2,100,000,000.\n");

      Number val1 = (Number) Arg1.pData.data;
      long val1Long = val1.longValue();
      ASSERT(
          val1Long >= 0 && val1Long <= 2100000000L,
          "Error: the first argument of  "
              + IdPred
              + " must be a number between 0 and 2,100,000,000.\n");

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(
          ((Arg2.pData != null) && (Arg2.pData.typeOfData == uNumber)),
          "Error: the second argument of  "
              + IdPred
              + " must be a number between 0 and 2,100,000,000.\n");

      Number val2 = (Number) Arg2.pData.data;
      long val2Long = val2.longValue();
      ASSERT(
          val2Long >= 0 && val2Long <= 2100000000L,
          "Error: the second argument of  "
              + IdPred
              + " must be a number between 0 and 2,100,000,000.\n");

      ASSERT(val1Long <= val2Long, "Error: the first argument of  "
          + IdPred
          + " must be less than or equal to the second argument.\n");

      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3), pTermRes.index);
      ASSERT(Arg3.pData == null, "Error: the third argument of  "
          + IdPred + " must be a free variable.\n");

      double randomDouble = rndRandom.nextDouble();
      double myDifference = (double) val2Long - val1Long;
      double mySolutionDouble = (myDifference * randomDouble) + val1Long;
      Double mySolutionDoubleObject = new Double(mySolutionDouble);
      Long mySolutionLong = new Long(mySolutionDoubleObject
          .longValue());
      PrologData aPrologData = new PrologData(uNumber, mySolutionLong);

      env.unification.Unif_Stack.pushEmptyRecord();
      resultat = env.unification.unify(aPrologData, pTermRes.index,
          pTermRes.pTerm.getAt(3), pTermRes.index);
      pTermRes.pos = -1;
      Return_Stack.push(Exec_Stack.pop());
      resultat = true;
    } else if (IdPred.equals("eq")) { // this corresponds to unification
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: eq takes two arguments.\n");
      env.unification.Unif_Stack.pushEmptyRecord();

      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);

      if ((Arg1.pData != null)
          && ((Arg1.pData.typeOfData == uCG) || (Arg1.pData.typeOfData == uConcept))
          && (Arg2.pData != null)
          && ((Arg2.pData.typeOfData == uCG) || (Arg2.pData.typeOfData == uConcept))) {
        resultat = env.unification
            .unify(pTermRes.pTerm.getAt(2), pTermRes.index,
                pTermRes.pTerm.getAt(1), pTermRes.index);
      } else {
        resultat = env.unification
            .unify(pTermRes.pTerm.getAt(1), pTermRes.index,
                pTermRes.pTerm.getAt(2), pTermRes.index);
      }

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("dif")) { // this corresponds to not(eq...))
      ASSERT((pTermRes.pTerm.size() == 3),
          "Error: dif takes two arguments.\n");
      env.unification.Unif_Stack.pushEmptyRecord();
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);

      if ((Arg1.pData != null)
          && ((Arg1.pData.typeOfData == uCG) || (Arg1.pData.typeOfData == uConcept))
          && (Arg2.pData != null)
          && ((Arg2.pData.typeOfData == uCG) || (Arg2.pData.typeOfData == uConcept))) {
        resultat = env.unification
            .unify(pTermRes.pTerm.getAt(2), pTermRes.index,
                pTermRes.pTerm.getAt(1), pTermRes.index);
      } else {
        resultat = env.unification
            .unify(pTermRes.pTerm.getAt(1), pTermRes.index,
                pTermRes.pTerm.getAt(2), pTermRes.index);
      }

      resultat = !resultat;

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
        // env.unification.Unif_Stack.pop();
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("fail")) {
      resultat = false;
    } else if (IdPred.equals("isSubType") || IdPred.equals("isSuperType")) { // isSubType(Type1,
                                          // Type2)
                                          // ou
                                          // isSuperType(Type1,
                                          // Type2)

      if (env.typeHierarchy == null) {
        throw new ExecException(
            "Error : No type hierarchy is specified.");
      }

      ASSERT((pTermRes.pTerm.size() == 3), "Error: " + IdPred
          + " takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT((Arg1.pData.typeOfData == uIdentifier),
          "Error: the first argument of " + IdPred
              + " must be an identifier.\n");

      String Type1 = (String) Arg1.pData.data;
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT((Arg2.pData.typeOfData == uIdentifier),
          "Error: the second argument of " + IdPred
              + " must be an identifier.\n");

      String Type2 = (String) Arg2.pData.data;

      if (IdPred.equals("isSubType")) {
        resultat = env.typeHierarchy.isSubType(Type1, Type2);
      } else {
        resultat = env.typeHierarchy.isSuperType(Type1, Type2);
      }

      if (resultat) {
        env.unification.Unif_Stack.pushEmptyRecord(); // even if there
                                // was no
                                // unification:
                                // For
                                // homogenizing
                                // with
                                // Retour_Arriere
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      }
    } else if (IdPred.equals("immediateSubTypes")
        || IdPred.equals("immediateSuperTypes")
        || IdPred.equals("subTypes") || IdPred.equals("superTypes")) { // oper(Type,
                                        // LstOfTypes)

      if (env.typeHierarchy == null) {
        throw new ExecException(
            "Error : No type hierarchy is specified.");
      }

      ASSERT((pTermRes.pTerm.size() == 3), "Error: " + IdPred
          + " takes two arguments.\n");
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT((Arg1.pData.typeOfData == uIdentifier),
          "Error: the first argument of " + IdPred
              + " must be an identifier.\n");

      String Type = (String) Arg1.pData.data;

      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT(((Arg2.pData == null) || (Arg2.pData.typeOfData == uList)),
          "Error: the second argument of " + IdPred
              + " must be a free variable or a list.\n");

      PrologData L = null;

      if (IdPred.equals("immediateSubTypes")) {
        L = env.typeHierarchy.immediateSubTypes(Type);
      } else if (IdPred.equals("immediateSuperTypes")) {
        L = env.typeHierarchy.immediateSuperTypes(Type);
      } else if (IdPred.equals("subTypes")) {
        L = env.typeHierarchy.subTypes(Type);
      } else {
        L = env.typeHierarchy.superTypes(Type);
      }

      env.unification.Unif_Stack.pushEmptyRecord();
      resultat = env.unification.unify(pTermRes.pTerm.getAt(2),
          pTermRes.index, L, pTermRes.index);

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("maxComSubTypes")
        || IdPred.equals("minComSuperTypes")) { // XComYTypes(Typ1,
                            // Typ2, MaxMinType)
      if (env.typeHierarchy == null) {
        throw new ExecException(
            "Error : No type hierarchy is specified.");
      }

      ASSERT((pTermRes.pTerm.size() == 4), "Error:" + IdPred
          + " takes tree arguments.\n");

      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT((Arg1.pData.typeOfData == uIdentifier),
          "Error: the first argument of " + IdPred
              + " must be an identifier.\n");

      String Type1 = (String) Arg1.pData.data;
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT((Arg2.pData.typeOfData == uIdentifier),
          "Error: the second argument of " + IdPred
              + " must be an identifier.\n");

      String Type2 = (String) Arg2.pData.data;
      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3), pTermRes.index);
      ASSERT(((Arg3.pData == null) || (Arg3.pData.typeOfData == uList)),
          "Error: the third argument of " + IdPred
              + " must be a free variable or a list.\n");

      Vector<String> Types3 = null;

      if (IdPred.equals("maxComSubTypes")) {
        Types3 = env.typeHierarchy.maxComSubTypes(Type1, Type2);
      } else {
        Types3 = env.typeHierarchy.minComSuperTypes(Type1, Type2);
      }

      PrologList aList = new PrologList();
      for (Enumeration<String> e = Types3.elements(); e.hasMoreElements();) {
        String aType = (String) e.nextElement();
        PrologData aDonnee = new PrologData(uIdentifier, aType);
        aList.addData(aDonnee);
      }

      env.unification.Unif_Stack.pushEmptyRecord();
      resultat = env.unification.unify(pTermRes.pTerm.getAt(3),
          pTermRes.index, new PrologData(uList, aList),
          pTermRes.index);

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    } else if (IdPred.equals("maxComSubType")
        || IdPred.equals("minComSuperType")) { // XComYType(Typ1, Typ2,
                            // MaxMinType)

      if (env.typeHierarchy == null) {
        throw new ExecException(
            "Error : No type hierarchy is specified.");
      }

      ASSERT((pTermRes.pTerm.size() == 4), "Error:" + IdPred
          + " takes tree arguments.\n");

      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);
      ASSERT((Arg1.pData.typeOfData == uIdentifier),
          "Error: the first argument of " + IdPred
              + " must be an identifier.\n");

      String Type1 = (String) Arg1.pData.data;
      Arg2 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(2),
          pTermRes.index);
      ASSERT((Arg2.pData.typeOfData == uIdentifier),
          "Error: the second argument of " + IdPred
              + " must be an identifier.\n");

      String Type2 = (String) Arg2.pData.data;
      PrologDataIndexPair Arg3 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(3), pTermRes.index);
      ASSERT(
          ((Arg3.pData == null) || (Arg3.pData.typeOfData == uIdentifier)),
          "Error: the third argument of " + IdPred
              + " must be a free variable or an identifier.\n");

      String Type3 = null;

      if (IdPred.equals("maxComSubType")) {
        Type3 = env.typeHierarchy.maxComSubType(Type1, Type2);
      } else {
        Type3 = env.typeHierarchy.minComSuperType(Type1, Type2);
      }

      env.unification.Unif_Stack.pushEmptyRecord();
      resultat = env.unification.unify(pTermRes.pTerm.getAt(3),
          pTermRes.index, new PrologData(uIdentifier, Type3),
          pTermRes.index);

      if (resultat) {
        pTermRes.pos = -1;
        Return_Stack.push(Exec_Stack.pop());
      } else {
        env.unification.Unif_Stack.pop();
      }
    }

    if (!resultat) {
      pTermRes.pos = 0;
    }

    return resultat;
  }

  /**
   * Dans cette nouvelle version : on cree une instanciation en profondeur du
   * du term. Pour cela, on ecrit le term dans le tampon
   * env.printer.nodeTreeDebug pour avoir la forme instanciee, en chaine de
   * caracteres et ensuite on la compile pour avoir sa representation interne
   ***/
  PrologTerm assertTerm(PrologTerm pTerme, int niv) throws CompileException {
    env.bWriteToDebugTree = true;
    env.printer.alternatePrintString = "";
    env.printer.printTerm(pTerme, niv); // Ecriture dans
                      // alternatePrintString

    PrologTerm trm = env.compile
        .compileTerm(env.printer.alternatePrintString);
    env.printer.alternatePrintString = "";
    env.bWriteToDebugTree = false;
    return trm;
  }

  /***
   * Ancienne def. Son probleme : elle ne fait pas une instanciation en
   * profondeur; mais juste au premier niveau PrologTerm assertTerm(PrologTerm
   * pTerme, int niv) { PrologTerm nouvTerm = new PrologTerm(); PrologData
   * uneDon; PrologDataIndexPair valArg; for (Enumeration e =
   * pTerme.elements(); e.hasMoreElements(); ) { uneDon = (PrologData)
   * e.nextElement(); valArg = env.unification.valeur(uneDon, niv); if
   * (valArg.pDonnee != null) nouvTerm.add(valArg.pDonnee); else
   * nouvTerm.add(uneDon); };
   *
   * return nouvTerm; }
   *******/
  public boolean resatisfyPredicateGoal(TermToBeResolved pTermRes,
      String IdPred) throws ExecException, CompileException {
    boolean resultat = false;
    RuleVector pLocalRules = null;

    if (IdPred.equals("branchOfCG")) {
      PrologDataIndexPair Arg2 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(2), pTermRes.index);
      CG unGC = (CG) Arg2.pData.data;
      Vector<Relation> vctRels = unGC.m_vctRelations;
      int nbreBranch = vctRels.size();

      while ((pTermRes.pos < nbreBranch) && !resultat) {
        env.unification.Unif_Stack.pushEmptyRecord();

        // Creer un CG a partir de la branche/relation courante dans le
        // CG arg2
        CG unGCBranch = createCGBranch((Relation) vctRels
            .elementAt(pTermRes.pos));

        // Inverser les arg de unifier comme pour la primitive "eq"
        resultat = env.unification.unify(
            new PrologData(uCG, unGCBranch), Arg2.index,
            pTermRes.pTerm.getAt(1), pTermRes.index);
        pTermRes.pos++;

        if (resultat) {
          Return_Stack.push(Exec_Stack.pop());
        } else {
          env.unification.Unif_Stack.pop();
        }
      }
    } else if (IdPred.equals("concOfCG")) { // concOfCG(ConceptOUVar, CG)

      PrologDataIndexPair Arg2 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(2), pTermRes.index);
      CG unGC = (CG) Arg2.pData.data;
      Vector<Concept> vctConcepts = unGC.m_vctConcepts;
      int nbreConcs = vctConcepts.size();
      resultat = false;

      PrologDataIndexPair Arg1 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(1), pTermRes.index);

      while ((pTermRes.pos < nbreConcs) && !resultat) {
        env.unification.Unif_Stack.pushEmptyRecord();

        Concept concCour = (Concept) vctConcepts
            .elementAt(pTermRes.pos);

        // Is Arg1 a free variable?
        if (Arg1.pData == null) {
          // Yes, it was a free variable.
          // Therefore, we don't transform it to a CG,
          // since otherwise, we will unify the whole CG.

          // Inverser les arg de unifier comme pour la primitive "eq"
          resultat = env.unification.unify(new PrologData(uConcept,
              concCour), Arg2.index, pTermRes.pTerm.getAt(1),
              pTermRes.index);
        } else {
          // No, it was not a free variable.
          // Therefore, there is no harm done
          // in making a CG out of the concept.

          // Make a CG out of the concept.
          // This is because env.unification.unifier does not do the
          // special variable-substitution magic on uConcept.
          CG gTmp = new CG();
          gTmp.addConcept(concCour);

          // Inverser les arg de unifier comme pour la primitive "eq"
          resultat = env.unification
              .unify(new PrologData(uCG, gTmp), Arg2.index,
                  pTermRes.pTerm.getAt(1), pTermRes.index);
        }
        pTermRes.pos++;

        if (resultat) {
          Return_Stack.push(Exec_Stack.pop());
        } else {
          env.unification.Unif_Stack.pop();
        }
      }
    } else if (IdPred.equals("member")) {
      PrologDataIndexPair Arg2 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(2), pTermRes.index);
      PrologList pLstPrlg = null;
      int Arg2Niv = Arg2.index;

      if (pTermRes.lstMember == null) {
        pLstPrlg = (PrologList) Arg2.pData.data;
      } else {
        pLstPrlg = pTermRes.lstMember;
        Arg2Niv = pTermRes.indLstMember;
      }

      int dernierInd = pLstPrlg.size() - 1;

      boolean finished = false;

      while (!finished && !resultat) {
        while ((pTermRes.pos < dernierInd) && !resultat) {
          env.unification.Unif_Stack.pushEmptyRecord();
          resultat = env.unification.unify(pTermRes.pTerm.getAt(1),
              pTermRes.index, pLstPrlg.getAt(pTermRes.pos),
              Arg2Niv);
          pTermRes.pos++;

          if (resultat) {
            Return_Stack.push(Exec_Stack.pop());
          } else {
            env.unification.Unif_Stack.pop();
          }
        }

        /**
         * Si on arrive au dernier element de la liste et c'est une
         * VarList alors il faut chercher sa valeur et relancer le
         * membre ...
         */
        if (!resultat && (pTermRes.pos == dernierInd)) {
          if (pLstPrlg.getAt(dernierInd).typeOfData == uVarList) {
            PrologDataIndexPair contr = env.unification
                .valueFromUnifStack(pLstPrlg.getAt(dernierInd),
                    Arg2Niv);
            ASSERT((contr.pData != null)
                && (contr.pData.typeOfData == uList),
                "Error: The second argument of member should be a list.\n");
            pLstPrlg = (PrologList) contr.pData.data;
            Arg2Niv = contr.index;
            pTermRes.lstMember = pLstPrlg;
            pTermRes.indLstMember = contr.index;

            dernierInd = pLstPrlg.size() - 1;
            pTermRes.pos = 0;
          } else {
            env.unification.Unif_Stack.pushEmptyRecord(); // pour la
                                    // forme
                                    // instanciee
                                    // de
                                    // membre
            resultat = env.unification.unify(pTermRes.pTerm
                .getAt(1), pTermRes.index, pLstPrlg
                .getAt(dernierInd), Arg2Niv);
            pTermRes.pos++;

            if (resultat) {
              Return_Stack.push(Exec_Stack.pop());
            } else {
              env.unification.Unif_Stack.pop();
            }

            finished = true;
          }
        } else {
          finished = true;
        }
      }

      if (!resultat) {
        pTermRes.lstMember = null;
        pTermRes.indLstMember = 0;
      }
    } else if (IdPred.equals("not")) {
      if (pTermRes.pos == -1) { // dans ce cas, indexInExecStack marque
                    // Return_Stack et non Exec_Stack

        for (int i = Return_Stack.indexOfTop(); ((i > pTermRes.indexInExecStack) && (i >= 0)); i--) {
          Return_Stack.pop(); // en depilant (afin de ne plus les
                    // considerer) les TermRes de PileRetour
          env.unification.Unif_Stack.pop(); // impliquent qu'il faut
                            // faire de meme avec
                            // leur
                            // UnificationRecord
        }
        pTermRes.indexInExecStack = -1;
      }

      // a ce niveau, vctResult = false (par defaut, ce qui est desire)
      // ... et en bas, on mettra pTermPos = 0
    } else if (IdPred.equals("findall")) {
      if (pTermRes.indLstMember != -1) {
        // voir remarque ci-dessous sur indLstMember ..
        // D?piler les trois buts au sommet de Exec_Stack fail,
        // addElemForAll(..), B
        // indLstMember est utilis? ici juste comme un tag indiquant la
        // prochaine fois
        // qu'il faut sauter ce traitement ci
        pTermRes.indLstMember = -1;
        env.unification.Unif_Stack.pushEmptyRecord(); // even if there
                                // was no
                                // unification:
                                // For
                                // homogenizing
                                // with
                                // Retour_Arriere
        env.unification.unify(pTermRes.pTerm.getAt(3), pTermRes.index,
            new PrologData(uList, pTermRes.lstMember),
            pTermRes.index);
        pTermRes.lstMember = null;
        Return_Stack.push(Exec_Stack.pop()); // il s'agit du but
                            // findall(..)
        Exec_Stack.pop(); // depiler But
        Exec_Stack.pop(); // depiler addElemForAll(..)
        Exec_Stack.pop(); // depiler fail

        resultat = true;
      }
    } else if (IdPred.equals("retract")) {
      PrologDataIndexPair Arg1 = env.unification.valueFromUnifStack(
          pTermRes.pTerm.getAt(1), pTermRes.index);
      Arg1 = env.unification.valueFromUnifStack(pTermRes.pTerm.getAt(1),
          pTermRes.index);

      if ((Arg1.pData.typeOfData == uIdentifier)
          || (Arg1.pData.typeOfData == uCG)) { // Il faut le
                              // transformer en un
                              // term

        PrologTerm unTrm = new PrologTerm();
        unTrm.addData(Arg1.pData);
        Arg1.pData = new PrologData(uTerm, unTrm);
      }

      String IdCle = env.compile.nameOfArgument(
          (PrologTerm) Arg1.pData.data, Arg1.index);
      pLocalRules = (RuleVector) env.program.get(IdCle);

      if (pLocalRules != null) {
        // //env.unification.Unif_Stack.addNewElement(); // une pour la
        // forme initiale
        PrologData data2;
        PrologRule aRule;
        int indRegle = 0;

        for (Enumeration<PrologRule> e = pLocalRules.elements(); (e
            .hasMoreElements() && !resultat);) {
          aRule = (PrologRule) e.nextElement();
          env.unification.Unif_Stack.pushEmptyRecord();

          int TopOfUnification_Stack = env.unification.Unif_Stack
              .indexOfTop();

          data2 = new PrologData(uTerm, aRule.getAt(0));
          resultat = env.unification.unify(data2,
              TopOfUnification_Stack, Arg1.pData, Arg1.index);

          if (resultat) {
            Return_Stack.push(Exec_Stack.pop());
            aRule.myDestroy();
            aRule = null;
            pLocalRules.removeElementAt(indRegle);

            if (pLocalRules.isEmpty()) {
              env.program.remove(IdCle);

              // pTermRes.Pos = 0;
            }
            programModified = true;
          } else {
            env.unification.Unif_Stack.pop();
            indRegle++;
          }
        } // fin du for (...

        // if (!vctResult) env.unification.Unif_Stack.Pop();
        data2 = null;
        aRule = null;
      } else {
        resultat = false;
      }

      IdCle = null;
    }

    if (!resultat) {
      pTermRes.pos = 0;
    }

    return resultat;
  }

  PrologData evalExpr(PrologData pDon, int niv) throws ExecException {
    Number aNumber = null;
    PrologDataIndexPair Arg1 = env.unification
        .valueFromUnifStack(pDon, niv);
    ASSERT((Arg1.pData != null),
        "Error: any variable in an expression should have a value.\n");

    if (Arg1.pData.typeOfData == uNumber) {
      aNumber = (Number) Arg1.pData.data;
    } else if (Arg1.pData.typeOfData == uTerm) {
      PrologTerm pTerm = (PrologTerm) Arg1.pData.data;
      String IdTerm = (String) pTerm.getAt(0).data;
      ASSERT((IdTerm.equals("add") || IdTerm.equals("sub")
          || IdTerm.equals("mul") || IdTerm.equals("div")),
          "Error: an operator in an expression must be add, sub, mul or div.\n");
      ASSERT((pTerm.size() == 3),
          "Error: any operator must have two arguments.\n");

      PrologData aDataTrans1 = evalExpr(pTerm.getAt(1), Arg1.index);
      ASSERT(
          ((aDataTrans1 != null) && (aDataTrans1.typeOfData == uNumber)),
          "Error : the operand should be a number.");

      Number val1 = (Number) aDataTrans1.data;

      PrologData aDataTrans2 = evalExpr(pTerm.getAt(2), Arg1.index);
      ASSERT(
          ((aDataTrans2 != null) && (aDataTrans2.typeOfData == uNumber)),
          "Error : the operand should be a number.");

      Number val2 = (Number) aDataTrans2.data;

      if ((val1 instanceof Long) && (val2 instanceof Long)) {
        int nbreEntier = 0;

        if (IdTerm.equals("add")) {
          nbreEntier = val1.intValue() + val2.intValue();
        } else if (IdTerm.equals("sub")) {
          nbreEntier = val1.intValue() - val2.intValue();
        } else if (IdTerm.equals("mul")) {
          nbreEntier = val1.intValue() * val2.intValue();
        }

        aNumber = new Long(nbreEntier);

        if (IdTerm.equals("div")) {
          double nbreDouble = 0.0;
          nbreDouble = val1.doubleValue() / val2.doubleValue();
          aNumber = new Double(nbreDouble);
        }
      } else {
        double nbreDouble = 0.0;

        if (IdTerm.equals("add")) {
          nbreDouble = val1.doubleValue() + val2.doubleValue();
        } else if (IdTerm.equals("sub")) {
          nbreDouble = val1.doubleValue() - val2.doubleValue();
        } else if (IdTerm.equals("mul")) {
          nbreDouble = val1.doubleValue() * val2.doubleValue();
        } else {
          nbreDouble = val1.doubleValue() / val2.doubleValue();
        }

        aNumber = new Double(nbreDouble);
      }
    } else {
      ASSERT(false,
          "Error: an element in an expression is neither a number nor an operator.\n");
    }

    Arg1 = null;

    return new PrologData(uNumber, aNumber);
  }

  public void clear_globalPrlgPCGObjs() {
    globalPrlgPCGObjs.clear(); // Est-ce suffisant pour detruire les objets
                  // aussi ??
  }

  // une liste peut se terminer par un constructeur suivi d'une variable
  // dont la valeur serait une liste, elle meme peut se terminer ...
  // dans certains cas, on aimerait avoir la liste qui contiendrait tous
  // elements des listes "lies" par les constructeurs
  PrologList copyAllOfTheListWithUnification(PrologList aList, int level)
      throws ExecException {
    if (aList.isEmpty()) {
      return aList;
    }

    PrologList newList = new PrologList();
    copyListWithUnification(aList, level, newList);

    PrologData lastElem = (PrologData) aList.lastElement();
    boolean finished = false;
    PrologDataIndexPair ValVarList = null;
    int valLevel = level;
    PrologList aList1 = null;

    while (!finished) {
      ValVarList = env.unification.valueFromUnifStack(lastElem, valLevel);
      valLevel = ValVarList.index;

      if (lastElem.typeOfData == uVarList) {
        if ((ValVarList.pData != null)
            && (ValVarList.pData.typeOfData != uList)) {
          throw new ExecException(
              "The value of the variable after | should be a list.\n");
        } else if (ValVarList.pData != null) {
          // Enlever le dernier element de la liste courante;
          // il represente une varListe qui est remplacee par sa
          // valeur
          // nouvListe.removeElementAt(nouvListe.size() - 1);
          aList1 = (PrologList) ValVarList.pData.data;
          copyListWithUnification(aList1, ValVarList.index, newList);

          try {
            lastElem = (PrologData) aList1.lastElement();
          } catch (Exception expt) {
            finished = true;
          }
        } else {
          throw new ExecException(
              "Warning : The list is partially specified; the variable after | is free.\n");
        }
      } else {
        finished = true;
        newList.addData(ValVarList.pData);
      }
    }

    return newList;
  }

  void copyListWithUnification(PrologList aList, int level, PrologList newList) {
    int indexOfLastElement = aList.size() - 1;

    for (int i = 0; i < indexOfLastElement; i++) {
      PrologDataIndexPair contr = env.unification.valueFromUnifStack(
          (PrologData) aList.elementAt(i), level);
      newList.addData(contr.pData);
    }
  }

  CG createCGBranch(Relation rel) {
    // 1. Creer le CG cadre
    Relation newRelation = new Relation();
    newRelation.m_pdRelationName = rel.m_pdRelationName;

    Concept concSrce = rel.m_concSource;
    Concept newConcSrce = new Concept(concSrce.m_pdType,
              concSrce.m_pdReferent, concSrce.m_pdValue,
              env);
    newConcSrce.addOutgoingRelation(newRelation);
    newRelation.m_concSource = newConcSrce;

    Concept concDest = rel.m_concDestination;
    Concept newConcDest = new Concept(concDest.m_pdType,
              concDest.m_pdReferent, concDest.m_pdValue,
              env);
    newConcDest.addIncomingRelation(newRelation);
    newRelation.m_concDestination = newConcDest;

    Vector<Concept> nouvVctConcs = new Vector<Concept>(2);
    nouvVctConcs.addElement(newConcSrce);
    nouvVctConcs.addElement(newConcDest);

    Vector<Relation> newVctRels = new Vector<Relation>(1);
    newVctRels.addElement(newRelation);

    return new CG(nouvVctConcs, newVctRels);
  }

  boolean isVariableGoal(String strIdVar, PrologData aTerm) {
    env.bWriteToDebugTree = true;
    env.printer.alternatePrintString = "";
    // -1 because we want to "print" the variable
    // and not its value.
    env.printer.printPrologData(aTerm, -1);

    String str = env.printer.alternatePrintString;
    env.printer.alternatePrintString = "";
    env.bWriteToDebugTree = false;

    int indDebStr = str.indexOf(strIdVar);
    boolean valRet = false;

    if (indDebStr >= 0) {
      int taille = strIdVar.length();

      // boolean finished = false;
      char carAvDeb;

      // boolean finished = false;
      char carAprFin;

      while ((indDebStr >= 0) && !valRet) {
        carAvDeb = str.charAt(indDebStr - 1); // En principe, indDebStr
                            // > 0
        carAprFin = str.charAt(indDebStr + taille);

        if (!Character.isLetterOrDigit(carAvDeb) && (carAvDeb != '_')
            && !Character.isLetterOrDigit(carAprFin)
            && (carAprFin != '_')) {
          valRet = true;
        } else {
          indDebStr = str.indexOf(strIdVar, indDebStr + taille);
        }
      }
    }

    return valRet;
  }

  byte typeFromClass(Class<? extends Object> aClass) {
    String strClassName = aClass.getName();
    byte resultType = 0;

    if (strClassName.equals("java.lang.Integer")
        || strClassName.equals("int")
        || strClassName.equals("java.lang.Long")
        || strClassName.equals("long")
        || strClassName.equals("java.lang.Double")
        || strClassName.equals("double")) {
      resultType = uNumber;
    } else if (strClassName.equals("java.lang.Boolean")
        || strClassName.equals("boolean")) {
      resultType = uBoolean;
    } else if (strClassName.equals("java.lang.String")) {
      resultType = uString;
    } else {
      resultType = uObject;
    }

    return resultType;
  }

  byte typeFromString(String nameOfClass) {
    byte result = 0;

    if (nameOfClass.equals("Long") || nameOfClass.equals("Double")) {
      result = uNumber;
    } else if (nameOfClass.equals("Boolean")) {
      result = uBoolean;
    } else if (nameOfClass.equals("String")) {
      result = uString;
    } else {
      result = uObject;
    }

    return result;
  }

  // Check whether type is a primitive type
  // (number, boolean, identifier, string)
  boolean typeIsPrimitive(byte typDon) {
    return ((typDon == uNumber) || (typDon == uBoolean)
        || (typDon == uIdentifier) || (typDon == uString));
  }
 
  String primitiveTypeToString(PrologData pData) throws ExecException {
    ASSERT(typeIsPrimitive(pData.typeOfData),
        "Error: wrong type of PrologData: Should be a number, a boolean, an identifier, or a string.\n");

    switch (pData.typeOfData) {
    case uNumber:
            if (pData.data instanceof Long) {
                Long valLong = ((Long) pData.data);
                return "\"" + valLong.toString() + "\"";
            } else {
                Double valDble = ((Double) pData.data);
                return "\"" + valDble.toString() + "\"";
            }
        case uBoolean: {
            boolean valBool = ((Boolean) pData.data).booleanValue();
            if (valBool) {
              return "\"true\"";
            } else {
              return "\"false\"";
            }
        }

        case uIdentifier:
          return "\"" + (String) pData.data + "\"";
        case uString:
          return (String) pData.data;
    }
   
    ASSERT(false,
        "Unreachable code reached in Resolution.primitiveTypeToString");
   
    return "";
  }
}
TOP

Related Classes of PrologPlusCG.prolog.Resolution

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.