Commit 25485c69 authored by Martin Spoto's avatar Martin Spoto
Browse files

More tries to make proof tree work...

parent 6fe83e28
......@@ -3,6 +3,6 @@ package ch.heiafr.prolograal.builtins;
import ch.heiafr.prolograal.runtime.ProloGraalAtom;
public final class ProloGraalBuiltinAtoms {
public static final ProloGraalAtom EMPTY_LIST = new ProloGraalAtom("[]");
public static final ProloGraalAtom DOT_OPERATOR = new ProloGraalAtom("'.'");
public static final ProloGraalAtom EMPTY_LIST = new ProloGraalAtom(null, "[]");
public static final ProloGraalAtom DOT_OPERATOR = new ProloGraalAtom(null, "'.'");
}
\ No newline at end of file
......@@ -72,7 +72,7 @@ public class ProloGraalInterpreterNode extends RootNode {
writer.println(runtime.getFirstClause().getVariables().values().stream().map(Object::toString).collect(Collectors.joining("\n")));
} else if(success.getSuccesses() != null && success.getSuccesses().size() > 0) {
for(ProloGraalSuccess succ : success.getSuccesses()) {
succ.getVariables().forEach(x -> {
succ.getVariables().values().forEach(x -> {
if(x.isBound())
writer.println(x);
});
......
......@@ -2,6 +2,8 @@ package ch.heiafr.prolograal.nodes;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.stream.Collectors;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
......@@ -25,30 +27,40 @@ public final class ProloGraalResolverNode extends RootNode {
public Object execute(VirtualFrame frame) {
ProloGraalRuntime goalRuntime = (ProloGraalRuntime) frame.getArguments()[0];
if (ProloGraalLanguage.DEBUG_MODE)
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("Executing : " + goalRuntime.getFirstClause());
return resolve(goalRuntime.getFirstClause().getHead());
}
ProloGraalBoolean r = resolve(goalRuntime.getFirstClause().getHead());
System.out.println(goalRuntime.getFirstClause().getHead());
return r;
}
private Stack<ProloGraalClause> visitedClauses = new Stack<>();
public ProloGraalBoolean resolve(ProloGraalTerm<?> goal) {
System.out.println("Resolving goal " + goal);
// get all possible predicates
List<ProloGraalClause> possibleClauses = clauses.get(goal);
if(possibleClauses.isEmpty()) // if no match, throw an error
if(possibleClauses == null || possibleClauses.isEmpty()) // if no match, throw an error
throw new ProloGraalExistenceError();
// for each possible clause
for(ProloGraalClause clause : possibleClauses) {
for(ProloGraalClause clauseIt : possibleClauses) {
ProloGraalClause clause = clauseIt.copy(); // creates a new context for this clause
visitedClauses.push(clause);
// save current states
goal.save();
clause.getHead().save();
// if the head of the clause is unifiable with the current goal
if(clause.getHead().isUnifiable(goal)) {
System.out.println("Unified " + goal + " with " + clause.getHead());
if(clause.isFact()) {
// if the clause is a fact, we just need to restore the state !! of the clause !! and return a success
clause.getHead().undo();
// if the clause is a fact, we just need to return a success after restoring states
clause = clauseIt.copy();
goal.isUnifiable(clause.getHead()); // unify again to report variables to parent
System.out.println("Success for goal : " + goal);
return new ProloGraalSuccess();
} else {
......@@ -58,23 +70,21 @@ public final class ProloGraalResolverNode extends RootNode {
subGoal.save();
if(!resolve(subGoal).asBoolean()) {
// if one of the goals cannot be unified, then this branch is a failure
// we need to restore the state of the processed goals
for(int j = 0; j <= i; j++) {
clause.getGoals().get(j).undo();
}
// and signal the failure
System.out.println("Failure for goal : " + goal);
return new ProloGraalFailure();
System.out.println("Failure for goal : " + goal + " with subgoal : " + subGoal);
continue;
}
}
// if we got to this point, every goal has been successfully unified, we can restore the state of every goal and return a success
clause.getGoals().forEach(ProloGraalTerm::undo);
// if we got to this point, every goal has been successfully unified, we can return a success
System.out.println("Success for goal : " + goal);
// unify again to report variables to parent
clause = clauseIt.copy();
goal.isUnifiable(clause.getHead());
return new ProloGraalSuccess();
}
} else {
clause.getHead().undo(); // undo all changes that the unification may have done
// undo all changes that the unification may have done
// ! should be a no-op !
goal.undo();
}
}
......
......@@ -116,7 +116,7 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
*/
@Override
public void enterAtom(ProloGraalParser.AtomContext ctx) {
ProloGraalAtom atom = new ProloGraalAtom(ctx.getText());
ProloGraalAtom atom = new ProloGraalAtom(clauses.peek().getVariables(), ctx.getText());
elements.push(atom);
}
......@@ -124,15 +124,15 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
public void enterNumber(ProloGraalParser.NumberContext ctx) {
String n = ctx.getText();
try {
elements.push(new ProloGraalIntegerNumber(Integer.parseInt(n)));
elements.push(new ProloGraalIntegerNumber(clauses.peek().getVariables(), Integer.parseInt(n)));
} catch (NumberFormatException ex) {
elements.push(new ProloGraalDoubleNumber(Double.parseDouble(n)));
elements.push(new ProloGraalDoubleNumber(clauses.peek().getVariables(), Double.parseDouble(n)));
}
}
@Override
public void enterVariable(ProloGraalParser.VariableContext ctx) {
ProloGraalVariable variable = new ProloGraalVariable(ctx.getText());
ProloGraalVariable variable = new ProloGraalVariable(clauses.peek().getVariables(), ctx.getText());
if(clauses.peek().getVariables().containsKey(variable)) {
elements.push(clauses.peek().getVariables().get(variable)); // add a reference to the previously added one
} else {
......@@ -148,7 +148,7 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
*/
@Override
public void enterComposedTerm(ProloGraalParser.ComposedTermContext ctx) {
elements.push(new ProloGraalStructure());
elements.push(new ProloGraalStructure(clauses.peek().getVariables()));
}
@Override
......@@ -213,7 +213,7 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
@Override
public void enterList(ProloGraalParser.ListContext ctx) {
elements.push(new ProloGraalList());
elements.push(new ProloGraalList(clauses.peek().getVariables()));
}
@Override
......
package ch.heiafr.prolograal.runtime;
import java.util.Map;
public final class ProloGraalAtom extends ProloGraalTerm<ProloGraalAtom> {
private final String name;
public ProloGraalAtom(String name) {
public ProloGraalAtom(Map<ProloGraalVariable, ProloGraalVariable> variables, String name) {
super(variables);
this.name = name;
this.hashCode = name.hashCode();
}
......@@ -33,7 +36,7 @@ public final class ProloGraalAtom extends ProloGraalTerm<ProloGraalAtom> {
}
@Override
public ProloGraalAtom copy() {
return new ProloGraalAtom(this.name);
public ProloGraalAtom copy(Map<ProloGraalVariable, ProloGraalVariable> variables) {
return new ProloGraalAtom(variables, this.name);
}
}
\ No newline at end of file
......@@ -17,6 +17,12 @@ public class ProloGraalClause {
variables = new HashMap<>();
}
public ProloGraalClause(ProloGraalClause other) {
variables = new HashMap<>();
this.head = other.head.copy(variables);
this.goals = other.goals.stream().sequential().map(x -> x.copy(variables)).collect(Collectors.toList());
}
public boolean isFact() {
return goals.size() == 0;
}
......@@ -49,4 +55,8 @@ public class ProloGraalClause {
public String toString() {
return head.toString() + ":-" + goals.stream().map(Object::toString).collect(Collectors.joining(",")) + ".";
}
public ProloGraalClause copy() {
return new ProloGraalClause(this);
}
}
\ No newline at end of file
package ch.heiafr.prolograal.runtime;
import java.util.Map;
public final class ProloGraalDoubleNumber extends ProloGraalNumber<ProloGraalDoubleNumber> {
final double value;
public ProloGraalDoubleNumber(double value) {
public ProloGraalDoubleNumber(Map<ProloGraalVariable, ProloGraalVariable> variables, double value) {
super(variables);
this.value = value;
this.hashCode = Double.hashCode(value);
}
......@@ -29,7 +32,7 @@ public final class ProloGraalDoubleNumber extends ProloGraalNumber<ProloGraalDou
}
@Override
public ProloGraalDoubleNumber copy() {
return new ProloGraalDoubleNumber(this.value);
public ProloGraalDoubleNumber copy(Map<ProloGraalVariable, ProloGraalVariable> variables) {
return new ProloGraalDoubleNumber(variables, this.value);
}
}
\ No newline at end of file
package ch.heiafr.prolograal.runtime;
import java.util.Map;
public final class ProloGraalIntegerNumber extends ProloGraalNumber<ProloGraalIntegerNumber> {
final int value;
public ProloGraalIntegerNumber(int value) {
public ProloGraalIntegerNumber(Map<ProloGraalVariable, ProloGraalVariable> variables, int value) {
super(variables);
this.value = value;
this.hashCode = Integer.hashCode(value);
}
......@@ -29,7 +32,7 @@ public final class ProloGraalIntegerNumber extends ProloGraalNumber<ProloGraalIn
}
@Override
public ProloGraalIntegerNumber copy() {
return new ProloGraalIntegerNumber(this.value);
public ProloGraalIntegerNumber copy(Map<ProloGraalVariable, ProloGraalVariable> variables) {
return new ProloGraalIntegerNumber(variables, this.value);
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package ch.heiafr.prolograal.runtime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import ch.heiafr.prolograal.builtins.ProloGraalBuiltinAtoms;
......@@ -13,12 +14,13 @@ public class ProloGraalList extends ProloGraalTerm<ProloGraalList> {
protected ProloGraalStructure internal;
public ProloGraalList() {
public ProloGraalList(Map<ProloGraalVariable, ProloGraalVariable> variables) {
super(variables);
items = new ArrayList<>();
}
public static ProloGraalList fromInternal(ProloGraalStructure internal) {
ProloGraalList r = new ProloGraalList();
public static ProloGraalList fromInternal(Map<ProloGraalVariable, ProloGraalVariable> variables, ProloGraalStructure internal) {
ProloGraalList r = new ProloGraalList(variables);
while(true) {
if(internal.getFunctor() != ProloGraalBuiltinAtoms.DOT_OPERATOR || internal.getArity() != 2) {
......@@ -27,7 +29,7 @@ public class ProloGraalList extends ProloGraalTerm<ProloGraalList> {
ProloGraalTerm<?> head = internal.getArguments().get(0);
ProloGraalTerm<?> tail = internal.getArguments().get(1);
if(head instanceof ProloGraalStructure && ((ProloGraalStructure)head).getFunctor() == ProloGraalBuiltinAtoms.DOT_OPERATOR) {
r.items.add(ProloGraalList.fromInternal((ProloGraalStructure) head));
r.items.add(ProloGraalList.fromInternal(variables, (ProloGraalStructure) head));
} else {
r.items.add(head);
}
......@@ -58,7 +60,7 @@ public class ProloGraalList extends ProloGraalTerm<ProloGraalList> {
public void buildInteralRepresentation() {
assert items != null && !items.isEmpty();
internal = new ProloGraalStructure();
internal = new ProloGraalStructure(variables);
ProloGraalStructure struct = internal;
internal.setFunctor(ProloGraalBuiltinAtoms.DOT_OPERATOR);
for(int i = 0; i < items.size()-1; i++) {
......@@ -68,7 +70,7 @@ public class ProloGraalList extends ProloGraalTerm<ProloGraalList> {
} else {
struct.addSubterm(item);
}
ProloGraalStructure next = new ProloGraalStructure();
ProloGraalStructure next = new ProloGraalStructure(variables);
next.setFunctor(ProloGraalBuiltinAtoms.DOT_OPERATOR);
struct.addSubterm(next);
struct = next;
......@@ -114,11 +116,11 @@ public class ProloGraalList extends ProloGraalTerm<ProloGraalList> {
}
@Override
public ProloGraalList copy() {
ProloGraalList list = new ProloGraalList();
list.tail = this.tail.copy();
public ProloGraalList copy(Map<ProloGraalVariable, ProloGraalVariable> variables) {
ProloGraalList list = new ProloGraalList(variables);
list.tail = this.tail.copy(variables);
for(ProloGraalTerm<?> item : this.items) {
list.addItem(item.copy());
list.addItem(item.copy(variables));
}
list.buildInteralRepresentation();
return list;
......
package ch.heiafr.prolograal.runtime;
public abstract class ProloGraalNumber<T extends ProloGraalTerm<T>> extends ProloGraalTerm<T> {
import java.util.Map;
public abstract class ProloGraalNumber<T extends ProloGraalTerm<T>> extends ProloGraalTerm<T> {
protected ProloGraalNumber(Map<ProloGraalVariable, ProloGraalVariable> variables) {
super(variables);
}
public abstract double asDouble();
public abstract int asInt();
......
package ch.heiafr.prolograal.runtime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class ProloGraalStructure extends ProloGraalTerm<ProloGraalStructure> {
protected ProloGraalAtom functor;
protected final Map<ProloGraalVariable, ProloGraalVariable> variables;
protected final List<ProloGraalTerm<?>> subterms;
protected int arity;
public ProloGraalStructure() {
public ProloGraalStructure(Map<ProloGraalVariable, ProloGraalVariable> variables) {
super(variables);
this.subterms = new ArrayList<>();
this.variables = new HashMap<>();
}
// private copy constructor
private ProloGraalStructure(ProloGraalAtom functor, List<ProloGraalTerm<?>> subterms, Map<ProloGraalVariable, ProloGraalVariable> variables) {
private ProloGraalStructure(Map<ProloGraalVariable, ProloGraalVariable> variables, ProloGraalAtom functor, List<ProloGraalTerm<?>> subterms) {
super(variables);
this.functor = functor;
this.subterms = subterms;
this.arity = subterms.size();
this.variables = new HashMap<>();
variables.values().forEach(x -> this.variables.put(x, x).copy());
}
public void addSubterm(ProloGraalTerm<?> subterm) {
......@@ -91,10 +88,10 @@ public final class ProloGraalStructure extends ProloGraalTerm<ProloGraalStructur
}
@Override
public ProloGraalStructure copy() {
public ProloGraalStructure copy(Map<ProloGraalVariable, ProloGraalVariable> variables) {
List<ProloGraalTerm<?>> subterms = new ArrayList<>(this.subterms.size());
this.subterms.forEach(x -> subterms.add(x.copy()));
return new ProloGraalStructure(this.functor.copy(), subterms, variables);
this.subterms.forEach(x -> subterms.add(x.copy(variables)));
return new ProloGraalStructure(variables, this.functor.copy(variables), subterms);
}
// save current state
......
package ch.heiafr.prolograal.runtime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ProloGraalSuccess extends ProloGraalBoolean {
private ProloGraalClause clause;
private List<ProloGraalVariable> variables;
private Map<ProloGraalVariable, ProloGraalVariable> variables;
private List<ProloGraalSuccess> successes;
......@@ -16,9 +18,10 @@ public class ProloGraalSuccess extends ProloGraalBoolean {
public ProloGraalSuccess(ProloGraalClause clause) {
this.clause = clause;
this.variables = new ArrayList<>(clause.getVariables().size());
this.variables = new HashMap<>(clause.getVariables().size());
for(ProloGraalVariable variable : clause.getVariables().values()) {
this.variables.add(variable.copy());
ProloGraalVariable var2 = variable.copy(variables);
this.variables.put(var2, var2);
}
}
......@@ -30,7 +33,7 @@ public class ProloGraalSuccess extends ProloGraalBoolean {
return this.successes;
}
public List<ProloGraalVariable> getVariables() {
public Map<ProloGraalVariable, ProloGraalVariable> getVariables() {
return this.variables;
}
......
package ch.heiafr.prolograal.runtime;
import java.util.Map;
import com.oracle.truffle.api.interop.TruffleObject;
public abstract class ProloGraalTerm<T extends ProloGraalTerm<T>> implements TruffleObject {
protected int hashCode;
// the variable pool
protected final Map<ProloGraalVariable, ProloGraalVariable> variables;
protected ProloGraalTerm(Map<ProloGraalVariable, ProloGraalVariable> variables) {
this.variables = variables;
}
@Override
public abstract boolean equals(Object obj);
......@@ -25,6 +34,10 @@ public abstract class ProloGraalTerm<T extends ProloGraalTerm<T>> implements Tru
}
public abstract T copy();
public Map<ProloGraalVariable, ProloGraalVariable> getVariables() {
return variables;
}
public abstract T copy(Map<ProloGraalVariable, ProloGraalVariable> variables);
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package ch.heiafr.prolograal.runtime;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Map;
import ch.heiafr.prolograal.ProloGraalLanguage;
......@@ -13,19 +14,25 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
private final String name;
private boolean isBound = false;
private ProloGraalTerm<?> boundValue;
private ProloGraalVariable parent; // used to indroduce a double link when binding variables
public ProloGraalVariable(String name) {
public ProloGraalVariable(Map<ProloGraalVariable, ProloGraalVariable> variables, String name) {
super(variables);
if (name.startsWith("_")) {
name = "_" + anonymousVariableSuffix++;
}
this.name = name;
this.hashCode = name.hashCode();
variables.put(this, this);
}
public ProloGraalVariable(ProloGraalVariable other) {
public ProloGraalVariable(Map<ProloGraalVariable, ProloGraalVariable> variables, ProloGraalVariable other) {
super(variables);
this.name = other.name;
this.isBound = other.isBound;
this.boundValue = other.boundValue.copy();
if(other.isBound)
this.boundValue = other.boundValue.copy(variables);
variables.put(this, this);
}
public ProloGraalTerm<?> getValue() {
......@@ -35,7 +42,16 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
return this;
}
private void signalParent(ProloGraalTerm<?> other) {
if(this.parent != null) {
System.out.println(this + " signaling to " + this.parent);
parent.bind(other);
parent.signalParent(other);
}
}
public void bind(ProloGraalTerm<?> other) {
// recursion check
if (other instanceof ProloGraalVariable) {
ProloGraalVariable otherVar = (ProloGraalVariable) other;
if (otherVar.isBound && otherVar.boundValue == this) {
......@@ -46,8 +62,13 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
}
this.isBound = true;
this.boundValue = other;
if (ProloGraalLanguage.DEBUG_MODE)
System.out.println(name + " = " + other);
if(other instanceof ProloGraalVariable) {
((ProloGraalVariable)other).parent = this;
}
signalParent(other);
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println(name + " = " + other + "<@" + System.identityHashCode(variables) + ">");
}
}
public void unbind() {
......@@ -62,15 +83,15 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
@Override
public String toString() {
if (this.isBound) {
/*if (this.isBound) {
if (boundValue instanceof ProloGraalVariable) {
ProloGraalVariable otherVar = (ProloGraalVariable) boundValue;
if (otherVar.isBound) {
return this.name + " = " + otherVar.boundValue.toString();
}
}
}
return this.name + (this.isBound ? " = " + boundValue.toString() : "");
}*/
return this.name + (this.isBound ? " = " + boundValue.toString() : "") + " <@" + System.identityHashCode(variables) + ">";
}
@Override
......@@ -88,6 +109,8 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
return true;
}
} else {
if(ProloGraalLanguage.DEBUG_MODE)
System.out.println("Already bound :" + this.toString() + ", trying to unify to : " + other.toString());
return this.boundValue.isUnifiable(other);
}
} else {
......@@ -96,9 +119,17 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
}
}
/**
* Creates a copy of this variable if it isn't already present in the current context.
* If it is already present, return a reference to the already existing variable.
*/
@Override
public ProloGraalVariable copy() {
return new ProloGraalVariable(this);
public ProloGraalVariable copy(Map<ProloGraalVariable, ProloGraalVariable> variables) {
if (variables.containsKey(this)) {
return variables.get(this);
} else {
return new ProloGraalVariable(variables, this);
}
}
public boolean isBound() {
......@@ -108,17 +139,14 @@ public final class ProloGraalVariable extends ProloGraalTerm<ProloGraalVariable>
// save current state
@Override
public void save() {