Skip to content

Commit

Permalink
Merge pull request #29 from m-lyons/import
Browse files Browse the repository at this point in the history
Imports are now expressions
  • Loading branch information
nikklassen authored Jun 16, 2016
2 parents ef3bfd1 + cede96a commit d273ea0
Show file tree
Hide file tree
Showing 26 changed files with 434 additions and 211 deletions.
12 changes: 4 additions & 8 deletions src/main/antlr4/Manifold.g4
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ tupleValue:
'(' ')';
functionTypeValue: tupleTypeValue '->' tupleTypeValue;
functionValue: functionTypeValue '{' (expression STATEMENT_TERMINATOR)* '}';
functionValue: functionTypeValue '{' (expression EXPRESSION_TERMINATOR)* '}';
////////////////////////////////////////////////////////
// //
Expand Down Expand Up @@ -83,6 +83,7 @@ rvalue:
| VISIBILITY_PUBLIC? lvalue '=' rvalue # AssignmentExpression
| 'primitive' 'port' typevalue (':' tupleTypeValue)? # PrimitivePortDefinitionExpression
| 'primitive' 'node' functionTypeValue # PrimitiveNodeDefinitionExpression
| 'import' STRING_VALUE #ImportExpr
;
lvalue:
Expand All @@ -97,12 +98,7 @@ expression:
// | declaration
;
statement:
expression #ExpressionStatment
| 'import' STRING_VALUE #ImportStatement
;
STATEMENT_TERMINATOR: ';';
EXPRESSION_TERMINATOR: ';';
////////////////////////////////////////////////////////
Expand All @@ -111,4 +107,4 @@ STATEMENT_TERMINATOR: ';';
// //
////////////////////////////////////////////////////////
schematic: (statement STATEMENT_TERMINATOR)*;
schematic: (expression EXPRESSION_TERMINATOR)*;
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,20 @@
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 ExpressionGraph exprGraph;
private File inputFile;
private List<String> errors;

public ExpressionGraph getExpressionGraph() {
return this.exprGraph;
}
Expand All @@ -32,12 +39,26 @@ 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.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
Expand Down Expand Up @@ -81,7 +102,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();

Expand Down Expand Up @@ -315,8 +336,37 @@ 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;
}

ExpressionVertex v = new ImportVertex(exprGraph, importedFile);
exprGraph.addVertex(v);
return v;
}

@Override
Expand Down
28 changes: 24 additions & 4 deletions src/main/java/org/manifold/compiler/front/ExpressionGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.antlr.v4.runtime.misc.Nullable;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.manifold.compiler.UndefinedBehaviourError;
Expand All @@ -13,6 +14,8 @@
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ExpressionGraph {

Expand All @@ -29,9 +32,18 @@ public Map<VariableIdentifier, VariableReferenceVertex> getVariableVertices() {
/**
* Copy everything from subGraph into this graph
* @param subGraph the graph to copy
* @param importVars should the visibility modifiers in subGraph are respected
*/
public void addSubGraph(ExpressionGraph subGraph, boolean importVars) {
public void addSubGraph(ExpressionGraph subGraph) {
addSubGraph(subGraph, null);
}

/**
* Copy all vertices from subGraph into this graph.
* @param subGraph the graph to copy
* @param namespace The namespace for any exported variables. If this is null all variables will be exported under
* the same name.
*/
public void addSubGraph(ExpressionGraph subGraph, @Nullable NamespaceIdentifier namespace) {
// map of subgraph edge -> new edge to be inserted
Map<ExpressionEdge, ExpressionEdge> exprEdgeMap = new HashMap<>();
subGraph.getEdges().forEach(e -> {
Expand All @@ -42,6 +54,7 @@ public void addSubGraph(ExpressionGraph subGraph, boolean importVars) {

// map of subgraph vertex -> new vertex
Map<ExpressionVertex, ExpressionVertex> exprVertexMap = new HashMap<>();
List<String> oldNs = namespace == null ? new ArrayList<>() : namespace.getName();

// do not add the input/output vertices since they are being replaced by the main graph's vertices
subGraph.getVertices().stream()
Expand All @@ -51,8 +64,13 @@ public void addSubGraph(ExpressionGraph subGraph, boolean importVars) {
VariableReferenceVertex var = (VariableReferenceVertex) v;
// Allow for ignoring the state of import, this is the case when this function
// is used to copy the body of a FunctionValueVertex
if (var.getExported() || !importVars) {
VariableIdentifier ref = var.getId();
if (namespace == null || var.getExported()) {
List<String> newNs =
Stream.concat(
oldNs.stream(),
var.getId().getNamespaceIdentifier().getName().stream())
.collect(Collectors.toList());
VariableIdentifier ref = new VariableIdentifier(new NamespaceIdentifier(newNs), var.getId().getName());
try {
this.addVertex(ref);
newVertex = this.getVariableVertex(ref);
Expand All @@ -61,6 +79,8 @@ public void addSubGraph(ExpressionGraph subGraph, boolean importVars) {
}
} else {
newVertex = new VariableReferenceVertex(this, var.getId());
// Uses the ExpressionVertex overload which will add this node to the non-variable vertices,
// instead of variable
this.addVertex(newVertex);
}
} else {
Expand Down
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
Expand Up @@ -10,6 +10,7 @@
public abstract class ExpressionVertex {

private final ExpressionGraph exprGraph;

protected ExpressionGraph getExpressionGraph() {
return this.exprGraph;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public ExpressionVertex copy(ExpressionGraph g,
// Use a new expression graph for the body, just like when constructing a function initially.
// This maintains proper scoping
ExpressionGraph newBody = new ExpressionGraph();
newBody.addSubGraph(functionBody, false);
newBody.addSubGraph(functionBody);

return new FunctionValueVertex(g, edgeMap.get(functionTypeEdge), newBody);
}
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/org/manifold/compiler/front/ImportTypeValue.java
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");
}
}
37 changes: 37 additions & 0 deletions src/main/java/org/manifold/compiler/front/ImportValue.java
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();
}
}
Loading

0 comments on commit d273ea0

Please sign in to comment.