Package jp.ac.kobe_u.cs.prolog.lang

Source Code of jp.ac.kobe_u.cs.prolog.lang.Prolog

package jp.ac.kobe_u.cs.prolog.lang;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.PushbackReader;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Hashtable;

/**
* Prolog engine.
*
* @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
* @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
* @version 1.2
*/
public class Prolog implements Serializable {
  /**
   *
   */
  private static final long serialVersionUID = 6067767541544158839L;

  /** Prolog thread */
  private final PrologControl control;

  /** Argument registers */
  public Term[] aregs;

  /** Continuation goal register */
  public Predicate cont;

  /** Choice point frame stack */
  public final CPFStack stack;

  /** Trail stack */
  public final Trail trail;

  /* Push down list */
  // public PushDownList pdl;
  /** Cut pointer */
  public int B0;

  /** Class loader */
  public final PrologClassLoader pcl;

  /** Internal Database */
  public final InternalDatabase internalDB;

  /** Current time stamp of choice point frame */
  protected long CPFTimeStamp;

  /**
   * Exception level of continuation passing loop: <li><code>0</code> for no
   * exception, <li><code>1</code> for <code>halt/0</code>, <li><code>2</code>
   * for <code>freeze/2</code> (not supported yet) </ul>
   */
  public int exceptionRaised;

  /**
   * <font color="red">Not supported yet</font>. Prolog implementation flag:
   * <code>bounded</code>.
   */
  protected boolean bounded = false;

  /** Prolog implementation flag: <code>max_integer</code>. */
  public final static int maxInteger = Integer.MAX_VALUE;

  /** Prolog implementation flag: <code>min_integer</code>. */
  public final static int minInteger = Integer.MIN_VALUE;

  /** Prolog implementation flag: <code>integer_rounding_function</code>. */
  public final static String integerRoundingFunction = "down";

  /**
   * <font color="red">Not supported yet</font>. Prolog implementation flag:
   * <code>char_conversion</code>.
   */
  private String charConversion;

  /** Prolog implementation flag: <code>debug</code>. */
  private String debug;

  /** Prolog implementation flag: <code>max_arity</code>. */
  public final static int maxArity = 255;

  /** Prolog implementation flag: <code>unknown</code>. */
  private String unknown;

  /**
   * <font color="red">Not supported yet</font>. Prolog implementation flag:
   * <code>double_quotes</code>.
   */
  private String doubleQuotes;

  /** Prolog implementation flag: <code>print_stack_trace</code>. */
  private String printStackTrace;

  /**
   * Holds an exception term for <code>catch/3</code> and <code>throw/1</code>
   * .
   */
  private Term exception;

  /** Holds the start time as <code>long</code> for <code>statistics/2</code>. */
  private long startRuntime;

  /**
   * Holds the previous time as <code>long</code> for
   * <code>statistics/2</code>.
   */
  private long previousRuntime;

  /** HashMap for creating a copy of term. */
  public final HashMap<VariableTerm, VariableTerm> copyHash;

  /** The size of the pushback buffer used for creating input streams. */
  public final static int PUSHBACK_SIZE = 3;
  // public static int PUSHBACK_SIZE = 2;

  /** Standard input stream. */
  private transient final PushbackReader userInput;

  /** Standard output stream. */
  private transient final PrintWriter userOutput;

  /** Standard error stream. */
  private transient final PrintWriter userError;

  /** Current input stream. */
  private transient PushbackReader currentInput;

  /** Current output stream. */
  private transient PrintWriter currentOutput;

  /** HashMap for managing input and output streams. */
  private final HashMapOfTerm streamManager;

  /** HashMap for managing internal databases. */
  private final HashMapOfTerm hashManager;

  /** Holds an atom <code>[]<code> (empty list). */
  public final static SymbolTerm Nil = SymbolTerm.makeSymbol("[]");

  /* Some symbols for stream options */
  private final static SymbolTerm SYM_MODE_1 = SymbolTerm.makeSymbol("mode",
      1);
  private final static SymbolTerm SYM_ALIAS_1 = SymbolTerm.makeSymbol(
      "alias", 1);
  private final static SymbolTerm SYM_TYPE_1 = SymbolTerm.makeSymbol("type",
      1);
  private final static SymbolTerm SYM_READ = SymbolTerm.makeSymbol("read");
  private final static SymbolTerm SYM_APPEND = SymbolTerm
      .makeSymbol("append");
  private final static SymbolTerm SYM_INPUT = SymbolTerm.makeSymbol("input");
  private final static SymbolTerm SYM_OUTPUT = SymbolTerm
      .makeSymbol("output");
  private final static SymbolTerm SYM_TEXT = SymbolTerm.makeSymbol("text");
  private final static SymbolTerm SYM_USERINPUT = SymbolTerm
      .makeSymbol("user_input");
  private final static SymbolTerm SYM_USEROUTPUT = SymbolTerm
      .makeSymbol("user_output");
  private final static SymbolTerm SYM_USERERROR = SymbolTerm
      .makeSymbol("user_error");

  /** Constructs new Prolog engine. */
  public Prolog(PrologControl c) {
    control = c;
    aregs = new Term[maxArity];
    cont = null;
    stack = new CPFStack(this);
    trail = new Trail(this);
    // pdl = new PushDownList();
    pcl = new PrologClassLoader();
    internalDB = new InternalDatabase();
    userInput = new PushbackReader(new BufferedReader(
        new InputStreamReader(System.in)), PUSHBACK_SIZE);
    userOutput = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
        System.out)), true);
    userError = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
        System.err)), true);

    copyHash = new HashMap<VariableTerm, VariableTerm>();
    hashManager = new HashMapOfTerm();
    streamManager = new HashMapOfTerm();

    streamManager.put(SYM_USERINPUT, new JavaObjectTerm(userInput));
    streamManager.put(new JavaObjectTerm(userInput), makeStreamProperty(
        SYM_READ, SYM_INPUT, SYM_USERINPUT, SYM_TEXT));
    streamManager.put(SYM_USEROUTPUT, new JavaObjectTerm(userOutput));
    streamManager.put(new JavaObjectTerm(userOutput), makeStreamProperty(
        SYM_APPEND, SYM_OUTPUT, SYM_USEROUTPUT, SYM_TEXT));
    streamManager.put(SYM_USERERROR, new JavaObjectTerm(userError));
    streamManager.put(new JavaObjectTerm(userError), makeStreamProperty(
        SYM_APPEND, SYM_OUTPUT, SYM_USERERROR, SYM_TEXT));
  }

  /** Initializes this Prolog engine. */
  public void init() {
    stack.clear();
    trail.clear();
    // pdl.init();
    B0 = stack.top();
    CPFTimeStamp = Long.MIN_VALUE;

    // Creates an initial choice point frame.
    Term[] noarg = {};
    stack.create(noarg, null);
    stack.setTR(trail.top());
    stack.setTimeStamp(++CPFTimeStamp);
    stack.setBP(new Failure(control));
    stack.setB0(B0);

    exceptionRaised = 0;

    charConversion = "off";
    debug = "off";
    unknown = "error";
    doubleQuotes = "codes";
    printStackTrace = "off";

    exception = SymbolTerm.makeSymbol("$no_ball");
    startRuntime = System.currentTimeMillis();
    previousRuntime = 0;

    userOutput.flush();
    userError.flush();
    currentInput = userInput;
    currentOutput = userOutput;
  }

  /** Sets the top of choice porint stack to <code>B0</code> (cut pointer). */
  public void setB0() {
    B0 = stack.top();
  }

  /** Discards all choice points after the value of <code>i</code>. */
  public void cut(int i) {
    stack.cut(i);
  }

  /** Discards all choice points after the value of <code>B0</code>. */
  public void neckCut() {
    stack.cut(B0);
  }

  /**
   * Returns a copy of term <code>t</code>.
   *
   * @param t
   *            a term to be copied. It must be dereferenced.
   */
  public Term copy(Term t) {
    copyHash.clear();
    return t.copy(this);
  }

  /*
   * public boolean unify(Term a1, Term a2) { Term d1, d2; pdl.init();
   * pdl.push(a1); pdl.push(a2); while (! pdl.empty()) { d1 =
   * pdl.pop().dereference(); d2 = pdl.pop().dereference(); if (d1 != d2) { if
   * (d1.isVariable()) { ((VariableTerm)d1).bind(d2, trail); } else if
   * (d2.isVariable()) { ((VariableTerm)d2).bind(d1, trail); } else if
   * (d2.isList()) { if (! d1.isList()) return false;
   * pdl.push(((ListTerm)d1).cdr()); pdl.push(((ListTerm)d2).cdr());
   * pdl.push(((ListTerm)d1).car()); pdl.push(((ListTerm)d2).car()); } else if
   * (d2.isStructure()) { if (! d1.isStructure()) return false; if (!
   * ((StructureTerm)d1).functor.equals(((StructureTerm)d2).functor)) return
   * false; for (int i=0; i<((StructureTerm)d1).arity; i++) {
   * pdl.push(((StructureTerm)d1).args[i]);
   * pdl.push(((StructureTerm)d2).args[i]); } } else if (! d1.equals(d2)) {
   * return false; } } } return true; }
   */

  /**
   * Do backtrak. This method restores the value of <code>B0</code> and
   * returns the backtrak point in current choice point.
   */
  public Predicate fail() {
    B0 = stack.getB0(); // restore B0
    return stack.getBP(); // execute next clause
  }

  /**
   * Returns the <code>Predicate</code> object refered, respectively,
   * <code>var</code>, <code>Int</code>, <code>flo</code>, <code>con</code>,
   * <code>str</code>, or <code>lis</code>, depending on whether the
   * dereferenced value of argument register <code>areg[1]</code> is a
   * variable, integer, float, atom, compound term, or non-empty list,
   * respectively.
   */
  public Predicate switch_on_term(Predicate var, Predicate Int,
      Predicate flo, Predicate con, Predicate str, Predicate lis) {
    Term arg1 = aregs[1].dereference();
    if (arg1.isVariable()) {
      return var;
    }
    if (arg1.isInteger()) {
      return Int;
    }
    if (arg1.isDouble()) {
      return flo;
    }
    if (arg1.isSymbol()) {
      return con;
    }
    if (arg1.isStructure()) {
      return str;
    }
    if (arg1.isList()) {
      return lis;
    }
    return var;
  }

  /**
   * If the dereferenced value of arugment register <code>areg[1]</code> is an
   * integer, float, atom, or compound term (except for non-empty list), this
   * returns the <code>Predicate</code> object to which its key is mapped in
   * hashtable <code>hash</code>.
   *
   * The key is calculated as follows:
   * <ul>
   * <li>integer - itself
   * <li>float - itself
   * <li>atom - itself
   * <li>compound term - functor/arity
   * </ul>
   *
   * If there is no mapping for the key of <code>areg[1]</code>, this returns
   * <code>otherwise</code>.
   */
  // TODO change to HashMap, also in compiler
  public Predicate switch_on_hash(Hashtable<Term, Predicate> hash,
      Predicate otherwise) {
    Term arg1 = aregs[1].dereference();
    Term key;
    if (arg1.isInteger() || arg1.isDouble() || arg1.isSymbol()) {
      key = arg1;
    } else if (arg1.isStructure()) {
      key = ((StructureTerm) arg1).functor();
    } else {
      throw new SystemException("Invalid argument in switch_on_hash");
    }
    Predicate p = hash.get(key);
    if (p != null) {
      return p;
    } else {
      return otherwise;
    }
  }

  /**
   * Restores the argument registers and continuation goal register from the
   * current choice point frame.
   */
  public void restore() {
    Term[] args = stack.getArgs();
    int i = args.length;
    System.arraycopy(args, 0, aregs, 1, i);
    cont = stack.getCont();
  }

  /** Creates a new choice point frame. */
  public Predicate jtry(Predicate p, Predicate next) {
    int i = p.arity();
    Term[] args = new Term[i];
    System.arraycopy(aregs, 1, args, 0, i);
    CPFStack.CPFEntry entry = stack.new CPFEntry(args, cont);
    stack.add(entry);
    entry.tr = trail.top();
    entry.timeStamp = ++CPFTimeStamp;
    entry.bp = next;
    entry.b0 = B0;
    return p;
  }

  /**
   * Resets all necessary information from the current choice point frame,
   * updates its next clause field to <code>next</code>, and then returns
   * <code>p</code>.
   */
  public Predicate retry(Predicate p, Predicate next) {
    restore();
    trail.unwind(stack.getTR());
    stack.setBP(next);
    return p;
  }

  /**
   * Resets all necessary information from the current choice point frame,
   * discard it, and then returns <code>p</code>.
   */
  public Predicate trust(Predicate p) {
    restore();
    trail.unwind(stack.getTR());
    stack.removeLast();
    return p;
  }

  Term makeStreamProperty(SymbolTerm _mode, SymbolTerm io, SymbolTerm _alias,
      SymbolTerm _type) {
    Term[] mode = { _mode };
    Term[] alias = { _alias };
    Term[] type = { _type };

    Term t = Nil;
    t = new ListTerm(new StructureTerm(SYM_MODE_1, mode), t);
    t = new ListTerm(io, t);
    t = new ListTerm(new StructureTerm(SYM_ALIAS_1, alias), t);
    t = new ListTerm(new StructureTerm(SYM_TYPE_1, type), t);
    return t;
  }

  /** Returns the current time stamp of choice point frame. */
  public long getCPFTimeStamp() {
    return CPFTimeStamp;
  }

  /** Returns the value of Prolog implementation flag: <code>bounded</code>. */
  public boolean isBounded() {
    return bounded;
  }

  /**
   * Returns the value of Prolog implementation flag: <code>max_integer</code>
   * .
   */
  public int getMaxInteger() {
    return maxInteger;
  }

  /**
   * Returns the value of Prolog implementation flag: <code>min_integer</code>
   * .
   */
  public int getMinInteger() {
    return minInteger;
  }

  /**
   * Returns the value of Prolog implementation flag:
   * <code>integer_rounding_function</code>.
   */
  public String getIntegerRoundingFunction() {
    return integerRoundingFunction;
  }

  /**
   * Returns the value of Prolog implementation flag:
   * <code>char_conversion</code>.
   */
  public String getCharConversion() {
    return charConversion;
  }

  /**
   * Sets the value of Prolog implementation flag:
   * <code>char_conversion</code>.
   */
  public void setCharConversion(String mode) {
    charConversion = mode;
  }

  /** Returns the value of Prolog implementation flag: <code>debug</code>. */
  public String getDebug() {
    return debug;
  }

  /** Sets the value of Prolog implementation flag: <code>debug</code>. */
  public void setDebug(String mode) {
    debug = mode;
  }

  /** Returns the value of Prolog implementation flag: <code>max_arity</code>. */
  public int getMaxArity() {
    return maxArity;
  }

  /** Returns the value of Prolog implementation flag: <code>unknown</code>. */
  public String getUnknown() {
    return unknown;
  }

  /** Sets the value of Prolog implementation flag: <code>unknown</code>. */
  public void setUnknown(String mode) {
    unknown = mode;
  }

  /**
   * Returns the value of Prolog implementation flag:
   * <code>double_quotes</code>.
   */
  public String getDoubleQuotes() {
    return doubleQuotes;
  }

  /**
   * Sets the value of Prolog implementation flag: <code>double_quotes</code>.
   */
  public void setDoubleQuotes(String mode) {
    doubleQuotes = mode;
  }

  /**
   * Returns the value of Prolog implementation flag:
   * <code>print_stack_trace</code>.
   */
  public String getPrintStackTrace() {
    return printStackTrace;
  }

  /**
   * Sets the value of Prolog implementation flag:
   * <code>print_stack_trace</code>.
   */
  public void setPrintStackTrace(String mode) {
    printStackTrace = mode;
  }

  /**
   * Returns the value of <code>exception</code>. This is used in
   * <code>catch/3</code>.
   */
  public Term getException() {
    return exception;
  }

  /**
   * Sets the value of <code>exception</code>. This is used in
   * <code>throw/1</code>.
   */
  public void setException(Term t) {
    exception = t;
  }

  /**
   * Returns the value of <code>startRuntime</code>. This is used in
   * <code>statistics/2</code>.
   */
  public long getStartRuntime() {
    return startRuntime;
  }

  /**
   * Returns the value of <code>previousRuntime</code>. This is used in
   * <code>statistics/2</code>.
   */
  public long getPreviousRuntime() {
    return previousRuntime;
  }

  /**
   * Sets the value of <code>previousRuntime</code>. This is used in
   * <code>statistics/2</code>.
   */
  public void setPreviousRuntime(long t) {
    previousRuntime = t;
  }

  /** Returns the standard input stream. */
  public PushbackReader getUserInput() {
    return userInput;
  }

  /** Returns the standard output stream. */
  public PrintWriter getUserOutput() {
    return userOutput;
  }

  /** Returns the standard error stream. */
  public PrintWriter getUserError() {
    return userError;
  }

  /** Returns the current input stream. */
  public PushbackReader getCurrentInput() {
    return currentInput;
  }

  /** Sets the current input stream to <code>in</code>. */
  public void setCurrentInput(PushbackReader in) {
    currentInput = in;
  }

  /** Returns the current output stream. */
  public PrintWriter getCurrentOutput() {
    return currentOutput;
  }

  /** Sets the current output stream to <code>out</code>. */
  public void setCurrentOutput(PrintWriter out) {
    currentOutput = out;
  }

  /** Returns the stream manager. */
  public HashMapOfTerm getStreamManager() {
    return streamManager;
  }

  /** Returns the hash manager. */
  public HashMapOfTerm getHashManager() {
    return hashManager;
  }
}
TOP

Related Classes of jp.ac.kobe_u.cs.prolog.lang.Prolog

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.