-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Imports are now expressions #29
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,13 +14,21 @@ | |
import org.manifold.parser.ManifoldLexer; | ||
import org.manifold.parser.ManifoldParser.*; | ||
|
||
import java.io.File; | ||
import java.net.URL; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.stream.Stream; | ||
|
||
class ExpressionContextVisitor extends ManifoldBaseVisitor<ExpressionVertex> { | ||
|
||
private ExpressionGraphParser parser; | ||
private ExpressionGraph exprGraph; | ||
private File inputFile; | ||
private List<String> errors; | ||
|
||
public ExpressionGraph getExpressionGraph() { | ||
return this.exprGraph; | ||
} | ||
|
@@ -32,12 +40,27 @@ public ExpressionGraph getExpressionGraph() { | |
private boolean isPublic = false; | ||
|
||
private int nextTmpVar = 0; | ||
public ExpressionContextVisitor() { | ||
this(new ExpressionGraph()); | ||
public ExpressionContextVisitor(File inputFile) { | ||
this(new ExpressionGraph(), inputFile); | ||
} | ||
|
||
public ExpressionContextVisitor(ExpressionGraph exprGraph) { | ||
public ExpressionContextVisitor(ExpressionGraph exprGraph, File inputFile) { | ||
this.inputFile = inputFile; | ||
this.parser = new ExpressionGraphParser(); | ||
this.exprGraph = exprGraph; | ||
this.errors = new ArrayList<>(); | ||
} | ||
|
||
public List<String> getErrors() { | ||
return errors; | ||
} | ||
|
||
private File getLib(String libPath) { | ||
URL url = this.getClass().getClassLoader().getResource("libraries/" + libPath); | ||
if (url == null) { | ||
return null; | ||
} | ||
return new File(url.getFile()); | ||
} | ||
|
||
@Override | ||
|
@@ -81,7 +104,7 @@ public ExpressionVertex visitFunctionInvocationExpression( | |
public ExpressionVertex visitFunctionValue( | ||
FunctionValueContext ctx) { | ||
ExpressionContextVisitor functionGraphBuilder = | ||
new ExpressionContextVisitor(); | ||
new ExpressionContextVisitor(inputFile); | ||
ctx.expression().forEach(functionGraphBuilder::visit); | ||
ExpressionGraph fSubGraph = functionGraphBuilder.getExpressionGraph(); | ||
|
||
|
@@ -315,8 +338,46 @@ private ExpressionVertex createVariableVertex(VariableIdentifier id) { | |
} | ||
|
||
@Override | ||
public ExpressionVertex visitImportStatement(ImportStatementContext context) { | ||
return null; | ||
public ExpressionVertex visitImportExpr(ImportExprContext context) { | ||
String importString = context.STRING_VALUE().getText() | ||
.replaceAll("\\\"", "\""); | ||
importString = importString.substring(1, importString.length() - 1); | ||
|
||
// Reassign to a new variable to satisfy the lambda requirement of "final" variables | ||
String filePath = importString; | ||
|
||
File importedFile = Stream.of( | ||
new File(inputFile.getParent(), filePath), | ||
new File(inputFile.getParent(), filePath + ".manifold") | ||
).filter(f -> f.exists()) | ||
.findFirst() | ||
.orElseGet(() -> { | ||
File lib = getLib(filePath); | ||
if (lib == null) { | ||
lib = getLib(filePath + ".manifold"); | ||
} | ||
if (lib != null) { | ||
return lib; | ||
} | ||
errors.add("Import " + filePath + " not found"); | ||
return null; | ||
}); | ||
if (importedFile == null) { | ||
return null; | ||
} | ||
|
||
ExpressionGraph g; | ||
try { | ||
g = parser.parseFile(importedFile); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is the best place to put this, but I'm not really sure where it would make the most sense. The alternative that seems to make the most sense is during elaboration of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand this correctly, it would make sense to me to have the import resolved during elaboration. I can see it being beneficial to keeping our simple graph views, well, simple. You know more about the process and performance so it's your call. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since there's no reason to parse a file if the import isn't used I'm going to move this in |
||
} catch (Exception e) { | ||
errors.add(e.getMessage().trim()); | ||
errors.add("Error while parsing included file " + filePath); | ||
return null; | ||
} | ||
|
||
ExpressionVertex v = new ImportVertex(exprGraph, g); | ||
exprGraph.addVertex(v); | ||
return v; | ||
} | ||
|
||
@Override | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package org.manifold.compiler.front; | ||
|
||
import org.antlr.v4.runtime.*; | ||
import org.antlr.v4.runtime.atn.ATNConfigSet; | ||
import org.antlr.v4.runtime.dfa.DFA; | ||
import org.antlr.v4.runtime.misc.NotNull; | ||
import org.antlr.v4.runtime.misc.Nullable; | ||
import org.apache.log4j.LogManager; | ||
import org.apache.log4j.Logger; | ||
import org.manifold.parser.ManifoldLexer; | ||
import org.manifold.parser.ManifoldParser; | ||
|
||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.util.BitSet; | ||
import java.util.List; | ||
|
||
public class ExpressionGraphParser { | ||
|
||
private static Logger log = LogManager.getLogger("ExpressionGraphParser"); | ||
|
||
public ExpressionGraph parseFile(File inputFile) throws IOException { | ||
ManifoldLexer lexer = new ManifoldLexer(new ANTLRInputStream( | ||
new FileInputStream(inputFile))); | ||
|
||
// Get a list of matched tokens | ||
CommonTokenStream tokens = new CommonTokenStream(lexer); | ||
|
||
// Pass the tokens to the parser | ||
ManifoldParser parser = new ManifoldParser(tokens); | ||
|
||
StringBuilder errors = new StringBuilder(); | ||
parser.addErrorListener(new ANTLRErrorListener() { | ||
|
||
@Override | ||
public void syntaxError(@NotNull Recognizer<?, ?> recognizer, @Nullable Object offendingSymbol, int line, | ||
int charPositionInLine, @NotNull String msg, @Nullable RecognitionException e) { | ||
errors.append("Error at line ").append(line).append(", char ") | ||
.append(charPositionInLine).append(": ").append(msg).append("\n"); | ||
} | ||
|
||
@Override | ||
public void reportAmbiguity(@NotNull Parser recognizer, @NotNull DFA dfa, int startIndex, int stopIndex, | ||
boolean exact, @Nullable BitSet ambigAlts, @NotNull ATNConfigSet configs) { | ||
// Pass | ||
} | ||
|
||
@Override | ||
public void reportAttemptingFullContext(@NotNull Parser recognizer, @NotNull DFA dfa, int startIndex, | ||
int stopIndex, @Nullable BitSet conflictingAlts, | ||
@NotNull ATNConfigSet configs) { | ||
// Pass | ||
} | ||
|
||
@Override | ||
public void reportContextSensitivity(@NotNull Parser recognizer, @NotNull DFA dfa, int startIndex, int stopIndex, | ||
int prediction, @NotNull ATNConfigSet configs) { | ||
// Pass | ||
} | ||
}); | ||
|
||
// Specify our entry point | ||
ManifoldParser.SchematicContext context = parser.schematic(); | ||
|
||
if (errors.length() != 0) { | ||
throw new FrontendBuildException(errors.toString()); | ||
} | ||
|
||
ExpressionContextVisitor graphBuilder = new ExpressionContextVisitor(inputFile); | ||
List<ManifoldParser.ExpressionContext> expressionContexts = context.expression(); | ||
for (ManifoldParser.ExpressionContext expressionContext : expressionContexts) { | ||
graphBuilder.visit(expressionContext); | ||
} | ||
if (graphBuilder.getErrors().size() > 0) { | ||
throw new FrontendBuildException( | ||
String.join("\n", graphBuilder.getErrors())); | ||
} | ||
ExpressionGraph exprGraph = graphBuilder.getExpressionGraph(); | ||
|
||
log.debug("writing out initial expression graph"); | ||
File exprGraphDot = new File(inputFile.getName() + ".exprs.dot"); | ||
exprGraph.writeDOTFile(exprGraphDot); | ||
return exprGraph; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.manifold.compiler.front; | ||
|
||
import org.manifold.compiler.SchematicValueVisitor; | ||
import org.manifold.compiler.TypeValue; | ||
import org.manifold.compiler.UndefinedBehaviourError; | ||
|
||
public class ImportTypeValue extends TypeValue implements NamedEntryTypeValue { | ||
|
||
private NamespaceIdentifier namespace; | ||
private ExpressionGraph exprGraph; | ||
|
||
public ImportTypeValue(ExpressionGraph exprGraph, NamespaceIdentifier namespace) { | ||
this.exprGraph = exprGraph; | ||
this.namespace = namespace; | ||
} | ||
|
||
public TypeValue getEntry(String key) throws Exception { | ||
VariableIdentifier id = new VariableIdentifier(namespace, key); | ||
VariableReferenceVertex source = exprGraph.getVariableVertex(id); | ||
source.elaborate(); | ||
return source.getType(); | ||
} | ||
|
||
@Override | ||
public void accept(SchematicValueVisitor schematicValueVisitor) { | ||
throw new UndefinedBehaviourError( | ||
"cannot accept non-frontend ValueVisitor into a frontend Value"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package org.manifold.compiler.front; | ||
|
||
import org.manifold.compiler.SchematicValueVisitor; | ||
import org.manifold.compiler.Value; | ||
|
||
public class ImportValue extends Value implements NamedEntryValue { | ||
private ExpressionGraph exprGraph; | ||
private NamespaceIdentifier namespace; | ||
|
||
public ImportValue(ExpressionGraph exprGraph, NamespaceIdentifier namespace) { | ||
super(new ImportTypeValue(exprGraph, namespace)); | ||
this.exprGraph = exprGraph; | ||
this.namespace = namespace; | ||
} | ||
@Override | ||
public boolean isElaborationtimeKnowable() { | ||
return false; | ||
} | ||
|
||
@Override | ||
public boolean isRuntimeKnowable() { | ||
return false; | ||
} | ||
|
||
@Override | ||
public void accept(SchematicValueVisitor schematicValueVisitor) { | ||
return; | ||
} | ||
|
||
@Override | ||
public Value getEntry(String key) throws Exception { | ||
VariableIdentifier id = new VariableIdentifier(namespace, key); | ||
VariableReferenceVertex source = exprGraph.getVariableVertex(id); | ||
source.elaborate(); | ||
return source.getValue(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was once called
EXPRESSION_TERMINATOR
. I don't see a need to change it now.