Commit fa171b86 authored by Martin Spoto's avatar Martin Spoto
Browse files

Fix logic of proof tree; fix output not properly getting root values in structures

parent 6c74ca7b
package ch.heiafr.prolograal;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import ch.heiafr.prolograal.builtins.ProloGraalBuiltinNode;
import ch.heiafr.prolograal.nodes.ProloGraalEvalRootNode;
import ch.heiafr.prolograal.parser.ProloGraalParserImpl;
import ch.heiafr.prolograal.runtime.ProloGraalBoolean;
import ch.heiafr.prolograal.runtime.ProloGraalContext;
import ch.heiafr.prolograal.runtime.ProloGraalRuntime;
import ch.heiafr.prolograal.runtime.ProloGraalTerm;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
......@@ -18,13 +20,10 @@ import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import ch.heiafr.prolograal.builtins.ProloGraalBuiltinNode;
import ch.heiafr.prolograal.nodes.ProloGraalEvalRootNode;
import ch.heiafr.prolograal.parser.ProloGraalParserImpl;
import ch.heiafr.prolograal.runtime.ProloGraalBoolean;
import ch.heiafr.prolograal.runtime.ProloGraalContext;
import ch.heiafr.prolograal.runtime.ProloGraalRuntime;
import ch.heiafr.prolograal.runtime.ProloGraalTerm;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@TruffleLanguage.Registration(id = ProloGraalLanguage.ID, name = "Prolog", defaultMimeType = ProloGraalLanguage.MIME_TYPE, characterMimeTypes = ProloGraalLanguage.MIME_TYPE, contextPolicy = ContextPolicy.SHARED, fileTypeDetectors = ProloGraalFileDetector.class)
public class ProloGraalLanguage extends TruffleLanguage<ProloGraalContext> {
......
package ch.heiafr.prolograal.nodes;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.exceptions.ProloGraalExistenceError;
import ch.heiafr.prolograal.parser.ProloGraalParseError;
import ch.heiafr.prolograal.parser.ProloGraalParserImpl;
import ch.heiafr.prolograal.runtime.*;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.exceptions.ProloGraalExistenceError;
import ch.heiafr.prolograal.parser.ProloGraalParseError;
import ch.heiafr.prolograal.parser.ProloGraalParserImpl;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
public class ProloGraalInterpreterNode extends RootNode {
......@@ -66,8 +65,16 @@ public class ProloGraalInterpreterNode extends RootNode {
if(callResult.asBoolean()) {
ProloGraalSuccess success = (ProloGraalSuccess)callResult;
for(ProloGraalVariable variable : success.getVariables().values()) {
if(variable.isBound())
writer.println(variable.getName() + " = " + variable.getRootValue());
if(variable.isBound()) {
ProloGraalTerm<?> root = variable.getRootValue();
String rootStr;
if(root instanceof ProloGraalStructure) {
rootStr = ((ProloGraalStructure) root).toRootString();
} else {
rootStr = root.toString();
}
writer.println(variable.getName() + " = " + rootStr);
}
}
}
writer.println(callResult);
......
package ch.heiafr.prolograal.nodes;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.exceptions.ProloGraalExistenceError;
import ch.heiafr.prolograal.runtime.*;
import com.oracle.truffle.api.nodes.Node;
import java.util.*;
public class ProloGraalProofTreeNode extends Node {
private final Map<ProloGraalTerm<?>, List<ProloGraalClause>> clauses;
private final Deque<ProloGraalTerm<?>> goals;
@Children
private ProloGraalProofTreeNode[] branches;
public ProloGraalProofTreeNode(Map<ProloGraalTerm<?>, List<ProloGraalClause>> clauses, Deque<ProloGraalTerm<?>> goals) {
this.clauses = clauses;
this.goals = goals;
}
public ProloGraalBoolean execute() {
if(ProloGraalLanguage.DEBUG_MODE) {
System.out.println("ProofTreeNode : " + goals);
}
if(goals.isEmpty()) { // leaf node
return new ProloGraalSuccess();
}
ProloGraalTerm<?> currentGoal = goals.getFirst();
List<ProloGraalClause> possibleClauses = clauses.get(currentGoal);
if(possibleClauses == null || possibleClauses.isEmpty()) // if no match, throw an error
throw new ProloGraalExistenceError();
List<ProloGraalProofTreeNode> branches = new ArrayList<>();
for(ProloGraalClause possibleClauseOriginal : possibleClauses) {
ProloGraalClause possibleClause = possibleClauseOriginal.copy();
currentGoal.save();
// if the head of the clause is unifiable with the current goal
if(possibleClause.getHead().unify(currentGoal)) {
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Unified " + currentGoal + " with " + possibleClause.getHead());
}
// create a copy of the current goals
Deque<ProloGraalTerm<?>> newGoals = new ArrayDeque<>(goals);
List<ProloGraalTerm<?>> body = possibleClause.getGoals();
// always remove the first goal since it will be replaced
newGoals.pollFirst();
// no need for distinction between facts and regular clauses
for (ProloGraalTerm<?> term : body) {
newGoals.addFirst(term); // add all the new goals
}
if(new ProloGraalProofTreeNode(clauses, newGoals).execute().asBoolean()) {
return new ProloGraalSuccess();
}
} else {
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Could not unify " + possibleClause.getHead() + " for goal " + currentGoal);
}
}
// undo all changes that the unification may have done
currentGoal.undo();
}
/*
this.branches = new ProloGraalProofTreeNode[branches.size()];
// insert tree branches to the AST
this.branches = this.insert(branches.toArray(this.branches));
for (ProloGraalProofTreeNode branch : branches) {
ProloGraalBoolean r = branch.execute(frame);
if(r.asBoolean())
return r;
}*/
return new ProloGraalFailure();
}
}
package ch.heiafr.prolograal.nodes;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.exceptions.ProloGraalExistenceError;
import ch.heiafr.prolograal.runtime.*;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.nodes.RootNode;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Map;
@NodeInfo(language = "Prolog", description = "Root node that spawns a proof tree")
public final class ProloGraalResolverNode extends RootNode {
private final ProloGraalContext context;
private final Map<ProloGraalTerm<?>, List<ProloGraalClause>> clauses;
@Child
private ProloGraalProofTreeNode treeNode;
protected ProloGraalResolverNode(ProloGraalLanguage language) {
super(language);
this.context = language.getContextReference().get();
......@@ -30,86 +36,16 @@ public final class ProloGraalResolverNode extends RootNode {
ProloGraalTerm<?> head = goalRuntime.getFirstClause().getHead();
ProloGraalBoolean r = resolve(head);
Deque<ProloGraalTerm<?>> goals = new ArrayDeque<>();
goals.push(head);
ProloGraalProofTreeNode proofTreeNode = new ProloGraalProofTreeNode(clauses, goals);
treeNode = this.insert(proofTreeNode); // FIXME handle multiples goals
ProloGraalBoolean r = treeNode.execute();
if(r.asBoolean()) {
r = new ProloGraalSuccess(head.getVariables());
}
return r;
}
private ProloGraalBoolean resolve(ProloGraalTerm<?> goal) {
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Resolving goal " + goal);
}
// get all possible predicates
List<ProloGraalClause> possibleClauses = clauses.get(goal);
if(possibleClauses == null || possibleClauses.isEmpty()) // if no match, throw an error
throw new ProloGraalExistenceError();
// for each possible clause
outer: for(ProloGraalClause clauseIt : possibleClauses) {
ProloGraalClause clause = clauseIt.copy(); // creates a new context for this clause
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Trying " + clause + " to resolve " + goal);
}
// save current states
goal.save();
// if the head of the clause is unifiable with the current goal
if(clause.getHead().isUnifiable(goal)) {
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Unified " + goal + " with " + clause.getHead());
}
if(clause.isFact()) {
// if the clause is a fact, we just need to return a success after restoring states
//goal.isUnifiable(clause.getHead()); // unify again to report variables to parent
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Success for goal : " + goal);
}
return new ProloGraalSuccess();
} else {
// if the clause is a complex clause, we need to iterate over each goals
for(int i = 0; i < clause.getGoalCount(); i++) {
ProloGraalTerm<?> subGoal = clause.getGoals().get(i);
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Resolving subgoal : " + subGoal + " for goal " + goal);
}
if(!resolve(subGoal).asBoolean()) {
// if one of the goals cannot be unified, then this branch is a failure
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Failure for goal : " + goal + " with subgoal : " + subGoal);
}
goal.undo();
continue outer;
}
}
// if we got to this point, every goal has been successfully unified, we can return a success
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Success for goal : " + goal);
}
// unify again to report variables to parent
//goal.isUnifiable(clause.getHead());
return new ProloGraalSuccess();
}
} else {
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Could not unify " + clause + " for goal " + goal);
}
// undo all changes that the unification may have done
goal.undo();
}
}
// we tried every clauses but none was successful
// no need to restore any state
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Failure for goal : " + goal);
}
return new ProloGraalFailure();
}
}
\ No newline at end of file
package ch.heiafr.prolograal.runtime;
import ch.heiafr.prolograal.builtins.ProloGraalBuiltinAtoms;
import java.util.Map;
public final class ProloGraalAtom extends ProloGraalTerm<ProloGraalAtom> {
......@@ -28,11 +26,11 @@ public final class ProloGraalAtom extends ProloGraalTerm<ProloGraalAtom> {
}
@Override
public boolean isUnifiable(ProloGraalTerm<?> other) {
public boolean unify(ProloGraalTerm<?> other) {
if(this.equals(other)) {
return true;
} else if(other instanceof ProloGraalVariable) {
return other.isUnifiable(this);
return other.unify(this);
}
return false;
}
......
package ch.heiafr.prolograal.runtime;
import java.io.InputStream;
import java.io.OutputStream;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.TruffleLanguage.Env;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.nodes.ProloGraalInterpreterNode;
import ch.heiafr.prolograal.nodes.ProloGraalResolverNode;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.TruffleLanguage.Env;
import java.io.InputStream;
import java.io.OutputStream;
public class ProloGraalContext {
......
......@@ -16,9 +16,9 @@ public abstract class ProloGraalNumber<T extends ProloGraalTerm<T>> extends Prol
}
@Override
public boolean isUnifiable(ProloGraalTerm<?> other) {
public boolean unify(ProloGraalTerm<?> other) {
if(other instanceof ProloGraalVariable)
return other.isUnifiable(this);
return other.unify(this);
else
return this.equals(other);
}
......
......@@ -106,16 +106,16 @@ public class ProloGraalStructure extends ProloGraalTerm<ProloGraalStructure> {
}
@Override
public boolean isUnifiable(ProloGraalTerm<?> other) {
public boolean unify(ProloGraalTerm<?> other) {
if (this.equals(other)) {
for (int i = 0; i < this.arity; i++) {
if (!this.subterms.get(i).getRootValue().isUnifiable(((ProloGraalStructure) other).subterms.get(i))) {
if (!this.subterms.get(i).getRootValue().unify(((ProloGraalStructure) other).subterms.get(i))) {
return false;
}
}
return true;
} else if (other instanceof ProloGraalVariable) {
return other.isUnifiable(this);
return other.unify(this);
}
return false;
}
......
package ch.heiafr.prolograal.runtime;
import java.util.Deque;
import java.util.Map;
import com.oracle.truffle.api.interop.TruffleObject;
import java.util.Map;
public abstract class ProloGraalTerm<T extends ProloGraalTerm<T>> implements TruffleObject {
protected int hashCode;
......@@ -27,7 +26,7 @@ public abstract class ProloGraalTerm<T extends ProloGraalTerm<T>> implements Tru
return this;
}
public abstract boolean isUnifiable(ProloGraalTerm<?> other);
public abstract boolean unify(ProloGraalTerm<?> other);
// save current state
public final void save() {
......
......@@ -94,7 +94,7 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
}
@Override
public boolean isUnifiable(ProloGraalTerm<?> other) {
public boolean unify(ProloGraalTerm<?> other) {
if (other instanceof ProloGraalVariable && other == this) {// can always unify to itself
return true;
}
......@@ -112,7 +112,7 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
}
if (this.isBound) {
return this.boundValue.getRootValue().isUnifiable(rootValue);
return this.boundValue.getRootValue().unify(rootValue);
} else {
this.bind(rootValue);
return true;
......
......@@ -18,8 +18,8 @@ yes
X = [a, b]
yes
% concatDL('-'([a, b, c | Xs], Xs), '-'([d, e, f | Ys], Ys), R).
R = '-'([a, b, c, d, e, f | Ys], Ys)
Xs = [d, e, f | Ys]
R = '-'/2([a, b, c, d, e, f | Ys], Ys)
yes
% listSuffix([a,b,c], [b,c]).
yes
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment