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

Merge branch 'master' into ci-test

parents a94e1aba 12713ba4
Pipeline #9453 passed with stage
in 31 seconds
......@@ -10,7 +10,7 @@ cp -f "$prefix.g4" ".antlr/$prefix.g4"
cd .antlr
# run ANTLR
java -cp $PROJECT_ROOT/antlr-4.7.1-complete.jar org.antlr.v4.Tool -package ch.heiafr.prolograal.parser -no-listener "ProloGraal.g4"
java -cp $PROJECT_ROOT/antlr-4.7.1-complete.jar org.antlr.v4.Tool -package ch.heiafr.prolograal.parser "ProloGraal.g4"
#java -cp $PROJECT_ROOT/antlr-4.7.1-complete.jar org.antlr.v4.Tool "ProloGraal.g4"
#javac -cp $PROJECT_ROOT/antlr-4.7.1-complete.jar *.java
......
......@@ -9,14 +9,6 @@
<artifactId>prolograal</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
......@@ -97,5 +89,10 @@
<artifactId>antlr4-runtime</artifactId>
<version>4.7</version>
</dependency>
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>3.9.0</version>
</dependency>
</dependencies>
</project>
......@@ -20,8 +20,9 @@ import com.oracle.truffle.api.source.SourceSection;
import ch.heiafr.prolograal.builtins.ProloGraalBuiltinNode;
import ch.heiafr.prolograal.nodes.ProloGraalEvalRootNode;
import ch.heiafr.prolograal.parser.ProloGraalParser;
import ch.heiafr.prolograal.parser.ProloGraalParserImpl;
import ch.heiafr.prolograal.runtime.ProloGraalContext;
import ch.heiafr.prolograal.runtime.ProloGraalTerm;
@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> {
......@@ -36,22 +37,19 @@ public class ProloGraalLanguage extends TruffleLanguage<ProloGraalContext> {
@Override
protected ProloGraalContext createContext(Env env) {
return new ProloGraalContext();
return new ProloGraalContext(this, env);
}
@Override
protected CallTarget parse(ParsingRequest request) throws Exception {
Source source = request.getSource();
Map<String, RootCallTarget> functions = null;
/*
* Parse the provided source. At this point, we do not have a SLContext yet. Registration of
* the functions with the SLContext happens lazily in SLEvalRootNode.
*/
List<ProloGraalTerm> clauses = null;
if (request.getArgumentNames().isEmpty()) {
functions = ProloGraalParser.parseProloGraal(this, source);
clauses = ProloGraalParserImpl.parseProloGraal(this, source);
}
RootNode eval = new ProloGraalEvalRootNode(this, null, functions);
RootNode eval = new ProloGraalEvalRootNode(this, clauses);
return Truffle.getRuntime().createCallTarget(eval);
}
......@@ -86,6 +84,9 @@ public class ProloGraalLanguage extends TruffleLanguage<ProloGraalContext> {
// FIXME when all types are declared
public static String toString(Object value) {
try {
if (value == null) {
return "ANY";
}
InteropLibrary interop = InteropLibrary.getFactory().getUncached(value);
if (interop.isString(value)) {
return interop.asString(value);
......@@ -122,7 +123,7 @@ public class ProloGraalLanguage extends TruffleLanguage<ProloGraalContext> {
return null;
}
private static final List<NodeFactory<? extends ProloGraalBuiltinNode>> EXTERNAL_BUILTINS = Collections.synchronizedList(new ArrayList());
private static final List<NodeFactory<? extends ProloGraalBuiltinNode>> EXTERNAL_BUILTINS = Collections.synchronizedList(new ArrayList<>());
public static void installBuiltin(NodeFactory<? extends ProloGraalBuiltinNode> builtin) {
EXTERNAL_BUILTINS.add(builtin);
......
package ch.heiafr.prolograal.nodes;
public abstract class ProloGraalAtomNode extends ProloGraalTermNode {
private String value;
public ProloGraalAtomNode(String value) {
this.value = value;
}
@Override
public String toString() {
return "ProloGraalAtomNode(" + value + ")";
}
}
\ No newline at end of file
package ch.heiafr.prolograal.nodes;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.nodes.Node;
public abstract class ProloGraalClauseNode extends Node {
}
\ No newline at end of file
package ch.heiafr.prolograal.nodes;
import java.util.Map;
import java.util.Arrays;
import java.util.List;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleContext;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.RootNode;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.runtime.ProloGraalContext;
import ch.heiafr.prolograal.runtime.ProloGraalTerm;
/**
* This class performs two additional tasks:
*
* <ul>
* <li>Lazily registration of functions on first execution. This fulfills the semantics of
* "evaluating" source code in SL.</li>
* <li>Conversion of arguments to types understood by SL. The SL source code can be evaluated from a
* different language, i.e., the caller can be a node from a different language that uses types not
* understood by SL.</li>
* </ul>
*/
public final class ProloGraalEvalRootNode extends RootNode {
private final Map<String, RootCallTarget> functions;
private final ProloGraalLanguage language;
private final List<ProloGraalTerm> clauses;
@CompilationFinal
private boolean registered;
......@@ -35,12 +30,13 @@ public final class ProloGraalEvalRootNode extends RootNode {
@Child
private DirectCallNode mainCallNode;
public ProloGraalEvalRootNode(ProloGraalLanguage language, RootCallTarget rootFunction,
Map<String, RootCallTarget> functions) {
public ProloGraalEvalRootNode(ProloGraalLanguage language, List<ProloGraalTerm> clauses) {
super(null); // internal frame
this.functions = functions;
this.mainCallNode = rootFunction != null ? DirectCallNode.create(rootFunction) : null;
this.clauses = clauses;
this.mainCallNode = null;
this.language = language;
this.reference = language.getContextReference();
System.out.println("ProloGraalEvalRootNode()");
}
@Override
......@@ -60,14 +56,22 @@ public final class ProloGraalEvalRootNode extends RootNode {
@Override
public Object execute(VirtualFrame frame) {
/* Lazy registrations of functions on first execution. */
System.out.println("ProloGraalEvalRootNode.execute" + Arrays.toString(frame.getArguments()));
/* Lazy registrations of clauses on first execution. */
if (!registered) {
/* Function registration is a slow-path operation that must not be compiled. */
CompilerDirectives.transferToInterpreterAndInvalidate();
reference.get().getFunctionRegistry().register(functions);
reference.get().registerClauses(clauses);
ProloGraalInterpreterNode interpreterNode = new ProloGraalInterpreterNode(language);
ProloGraalResolverNode resolverNode = new ProloGraalResolverNode(language);
reference.get().registerInterpreter(interpreterNode);
reference.get().registerResolver(resolverNode);
registered = true;
}
return new Object(); // FIXME
return Truffle.getRuntime().createCallTarget(reference.get().getInterpreterNode()).call();
}
}
package ch.heiafr.prolograal.nodes;
import java.io.IOException;
import java.util.List;
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 org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.UserInterruptException;
import org.jline.reader.impl.history.DefaultHistory;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.parser.ProloGraalParseError;
import ch.heiafr.prolograal.parser.ProloGraalParserImpl;
import ch.heiafr.prolograal.runtime.ProloGraalContext;
import ch.heiafr.prolograal.runtime.ProloGraalFailure;
import ch.heiafr.prolograal.runtime.ProloGraalSuccess;
import ch.heiafr.prolograal.runtime.ProloGraalTerm;
public class ProloGraalInterpreterNode extends RootNode {
private final ProloGraalLanguage language;
private final ProloGraalContext context;
public ProloGraalInterpreterNode(ProloGraalLanguage language) {
super(language);
this.language = language;
this.context = language.getContextReference().get();
}
@Override
public Object execute(VirtualFrame frame) {
LineReader reader = LineReaderBuilder.builder().history(new DefaultHistory()).build();
while(true) {
try {
String line = reader.readLine("?- ");
Source source = Source.newBuilder("pl", line, null).build();
try {
List<ProloGraalTerm> terms = ProloGraalParserImpl.parseProloGraal(language, source);
if(terms.size() > 0) {
if(terms.get(0).toString().equals("exit")) break;
System.out.println(Truffle.getRuntime().createCallTarget(context.getResolverNode()).call(terms));
}
} catch(ProloGraalParseError parseError) {
System.err.println(parseError.getMessage());
}
} catch (UserInterruptException ex) {
ex.printStackTrace();
return new ProloGraalFailure();
}
}
return new ProloGraalSuccess();
}
}
\ No newline at end of file
package ch.heiafr.prolograal.nodes;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeInfo;
@NodeInfo(language = "Prolog", description = "The abstract base node for all Prolog nodes.")
public abstract class ProloGraalNode extends Node {
}
\ No newline at end of file
package ch.heiafr.prolograal.nodes;
import java.util.List;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
import ch.heiafr.prolograal.ProloGraalLanguage;
import ch.heiafr.prolograal.runtime.ProloGraalBoolean;
import ch.heiafr.prolograal.runtime.ProloGraalContext;
import ch.heiafr.prolograal.runtime.ProloGraalTerm;
public final class ProloGraalResolverNode extends RootNode {
private final ProloGraalContext context;
private final List<ProloGraalTerm> terms;
protected ProloGraalResolverNode(ProloGraalLanguage language) {
super(language);
this.context = language.getContextReference().get();
terms = context.getClauses();
}
@Override
public Object execute(VirtualFrame frame) {
@SuppressWarnings("unchecked")
ProloGraalTerm goal = ((List<ProloGraalTerm>) frame.getArguments()[0]).get(0); // TODO do this more cleanly
System.out.println("Executing : " + goal);
return ProloGraalBoolean.fromBoolean(terms.stream().anyMatch(x -> x.equals(goal)));
}
}
\ No newline at end of file
package ch.heiafr.prolograal.nodes;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
public abstract class ProloGraalTermNode extends ProloGraalNode {
}
\ No newline at end of file
grammar ProloGraal;
@parser::header
{
// DO NOT MODIFY - generated from ProloGraal.g4
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.RootCallTarget;
import ch.heiafr.prolograal.ProloGraalLanguage;
}
@lexer::header
{
// DO NOT MODIFY - generated from ProloGraal.g4
}
@parser::members
{
private ProloGraalNodeFactory factory;
private Source source;
private static final class BailoutErrorListener extends BaseErrorListener {
private final Source source;
BailoutErrorListener(Source source) {
this.source = source;
}
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throwParseError(source, line, charPositionInLine, (Token) offendingSymbol, msg);
}
}
public void SemErr(Token token, String message) {
assert token != null;
throwParseError(source, token.getLine(), token.getCharPositionInLine(), token, message);
}
private static void throwParseError(Source source, int line, int charPositionInLine, Token token, String message) {
int col = charPositionInLine + 1;
String location = "-- line " + line + " col " + col + ": ";
int length = token == null ? 1 : Math.max(token.getStopIndex() - token.getStartIndex(), 0);
throw new ProloGraalParseError(source, line, col, length, String.format("Error(s) parsing script:%n" + location + message));
}
public static Map<String, RootCallTarget> parseProloGraal(ProloGraalLanguage language, Source source) {
ProloGraalLexer lexer = new ProloGraalLexer(CharStreams.fromString(source.getCharacters().toString()));
ProloGraalParser parser = new ProloGraalParser(new CommonTokenStream(lexer));
lexer.removeErrorListeners();
parser.removeErrorListeners();
BailoutErrorListener listener = new BailoutErrorListener(source);
lexer.addErrorListener(listener);
parser.addErrorListener(listener);
parser.factory = new ProloGraalNodeFactory(language, source);
parser.source = source;
parser.prolograal();
return parser.factory.getAllFunctions();
}
}
// parser
prolograal
......@@ -71,7 +9,7 @@ clause clause* EOF
atom
:
ATOM { factory.registerAtom($ATOM); }
ATOM
;
number
......@@ -86,9 +24,12 @@ atom
term
:
atom |
number |
functor ('(' term (',' term)* ')')?
functor
(
'(' term (',' term)* ')'
) |
atom |
number
;
fact
......
// Generated from ProloGraal.g4 by ANTLR 4.7.1
package ch.heiafr.prolograal.parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
/**
* This class provides an empty implementation of {@link ProloGraalListener},
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
public class ProloGraalBaseListener implements ProloGraalListener {
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterProlograal(ProloGraalParser.ProlograalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitProlograal(ProloGraalParser.ProlograalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterAtom(ProloGraalParser.AtomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitAtom(ProloGraalParser.AtomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterNumber(ProloGraalParser.NumberContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitNumber(ProloGraalParser.NumberContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterFunctor(ProloGraalParser.FunctorContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitFunctor(ProloGraalParser.FunctorContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTerm(ProloGraalParser.TermContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTerm(ProloGraalParser.TermContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterFact(ProloGraalParser.FactContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitFact(ProloGraalParser.FactContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterClause(ProloGraalParser.ClauseContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitClause(ProloGraalParser.ClauseContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterEveryRule(ParserRuleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitEveryRule(ParserRuleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void visitTerminal(TerminalNode node) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void visitErrorNode(ErrorNode node) { }
}
\ No newline at end of file
// Generated from ProloGraal.g4 by ANTLR 4.7.1
package ch.heiafr.prolograal.parser;
// DO NOT MODIFY - generated from ProloGraal.g4
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
......
// Generated from ProloGraal.g4 by ANTLR 4.7.1
package ch.heiafr.prolograal.parser;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**
* This interface defines a complete listener for a parse tree produced by
* {@link ProloGraalParser}.
*/
public interface ProloGraalListener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link ProloGraalParser#prolograal}.
* @param ctx the parse tree
*/
void enterProlograal(ProloGraalParser.ProlograalContext ctx);
/**
* Exit a parse tree produced by {@link ProloGraalParser#prolograal}.
* @param ctx the parse tree
*/
void exitProlograal(ProloGraalParser.ProlograalContext ctx);
/**
* Enter a parse tree produced by {@link ProloGraalParser#atom}.
* @param ctx the parse tree
*/
void enterAtom(ProloGraalParser.AtomContext ctx);
/**