TuPrologEngine.java
/*
* #%L
* prolobjectlink-jpi-tuprolog
* %%
* Copyright (C) 2019 Prolobjectlink Project
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/
package io.github.prolobjectlink.prolog.tuprolog;
import static io.github.prolobjectlink.prolog.PrologLogger.DONT_WORRY;
import static io.github.prolobjectlink.prolog.PrologLogger.FILE_NOT_FOUND;
import static io.github.prolobjectlink.prolog.PrologLogger.IO;
import static io.github.prolobjectlink.prolog.PrologLogger.SYNTAX_ERROR;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import alice.tuprolog.Int;
import alice.tuprolog.InvalidTheoryException;
import alice.tuprolog.Library;
import alice.tuprolog.MalformedGoalException;
import alice.tuprolog.Operator;
import alice.tuprolog.Parser;
import alice.tuprolog.PrimitiveInfo;
import alice.tuprolog.Prolog;
import alice.tuprolog.Struct;
import alice.tuprolog.Term;
import alice.tuprolog.Theory;
import alice.tuprolog.TheoryManager;
import io.github.prolobjectlink.prolog.AbstractEngine;
import io.github.prolobjectlink.prolog.Licenses;
import io.github.prolobjectlink.prolog.PrologClause;
import io.github.prolobjectlink.prolog.PrologEngine;
import io.github.prolobjectlink.prolog.PrologIndicator;
import io.github.prolobjectlink.prolog.PrologOperator;
import io.github.prolobjectlink.prolog.PrologProgram;
import io.github.prolobjectlink.prolog.PrologProvider;
import io.github.prolobjectlink.prolog.PrologQuery;
import io.github.prolobjectlink.prolog.PrologTerm;
import io.github.prolobjectlink.prolog.SyntaxError;
/**
*
* @author Jose Zalacain
* @since 1.0
*/
public class TuPrologEngine extends AbstractEngine implements PrologEngine {
final Prolog engine;
protected TuPrologEngine(PrologProvider provider, Prolog engine) {
super(provider);
this.engine = engine;
}
public void consult(String path) {
try {
Theory theory = new Theory(new FileInputStream(path));
engine.setTheory(theory);
} catch (FileNotFoundException e) {
getLogger().warn(getClass(), FILE_NOT_FOUND + path, e);
getLogger().info(getClass(), DONT_WORRY + path);
} catch (IOException e) {
getLogger().warn(getClass(), IO + path, e);
getLogger().info(getClass(), DONT_WORRY + path);
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR + path, e);
}
}
public void consult(Reader reader) {
BufferedReader bfr = new BufferedReader(reader);
StringBuilder script = new StringBuilder();
try {
String line = bfr.readLine();
while (line != null) {
script.append(line);
script.append("\n");
line = bfr.readLine();
}
engine.setTheory(new Theory("" + script + ""));
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR + script, e);
} catch (IOException e) {
getLogger().warn(getClass(), IO + script, e);
}
}
public void include(String path) {
TheoryManager manager = engine.getTheoryManager();
try {
manager.consult(new Theory(new FileInputStream(path)), true, null);
} catch (FileNotFoundException e) {
getLogger().error(getClass(), FILE_NOT_FOUND + path, e);
} catch (IOException e) {
getLogger().error(getClass(), IO + path, e);
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR + path, e);
}
}
public void include(Reader reader) {
TheoryManager manager = engine.getTheoryManager();
BufferedReader bfr = new BufferedReader(reader);
StringBuilder script = new StringBuilder();
try {
String line = bfr.readLine();
while (line != null) {
script.append(line);
script.append("\n");
line = bfr.readLine();
}
manager.consult(new Theory("" + script + ""), true, null);
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR + script, e);
} catch (IOException e) {
getLogger().warn(getClass(), IO + script, e);
}
}
public void persist(String path) {
PrintWriter writer = null;
try {
writer = new PrintWriter(path);
writer.write(engine.getTheoryManager().getTheory(true));
} catch (IOException e) {
getLogger().warn(getClass(), IO + path, e);
getLogger().info(getClass(), DONT_WORRY + path);
} finally {
if (writer != null) {
writer.close();
}
}
}
public void abolish(String functor, int arity) {
Struct pi = new Struct("/", new Struct(functor), new Int(arity));
engine.getTheoryManager().abolish(pi);
}
public void asserta(String stringClause) {
TheoryManager manager = engine.getTheoryManager();
if (stringClause != null && !clause(stringClause)) {
manager.assertA((Struct) Term.createTerm(stringClause), true, null, false);
}
}
public void asserta(PrologTerm term) {
TheoryManager manager = engine.getTheoryManager();
if (term != null && !clause(term)) {
manager.assertA(fromTerm(term, Struct.class), true, null, false);
}
}
public void asserta(PrologTerm head, PrologTerm... body) {
boolean hasBody = body != null && body.length > 0;
if (hasBody ? !clause(head, body) : !clause(head)) {
TheoryManager manager = engine.getTheoryManager();
manager.assertA(fromTerm(head, body, Struct.class), true, null, false);
}
}
public void assertz(String stringClause) {
TheoryManager manager = engine.getTheoryManager();
if (stringClause != null && !clause(stringClause)) {
manager.assertZ((Struct) Term.createTerm(stringClause), true, null, false);
}
}
public void assertz(PrologTerm term) {
TheoryManager manager = engine.getTheoryManager();
if (term != null && !clause(term)) {
manager.assertZ(fromTerm(term, Struct.class), true, null, false);
}
}
public void assertz(PrologTerm head, PrologTerm... body) {
boolean hasBody = body != null && body.length > 0;
if (hasBody ? !clause(head, body) : !clause(head)) {
TheoryManager manager = engine.getTheoryManager();
manager.assertZ(fromTerm(head, body, Struct.class), true, null, false);
}
}
public boolean clause(String stringClause) {
Term toBeMatched = Term.createTerm(stringClause);
TheoryManager manager = engine.getTheoryManager();
try {
Theory theory = new Theory(manager.getTheory(true));
Iterator<? extends Term> iterator = theory.iterator(engine);
while (iterator.hasNext()) {
Term term = iterator.next();
if (term.match(toBeMatched)) {
return true;
}
}
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR, e);
}
return false;
}
public boolean clause(PrologTerm head) {
TheoryManager manager = engine.getTheoryManager();
try {
Theory theory = new Theory(manager.getTheory(true));
Iterator<? extends Term> iterator = theory.iterator(engine);
while (iterator.hasNext()) {
Term term = iterator.next();
if (term.match(fromTerm(head, Struct.class))) {
return true;
}
}
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR, e);
}
return false;
}
public boolean clause(PrologTerm head, PrologTerm... body) {
TheoryManager manager = engine.getTheoryManager();
try {
Theory theory = new Theory(manager.getTheory(true));
Iterator<? extends Term> iterator = theory.iterator(engine);
while (iterator.hasNext()) {
Term term = iterator.next();
if (term.match(fromTerm(head, body, Struct.class))) {
return true;
}
}
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR, e);
}
return false;
}
public void retract(String stringClause) {
try {
engine.solve("retract(" + stringClause + ").");
} catch (MalformedGoalException e) {
throw new SyntaxError("Syntax error", e);
}
}
public void retract(PrologTerm head) {
retract("" + fromTerm(head, Struct.class) + "");
}
public void retract(PrologTerm head, PrologTerm... body) {
retract("" + fromTerm(head, body, Struct.class) + "");
}
public PrologQuery query(String stringQuery) {
return new TuPrologQuery(this, stringQuery);
}
public PrologQuery query(PrologTerm term) {
return new TuPrologQuery(this, term);
}
public PrologQuery query(PrologTerm[] terms) {
return new TuPrologQuery(this, terms);
}
public PrologQuery query(PrologTerm term, PrologTerm... terms) {
return new TuPrologQuery(this, term, terms);
}
public void operator(int priority, String specifier, String operator) {
engine.getOperatorManager().opNew(operator, specifier, priority);
}
public boolean currentPredicate(String functor, int arity) {
String newFunctor = removeQuoted(functor);
PrologIndicator pi = new TuPrologIndicator(newFunctor, arity);
return currentPredicates().contains(pi);
}
public boolean currentOperator(int priority, String specifier, String operator) {
return engine.getOperatorManager().opPrio(operator, specifier) == priority;
}
public Set<PrologOperator> currentOperators() {
List<Operator> operatorsList = engine.getOperatorManager().getOperators();
Set<PrologOperator> operators = new HashSet<PrologOperator>(operatorsList.size());
for (Operator operator : operatorsList) {
String name = operator.name;
int priority = operator.prio;
String specifier = operator.type;
PrologOperator op = new TuPrologOperator(priority, specifier, name);
operators.add(op);
}
return operators;
}
public Iterator<PrologClause> iterator() {
Collection<PrologClause> cls = new LinkedList<PrologClause>();
Parser parser = new Parser(engine.getTheoryManager().getTheory(true));
for (Iterator<Term> iterator = parser.iterator(); iterator.hasNext();) {
Term term = iterator.next();
if (term instanceof Struct) {
Struct struct = (Struct) term;
if (struct.getName().equals(":-") && struct.getArity() == 2) {
PrologTerm head = toTerm(struct.getArg(0), PrologTerm.class);
PrologTerm body = toTerm(struct.getArg(1), PrologTerm.class);
cls.add(new TuPrologClause(provider, head, body, false, false, false));
} else {
PrologTerm head = toTerm(struct, PrologTerm.class);
cls.add(new TuPrologClause(provider, head, false, false, false));
}
}
}
return new PrologProgramIterator(cls);
}
public int getProgramSize() {
int counter = 0;
Iterator<? extends Term> i = engine.getTheory().iterator(engine);
while (i.hasNext()) {
i.next();
counter++;
}
return counter;
}
@Override
public PrologProgram getProgram() {
return new TuPrologProgram(this);
}
public Set<PrologIndicator> getPredicates() {
Set<PrologIndicator> predicates = new HashSet<PrologIndicator>();
TheoryManager manager = engine.getTheoryManager();
try {
Theory theory = new Theory(manager.getTheory(true));
Iterator<? extends Term> iterator = theory.iterator(engine);
while (iterator.hasNext()) {
Term term = iterator.next();
if (term instanceof Struct) {
Struct struct = (Struct) term;
int arity = struct.getArity();
String functor = struct.getName();
if (functor.equals(":-") && arity == 2) {
Term head = struct.getArg(0);
if (head instanceof Struct) {
Struct headStruct = (Struct) head;
arity = headStruct.getArity();
functor = headStruct.getName();
TuPrologIndicator pi = new TuPrologIndicator(functor, arity);
predicates.add(pi);
}
} else {
TuPrologIndicator pi = new TuPrologIndicator(functor, arity);
predicates.add(pi);
}
}
}
} catch (InvalidTheoryException e) {
getLogger().error(getClass(), SYNTAX_ERROR, e);
}
return predicates;
}
public Set<PrologIndicator> getBuiltIns() {
String[] libraries = engine.getCurrentLibraries();
Set<PrologIndicator> builtins = new HashSet<PrologIndicator>();
for (String libraryName : libraries) {
Library library = engine.getLibrary(libraryName);
Collection<List<PrimitiveInfo>> c = library.getPrimitives().values();
for (List<PrimitiveInfo> list : c) {
for (PrimitiveInfo primitiveInfo : list) {
String key = primitiveInfo.getKey();
String functor = key.substring(0, key.lastIndexOf('/'));
int arity = Integer.parseInt(key.substring(key.lastIndexOf('/') + 1));
TuPrologIndicator pi = new TuPrologIndicator(functor, arity);
builtins.add(pi);
}
}
}
return builtins;
}
public String getLicense() {
return Licenses.LGPL_V3;
}
public String getVersion() {
return TuProlog.VERSION;
}
public final String getVendor() {
return TuProlog.NAME;
}
public String getName() {
return TuProlog.NAME;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((engine == null) ? 0 : engine.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TuPrologEngine other = (TuPrologEngine) obj;
// tu-prolog engine not override equals from object
// current criteria is not null engine instances
return engine != null && other.engine != null;
}
public void dispose() {
if (engine != null) {
engine.clearTheory();
}
}
public final List<String> verify() {
return Arrays.asList("OK");
}
}