Skip to content

Commit

Permalink
Support for the load statement in the compiler (#76)
Browse files Browse the repository at this point in the history
Porting the load statement from the previous compiler to the new
architecture.

- Exposing a "partial compilation chain" providing a list of actions out
of a file name;
- Load statements reified as a `LoadFile` action
- When interpreting the action, triggering the partial chain to get
actions, and then using the execution engine to enrich the already
existing `Unit`
- Recording already visited files to avoid loops or double loading.
  • Loading branch information
mosser authored Sep 14, 2024
2 parents 1a136b0 + 8539682 commit eb30cd8
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 15 deletions.
19 changes: 16 additions & 3 deletions compiler/src/main/antlr4/ca/mcscert/jpipe/syntax/JPipe.g4
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@ grammar JPipe;
******************/

// Root rule for parsing (called by the compilationChain)
unit : (justification)+ EOF;
unit : (justification | pattern | load)+ EOF;

// Declare a justification
justification : JUSTIFICATION id=ID OPEN justif_body CLOSE;
justification : JUSTIFICATION id=ID (IMPLEMENTS parent=ID)? OPEN justif_body CLOSE;
justif_body : (evidence | sub_conclusion | strategy | relation | conclusion)+;

pattern : PATTERN id=ID (IMPLEMENTS parent=ID)? OPEN pattern_body CLOSE;
pattern_body : (evidence | sub_conclusion | strategy | relation | conclusion | abstract)+;

load : LOAD path=STRING;

// Body of a justification/pattern content
element : id=ID IS name=STRING;

element: id=ID IS name=STRING;
evidence : EVIDENCE element;
strategy : STRATEGY element;
sub_conclusion : SUBCONCLUSION element;
conclusion : CONCLUSION element;
abstract : ABSTRACT_SUP element;

relation : from=ID SUPPORT_LNK to=ID;

Expand All @@ -28,13 +34,20 @@ relation : from=ID SUPPORT_LNK to=ID;
// Keywords

JUSTIFICATION : 'justification';
IMPLEMENTS : 'implements';
IS : 'is';

EVIDENCE : 'evidence';
STRATEGY : 'strategy';
SUBCONCLUSION : 'sub-conclusion';
CONCLUSION : 'conclusion';
PATTERN : 'pattern';
ABSTRACT_SUP : '@support';

SUPPORT_LNK : 'supports';

LOAD : 'load';

// Making whitespaces and newlines irrelevant to the syntax
WHITESPACE : [ \t]+ -> channel(HIDDEN);
NEWLINE : ('\r'? '\n' | '\r')+ -> channel(HIDDEN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import ca.mcscert.jpipe.error.ErrorManager;
import ca.mcscert.jpipe.error.FatalException;
import ca.mcscert.jpipe.model.Unit;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
Expand Down Expand Up @@ -41,11 +43,23 @@ public ExecutionEngine(boolean failOnError) {
* @return the Unit after all the actions have been applied.
*/
public Unit spawn(String fileName, List<Action> actions) {
Unit unit = new Unit(fileName);
Unit unit = new Unit(fileName, Paths.get(fileName));
this.update(unit, actions);
return unit;
}

/**
* Enrich an existing compilation unit with actions (coming from a load for example).
*
* @param context the unit to enrich.
* @param actions the actions to execute.
* @return the enriched unit.
*/
public Unit enrich(Unit context, List<Action> actions) {
this.update(context, actions);
return context;
}

private void update(Unit u, List<Action> actions) {
List<Throwable> errors = new ArrayList<>();
this.execute(actions, u, errors);
Expand Down
54 changes: 54 additions & 0 deletions compiler/src/main/java/ca/mcscert/jpipe/actions/LoadFile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ca.mcscert.jpipe.actions;

import ca.mcscert.jpipe.compiler.CompilerFactory;
import ca.mcscert.jpipe.compiler.model.Source;
import ca.mcscert.jpipe.compiler.model.Transformation;
import ca.mcscert.jpipe.compiler.steps.io.FileReader;
import ca.mcscert.jpipe.error.SemanticError;
import ca.mcscert.jpipe.model.Unit;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* Load a file referenced in another file.
*/
public class LoadFile implements Action {

private static final Logger logger = LogManager.getLogger();

private final String fileName;

public LoadFile(String fileName) {
this.fileName = fileName;
}

@Override
public void execute(Unit context) throws Exception {
Path p = new File(fileName).toPath().normalize();
canLoad(p, context);
context.addLoadedFile(p);
Transformation<InputStream, List<Action>> partial = CompilerFactory.actionProvider();
Source<InputStream> reader = new FileReader();
try (InputStream in = reader.provideFrom(p.toString())) {
List<Action> actions = partial.fire(in, p.toString());
ExecutionEngine engine = new ExecutionEngine();
engine.enrich(context, actions);
}
}


private void canLoad(Path p, Unit context) {

if (context.isInScope(p)) {
throw new SemanticError("Cannot load file " + p + " as it is already loaded");
}
if (!p.toFile().exists()) {
throw new SemanticError("Cannot load file " + p + " (file not found or not readable)");
}
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package ca.mcscert.jpipe.compiler;

import ca.mcscert.jpipe.actions.Action;
import ca.mcscert.jpipe.cli.Configuration;
import ca.mcscert.jpipe.compiler.model.ChainBuilder;
import ca.mcscert.jpipe.compiler.model.ChainCompiler;
import ca.mcscert.jpipe.compiler.model.Transformation;
import ca.mcscert.jpipe.compiler.steps.ActionListInterpretation;
import ca.mcscert.jpipe.compiler.steps.ActionListProvider;
import ca.mcscert.jpipe.compiler.steps.Apply;
Expand All @@ -14,6 +18,7 @@
import ca.mcscert.jpipe.compiler.steps.io.FileReader;
import ca.mcscert.jpipe.compiler.steps.io.GraphVizRenderer;
import ca.mcscert.jpipe.visitors.exporters.GraphVizExporter;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -56,4 +61,21 @@ private static Compiler defaultCompiler(Configuration config) {
.andThen(new GraphVizRenderer(config.getFormat()));
}


/**
* Provide a partial compilation chain to get actions out of a given filename.
*
* @return a default instance of Compiler.
*/
public static Transformation<InputStream, List<Action>> actionProvider() {
List<Throwable> errors = new ArrayList<>();
return new FileReader()
.andThen(new CharStreamProvider())
.andThen(new Lexer(errors))
.andThen(new Parser(errors))
.andThen(new LazyHaltAndCatchFire<>(errors))
.andThen(new ActionListProvider())
.asTransformation();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ public ChainCompiler<I, O> andThen(Sink<O> sink) {
return new ChainCompiler<>(this.source, this.chain, sink);
}


public Transformation<I, O> asTransformation() {
return this.chain;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
import ca.mcscert.jpipe.actions.CreateRelation;
import ca.mcscert.jpipe.actions.CreateStrategy;
import ca.mcscert.jpipe.actions.CreateSubConclusion;
import ca.mcscert.jpipe.actions.LoadFile;
import ca.mcscert.jpipe.compiler.model.Transformation;
import ca.mcscert.jpipe.syntax.JPipeBaseListener;
import ca.mcscert.jpipe.syntax.JPipeParser;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.tree.ParseTree;
Expand Down Expand Up @@ -58,6 +61,13 @@ public List<Action> collect() {
return result;
}

@Override
public void enterLoad(JPipeParser.LoadContext ctx) {
String relativePath = linearize(this.buildContext.unitFileName,
strip(ctx.path.getText()));
result.add(new LoadFile(relativePath));
}

@Override
public void enterJustification(JPipeParser.JustificationContext ctx) {
this.buildContext = buildContext.updateCurrentJustification(ctx.id.getText());
Expand Down Expand Up @@ -101,6 +111,13 @@ public void enterRelation(JPipeParser.RelationContext ctx) {
private String strip(String s) {
return s.substring(1, s.length() - 1);
}

private String linearize(String rootFile, String fileName) {
Path root = Paths.get(rootFile).getParent();
Path target = Paths.get(fileName);
return root.resolve(target).toString();
}

}

}
33 changes: 32 additions & 1 deletion compiler/src/main/java/ca/mcscert/jpipe/model/Unit.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import ca.mcscert.jpipe.model.elements.JustificationElement;
import ca.mcscert.jpipe.visitors.ModelVisitor;
import java.io.File;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
* Define what a compilation Unit is in JPipe.
Expand All @@ -11,21 +15,39 @@ public final class Unit implements Visitable {

private final String name;
private final SymbolTable<Justification> contents;
private final Set<String> loaded;

/**
* Instantiates a compilation unit, using its name (source file).
*
* @param name the source file used to run the compiler.
* @param filePath path of the original file;
*/
public Unit(String name) {
public Unit(String name, Path filePath) {
this.name = name;
this.contents = new SymbolTable<>();
this.loaded = new HashSet<>();
loaded.add(filePath.normalize().toString());
}

public String getName() {
return name;
}


public boolean isInScope(Path p) {
return this.loaded.contains(p.normalize().toString());
}

/**
* Add a path as part of the files loaded to contribute to this unit.
*
* @param p the path to add
*/
public void addLoadedFile(Path p) {
this.loaded.add(p.normalize().toString());
}

/**
* Record a new justification inside the unit symbol table.
*
Expand Down Expand Up @@ -60,4 +82,13 @@ public void accept(ModelVisitor<?> visitor) {
visitor.visit(this);
}


@Override
public String toString() {
return "Unit{"
+ "name='" + name + '\''
+ ", contents=" + contents
+ ", loaded=" + loaded
+ '}';
}
}
18 changes: 12 additions & 6 deletions compiler/src/main/puml/model.puml
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,37 @@ class Unit {

Unit *--> "1..*" Justification

class Justification {
class Justification implements Visitable {
+ name: String
}

Justification *--> "1" Conclusion
Justification --> "1\nconclusion" Conclusion
Justification *-> "symbols\n*" JustificationElement

abstract class JustificationElement {
abstract class JustificationElement implements Visitable {
+ id: Symbol
+ label: String
}

class Conclusion extends JustificationElement

Conclusion -> "1" Strategy
Conclusion -> "1\nstrategy" Strategy

class Strategy extends JustificationElement

Strategy -> "1..*" Support
Strategy -> "1..*\nsupports" Support

abstract class Support extends JustificationElement

class Evidence extends Support

class SubConclusion extends Support

Strategy "1" <-- SubConclusion
Strategy "1\nstrategy" <-- SubConclusion

interface Visitable {
+ accept(v: ModelVisitor)

}

@enduml
23 changes: 23 additions & 0 deletions compiler/src/test/resources/load.jd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
load "simple.jd"

justification prove_models2 {

evidence Su1 is "Atomic Petri Nets are available"
strategy St1 is "Merge atomic models"
Su1 supports St1

sub-conclusion SC1 is "Complete model is merged"
St1 supports SC1

evidence Su2 is "Prover is available"
evidence Su3 is "Scenario are available as TINA artefacts"
strategy St2 is "Prove model"
Su2 supports St2
Su3 supports St2
SC1 supports St2

conclusion C is "Model is correct"
St2 supports C

}

2 changes: 1 addition & 1 deletion langium/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Unreleased

### v0.2.1 (2024-08-06)
### v0.2.2 (2024-08-06)
- Leader: Cass Braun
- Features:
- Added patterns and compositions to grammar with basic language support
Expand Down
4 changes: 2 additions & 2 deletions langium/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion langium/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Language Support for the jPipe language",
"author": "McMaster Centre for Software Certification (McSCert)",
"publisher": "mcscert",
"version": "0.2.1",
"version": "0.2.2",
"license": "MIT",
"icon": "images/logo.png",
"repository": {
Expand Down

0 comments on commit eb30cd8

Please sign in to comment.