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

wip comments --> ProofTreeNode

parent cba9b86d
......@@ -2,6 +2,12 @@ package ch.heiafr.prolograal.builtins;
import ch.heiafr.prolograal.runtime.ProloGraalAtom;
/**
* Class containing the different built-in atoms.
* Unlike built-in predicates, these are meant for internal use.
* @author Martin Spoto
* @see ProloGraalAtom
*/
public final class ProloGraalBuiltinAtoms {
public static final ProloGraalAtom EMPTY_LIST = new ProloGraalAtom(null, "[]");
public static final ProloGraalAtom DOT_OPERATOR = new ProloGraalAtom(null, "'.'");
......
package ch.heiafr.prolograal.builtins.predicates;
import ch.heiafr.prolograal.runtime.ProloGraalClause;
import ch.heiafr.prolograal.runtime.ProloGraalRuntime;
/**
* Abstract base class for built-ins.
* A built-in must inherit from this class and be added to the built-in list to work.
* The built-in list is handled in the installBuiltins method from {@link ProloGraalRuntime}.
* @author Martin Spoto
*/
public abstract class ProloGraalBuiltinClause extends ProloGraalClause {
/**
* Overridable execute method for built-ins.
* May have side effects, like writing or opening a file.
*/
public void execute() {
// default behaviour is to do nothing...
}
/**
* We want the built-ins to override this because otherwise they will lose their "ProloGraalBultinClause" status.
* @return a copy of the built-in
*/
@Override
public abstract ProloGraalClause copy();
}
package ch.heiafr.prolograal.builtins.predicates;
import ch.heiafr.prolograal.runtime.ProloGraalClause;
public abstract class ProloGraalBultinClause extends ProloGraalClause {
public void execute() {
// default behaviour is to do nothing...
}
// we want the built-ins to override this because otherwise they will lose their "ProloGraalBultinClause" status
@Override
public abstract ProloGraalClause copy();
}
......@@ -5,19 +5,32 @@ import ch.heiafr.prolograal.runtime.*;
import java.util.Map;
/**
* @see ProloGraalRuntime for registration of the built-in
* Class representing the var/1(X) built-in predicate.
* Is unifiable only if X is an unbound variable.
* @author Martin Spoto
* @see ProloGraalBuiltinClause
*/
public class ProloGraalVarBuiltin extends ProloGraalBultinClause {
public final class ProloGraalVarBuiltin extends ProloGraalBuiltinClause {
// create a custom head for the predicate so we can customize the unification process
protected static class VarPredicateHead extends ProloGraalStructure {
/**
* Class representing the head of this predicate.
* Necessary to override the unification behaviour.
*/
private static class VarPredicateHead extends ProloGraalStructure {
public VarPredicateHead(Map<ProloGraalVariable, ProloGraalVariable> variables) {
super(variables);
// add the correct functor for this predicate, and an anonymous variable since we do not need it
setFunctor(new ProloGraalAtom(variables, "var"));
addSubterm(new ProloGraalVariable(variables, "_"));
}
/**
* Overrides the default structure unification behaviour.
* Checks that the param has the same functor and exactly one argument, then checks that the argument
* resolves to a variable
* @return true if other has the same functor and exactly one argument, and that argument is an unbound variable
*/
@Override
public boolean unify(ProloGraalTerm<?> other) {
if (other instanceof ProloGraalStructure) {
......@@ -29,6 +42,7 @@ public class ProloGraalVarBuiltin extends ProloGraalBultinClause {
return false;
}
// override the default copy so we do not lose the custom unification behaviour
@Override
public ProloGraalStructure copy(Map<ProloGraalVariable, ProloGraalVariable> variables) {
return new VarPredicateHead(variables);
......@@ -37,10 +51,12 @@ public class ProloGraalVarBuiltin extends ProloGraalBultinClause {
public ProloGraalVarBuiltin() {
super();
// creates our custom head and set it
VarPredicateHead head = new VarPredicateHead(getVariables());
setHead(head);
}
// override the default copy so we do not lose the custom head
@Override
public ProloGraalClause copy() {
return new ProloGraalVarBuiltin();
......
......@@ -5,30 +5,38 @@ import ch.heiafr.prolograal.runtime.*;
import java.io.PrintWriter;
/**
* @see ProloGraalRuntime for registration of the built-in
* Class representing the write/1(X) predicate.
* Writes the string representation of X.
* @author Martin Spoto
* @see ProloGraalBuiltinClause
*/
public class ProloGraalWriteBuiltin extends ProloGraalBultinClause {
public final class ProloGraalWriteBuiltin extends ProloGraalBuiltinClause {
private final PrintWriter writer;
private final ProloGraalContext context;
private ProloGraalVariable arg;
private final PrintWriter writer; // used for outputting
private final ProloGraalContext context; // we keep the context for the copy method
private ProloGraalVariable arg; // the variable X in write(X). We keep it to print it after the unification process
public ProloGraalWriteBuiltin(ProloGraalContext context) {
super();
// get printer from context
this.writer = new PrintWriter(context.getOutput(), true);
this.context = context;
// create the head of this clause. We keep the variable for later use
// create the head of this clause
// since we do not need custom unification, a simple structure is enough
ProloGraalStructure head = new ProloGraalStructure(getVariables());
head.setFunctor(new ProloGraalAtom(getVariables(), "write"));
// we create and store the variable to access it more easily later in the execute method
arg = new ProloGraalVariable(getVariables(), "_");
head.addSubterm(arg);
setHead(head);
}
/**
* Execute the write, printing the string representation of whatever the variable is currently bound to.
*/
@Override
public void execute() {
// will print whatever the variable is currently bound to, i.e. what we want to print
String str = arg.getRootValue().toString();
if(str.startsWith("'") && str.endsWith("'")) {
// strip single quotes
......@@ -38,6 +46,7 @@ public class ProloGraalWriteBuiltin extends ProloGraalBultinClause {
writer.flush();
}
// override the default copy so we do not lose the built-in status
@Override
public ProloGraalClause copy() {
return new ProloGraalWriteBuiltin(context);
......
......@@ -3,6 +3,11 @@ package ch.heiafr.prolograal.exceptions;
import ch.heiafr.prolograal.runtime.ProloGraalTerm;
import com.oracle.truffle.api.nodes.ControlFlowException;
/**
* Class representing an error caused by the non-existence of a clause.
* Thrown when looking for possible clauses for the current goal, and finding nothing.
* @author Martin Spoto
*/
public class ProloGraalExistenceError extends ControlFlowException {
// cannot use built-in because of inheritance from ControlFlowException
......
......@@ -10,6 +10,11 @@ import com.oracle.truffle.api.TruffleLanguage.ContextReference;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
/**
* Class representing the Truffle root node for evaluation of source code.
* Taken and adapted from the SimpleLanguage demo implementation.
* @author Martin Spoto
*/
public final class ProloGraalEvalRootNode extends RootNode {
private final ProloGraalLanguage language;
......@@ -26,14 +31,9 @@ public final class ProloGraalEvalRootNode extends RootNode {
this.reference = language.getContextReference();
}
@Override
protected boolean isInstrumentable() {
return false;
}
@Override
public String getName() {
return "root eval";
return "ProloGraalEvalRootNode";
}
@Override
......
......@@ -19,6 +19,13 @@ import java.util.ArrayDeque;
import java.util.Deque;
import java.util.stream.Collectors;
/**
* Class representing the Truffle root interpreting node.
* Contains the logic to handle user queries on the command line.
* @author Martin Spoto
* @see ProloGraalParserImpl
* @see ProloGraalResolverNode
*/
public class ProloGraalInterpreterNode extends RootNode {
private final ProloGraalLanguage language;
......@@ -32,11 +39,15 @@ public class ProloGraalInterpreterNode extends RootNode {
@Override
public Object execute(VirtualFrame frame) {
// get input/output facilities from current context
PrintWriter writer = new PrintWriter(context.getOutput(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(context.getInput(), StandardCharsets.UTF_8));
// will store the path to the next possible branch of the proof tree for the latest success
Deque<Integer> currentBranches = new ArrayDeque<>();
// store the runtime of the latest query so we can reuse it in case of a redo
ProloGraalRuntime lastRuntime = null;
// used in case of a redo to skip parsing phase
boolean skipParsing = false;
while (true) {
......@@ -44,6 +55,7 @@ public class ProloGraalInterpreterNode extends RootNode {
writer.flush();
String line;
// read the next query
try {
line = reader.readLine();
} catch (IOException ex) {
......@@ -53,16 +65,18 @@ public class ProloGraalInterpreterNode extends RootNode {
writer.println();
if (line == null) {
// readline returns null if EOF
break;
} else if (line.equals("exit.")) {
writer.println("Exiting.");
break;
} else if (line.equals("listing.")) {
// print all clauses in the context runtime
writer.println(context.getRuntime().getClauses().values());
continue;
} else if (line.startsWith("listing ")) {
String filter = line.split("[ .]")[1];
// print all clauses with heads starting with the given filter
// print all clauses with heads starting with the given filter in the context runtime
writer.println(
context.getRuntime()
.getClauses()
......@@ -75,11 +89,23 @@ public class ProloGraalInterpreterNode extends RootNode {
.collect(Collectors.toList()));
continue;
} else if (line.equals("redo.")) {
// triggers a redo instead of a normal parsing
if (lastRuntime == null) {
writer.println("no");
continue;
}
skipParsing = true;
} else if (line.equals("help") || line.equals("help.")) {
writer.println(
"Available commands :\n" +
"\t'exit.' : Exit this interpreter.\n" +
"\t'listing.' : Print all known clauses.\n" +
"\t'listing <name>.' : Print all known clauses starting with <name>.\n" +
"\t'redo.' : Redo the most recent query, finding the next result\n" +
"\t or returning no if no more are found.\n" +
"\t'help.' : Print this help message."
);
continue;
}
Source source = null;
......@@ -94,12 +120,14 @@ public class ProloGraalInterpreterNode extends RootNode {
ProloGraalRuntime runtime;
try {
if (!skipParsing) {
// parse the source to get a runtime
runtime = ProloGraalParserImpl.parseProloGraal(language, source);
lastRuntime = runtime;
} else {
runtime = lastRuntime;
}
} catch (ProloGraalParseError parseError) {
// clear latest runtime on error so we cannot redo
lastRuntime = null;
writer.println(parseError.getMessage());
continue;
......@@ -108,9 +136,11 @@ public class ProloGraalInterpreterNode extends RootNode {
ProloGraalBoolean callResult;
try {
skipParsing = false;
// get the result from the resolver node
callResult =
(ProloGraalBoolean) Truffle.getRuntime().createCallTarget(context.getResolverNode()).call(runtime
, currentBranches);
(ProloGraalBoolean) Truffle.getRuntime()
.createCallTarget(context.getResolverNode())
.call(runtime, currentBranches);
if (currentBranches.isEmpty()) {
// there are no more solutions
lastRuntime = null;
......@@ -122,7 +152,9 @@ public class ProloGraalInterpreterNode extends RootNode {
writer.println();
if (callResult.asBoolean()) {
// result is a success
ProloGraalSuccess success = (ProloGraalSuccess) callResult;
// print all bound variables
for (ProloGraalVariable variable : success.getVariables().values()) {
if (!variable.isBound()) {
// nothing to display
......@@ -130,6 +162,7 @@ public class ProloGraalInterpreterNode extends RootNode {
}
ProloGraalTerm<?> root = variable.getRootValue();
String rootStr;
// special handling for structure to get prettier output
if (root instanceof ProloGraalStructure) {
rootStr = ((ProloGraalStructure) root).toRootString();
} else {
......@@ -141,6 +174,7 @@ public class ProloGraalInterpreterNode extends RootNode {
writer.println();
writer.println(callResult);
}
try {
reader.close();
} catch (IOException ex) {
......
package ch.heiafr.prolograal.nodes;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.builtins.predicates.ProloGraalBultinClause;
import ch.heiafr.prolograal.builtins.predicates.ProloGraalBuiltinClause;
import ch.heiafr.prolograal.exceptions.ProloGraalExistenceError;
import ch.heiafr.prolograal.runtime.*;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
......@@ -12,11 +12,16 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Class representing a node of the proof tree.
* Each node is characterized by its goals.
* @author Martin Spoto
*/
@NodeInfo(shortName = "ProofTreeNode")
public class ProloGraalProofTreeNode extends Node {
private final Map<ProloGraalTerm<?>, List<ProloGraalClause>> clauses;
private final Deque<ProloGraalTerm<?>> goals;
private final Map<ProloGraalTerm<?>, List<ProloGraalClause>> clauses; // reference to the context clauses
private final Deque<ProloGraalTerm<?>> goals; // the goals of this node
public ProloGraalProofTreeNode(Map<ProloGraalTerm<?>, List<ProloGraalClause>> clauses,
Deque<ProloGraalTerm<?>> goals) {
......@@ -24,8 +29,19 @@ public class ProloGraalProofTreeNode extends Node {
this.goals = goals;
}
/**
* Execute this node, creating a new child node containing the current goal list with its first goal replaced by
* its body.
* @param branches in-out parameter containing a list of branches.
* Used to determine the starting point of this node when descending,
* and to store the path to next possible branch when climbing back up the call stack after
* a success is found.
* @throws ProloGraalExistenceError if the context contains no clauses compatible with the first goal
* @return either {@link ProloGraalSuccess} or {@link ProloGraalFailure}, depending on whether this proof tree
* branch ends in a success (empty node) or not
*/
@TruffleBoundary
public ProloGraalBoolean execute(Deque<Integer> branches) {
public ProloGraalBoolean execute(Deque<Integer> branches) throws ProloGraalExistenceError {
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println("ProofTreeNode : " + goals);
......@@ -72,9 +88,9 @@ public class ProloGraalProofTreeNode extends Node {
}
if (branches.isEmpty()) {
if (unifiableClause instanceof ProloGraalBultinClause) {
if (unifiableClause instanceof ProloGraalBuiltinClause) {
// if the clause is a built-in, execute its internal behaviour
((ProloGraalBultinClause) unifiableClause).execute();
((ProloGraalBuiltinClause) unifiableClause).execute();
}
}
......
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