Commit 51cbd0ef authored by René Schöne's avatar René Schöne
Browse files

towards releasing 0.3.1

- begin with support for multi-file errors
parent 292d91d8
Pipeline #9890 passed with stages
in 11 minutes and 2 seconds
aspect Analysis {
// --- lookupTokenEndpointDefinition ---
inh java.util.List<TokenEndpointDefinition> TokenEndpointDefinition.lookupTokenEndpointDefinitions(TokenComponent token);
eq RagConnect.getEndpointDefinition().lookupTokenEndpointDefinitions(TokenComponent token) = lookupTokenEndpointDefinitions(token);
eq RagConnect.getConnectSpecificationFile().lookupTokenEndpointDefinitions(TokenComponent token) = lookupTokenEndpointDefinitions(token);
syn java.util.List<TokenEndpointDefinition> RagConnect.lookupTokenEndpointDefinitions(TokenComponent token) {
java.util.List<TokenEndpointDefinition> result = new java.util.ArrayList<>();
for (EndpointDefinition def : getEndpointDefinitionList()) {
for (EndpointDefinition def : allEndpointDefinitionList()) {
if (def.isTokenEndpointDefinition() && def.asTokenEndpointDefinition().getToken().equals(token)) {
result.add(def.asTokenEndpointDefinition());
}
......@@ -14,10 +14,10 @@ aspect Analysis {
// --- lookupTypeEndpointDefinition ---
inh java.util.List<TypeEndpointDefinition> TypeEndpointDefinition.lookupTypeEndpointDefinitions(TypeComponent type);
eq RagConnect.getEndpointDefinition().lookupTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type);
eq RagConnect.getConnectSpecificationFile().lookupTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type);
syn java.util.List<TypeEndpointDefinition> RagConnect.lookupTypeEndpointDefinitions(TypeComponent type) {
java.util.List<TypeEndpointDefinition> result = new java.util.ArrayList<>();
for (EndpointDefinition def : getEndpointDefinitionList()) {
for (EndpointDefinition def : allEndpointDefinitionList()) {
if (def.isTypeEndpointDefinition() && def.asTypeEndpointDefinition().getType().equals(type)) {
result.add(def.asTypeEndpointDefinition());
}
......@@ -27,8 +27,8 @@ aspect Analysis {
// --- lookupDependencyDefinition ---
inh DependencyDefinition DependencyDefinition.lookupDependencyDefinition(TypeDecl source, String id);
eq RagConnect.getDependencyDefinition().lookupDependencyDefinition(TypeDecl source, String id) {
for (DependencyDefinition def : getDependencyDefinitionList()) {
eq RagConnect.getConnectSpecificationFile().lookupDependencyDefinition(TypeDecl source, String id) {
for (DependencyDefinition def : allDependencyDefinitionList()) {
if (def.getID().equals(id) && def.getSource().containingTypeDecl().equals(source)) {
return def;
}
......
......@@ -2,7 +2,7 @@ aspect NameResolution {
refine RefResolverStubs eq EndpointDefinition.resolveMappingByToken(String id, int position) {
// return a MappingDefinition
for (MappingDefinition mappingDefinition : ragconnect().getMappingDefinitionList()) {
for (MappingDefinition mappingDefinition : ragconnect().allMappingDefinitionList()) {
if (mappingDefinition.getID().equals(id)) {
return mappingDefinition;
}
......
import java.util.List;
import java.util.ArrayList;
aspect Navigation {
// --- program ---
......@@ -16,9 +19,37 @@ aspect Navigation {
// --- containedFileName ---
eq Grammar.getChild().containedFileName() = null; // should be in PP
eq RagConnect.getChild().containedFileName() = getFileName();
eq RagConnect.getChild().containedFileName() = null;
eq ConnectSpecificationFile.getChild().containedFileName() = getFileName();
eq MRagConnect.getChild().containedFileName() = null;
//--- allEndpointDefinitionList ---
syn List<EndpointDefinition> RagConnect.allEndpointDefinitionList() {
List<EndpointDefinition> result = new ArrayList<>();
for (var spec : getConnectSpecificationFileList()) {
spec.getEndpointDefinitionList().forEach(result::add);
}
return result;
}
//--- allDependencyDefinitionList ---
syn List<DependencyDefinition> RagConnect.allDependencyDefinitionList() {
List<DependencyDefinition> result = new ArrayList<>();
for (var spec : getConnectSpecificationFileList()) {
spec.getDependencyDefinitionList().forEach(result::add);
}
return result;
}
//--- allMappingDefinitionList ---
syn List<MappingDefinition> RagConnect.allMappingDefinitionList() {
List<MappingDefinition> result = new ArrayList<>();
for (var spec : getConnectSpecificationFileList()) {
spec.getMappingDefinitionList().forEach(result::add);
}
return result;
}
// --- isTokenEndpointDefinition ---
syn boolean EndpointDefinition.isTokenEndpointDefinition() = false;
eq TokenEndpointDefinition.isTokenEndpointDefinition() = true;
......@@ -70,7 +101,7 @@ aspect Navigation {
// --- targetEndpointDefinition ---
syn EndpointDefinition DependencyDefinition.targetEndpointDefinition() {
// resolve definition in here, as we do not need resolveMethod in any other place (yet)
for (EndpointDefinition endpointDefinition : ragconnect().getEndpointDefinitionList()) {
for (EndpointDefinition endpointDefinition : ragconnect().allEndpointDefinitionList()) {
if (endpointDefinition.isSendTokenEndpointDefinition() &&
endpointDefinition.asSendTokenEndpointDefinition().getToken().equals(this.getTarget())) {
return endpointDefinition;
......
RagConnect ::= EndpointDefinition* DependencyDefinition* MappingDefinition* Program <FileName> ;
RagConnect ::= ConnectSpecificationFile* Program ;
abstract ConnectSpecification ::= EndpointDefinition* DependencyDefinition* MappingDefinition* ;
ConnectSpecificationFile : ConnectSpecification ::= <FileName> ;
abstract EndpointDefinition ::= <AlwaysApply:boolean> ;
......
......@@ -177,7 +177,7 @@ aspect AttributesForMustache {
syn lazy MRagConnect RagConnect.toMustache() {
MRagConnect result = new MRagConnect();
result.setRagConnect(this);
for (EndpointDefinition def : getEndpointDefinitionList()) {
for (EndpointDefinition def : allEndpointDefinitionList()) {
if (def.isReceiveTokenEndpointDefinition()) {
result.addTokenReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache());
} else if (def.isSendTokenEndpointDefinition()) {
......@@ -193,7 +193,7 @@ aspect AttributesForMustache {
for (MappingDefinition def : allMappingDefinitions()) {
result.addMappingDefinition(def.toMustache());
}
for (DependencyDefinition def : getDependencyDefinitionList()) {
for (DependencyDefinition def : allDependencyDefinitionList()) {
result.addDependencyDefinition(def.toMustache());
}
for (TokenComponent token : getProgram().allTokenComponents()) {
......@@ -316,7 +316,7 @@ aspect AspectGeneration {
aspect RelationGeneration {
syn java.util.List<Relation> RagConnect.additionalRelations() {
java.util.List<Relation> result = new java.util.ArrayList<>();
for (DependencyDefinition dd : getDependencyDefinitionList()) {
for (DependencyDefinition dd : allDependencyDefinitionList()) {
result.add(dd.getRelationToCreate());
}
return result;
......
......@@ -298,7 +298,7 @@ aspect Mappings {
syn java.util.List<MappingDefinition> RagConnect.allMappingDefinitions() {
java.util.List<MappingDefinition> result = new java.util.ArrayList<>();
// user-defined mappings
getMappingDefinitionList().iterator().forEachRemaining(result::add);
allMappingDefinitionList().iterator().forEachRemaining(result::add);
// byte[] <-> primitive conversion
result.add(defaultBytesToBooleanMapping());
result.add(defaultBytesToIntMapping());
......
......@@ -4,4 +4,4 @@ import org.jastadd.ragconnect.ast.*;
:};
%goal goal;
%goal ragconnect;
%goal connect_specification_file;
RagConnect ragconnect
= endpoint_definition.d ragconnect.r {: r.getEndpointDefinitionList().insertChild(d, 0); return r; :}
| dependency_definition.d ragconnect.r {: r.getDependencyDefinitionList().insertChild(d, 0); return r; :}
| mapping_definition.d ragconnect.r {: r.getMappingDefinitionList().insertChild(d, 0); return r; :}
| comment ragconnect.r {: return r; :}
| {: return new RagConnect(); :}
ConnectSpecificationFile connect_specification_file
= endpoint_definition.d connect_specification_file.r
{:
r.getEndpointDefinitionList().insertChild(d, 0); return r;
:}
| dependency_definition.d connect_specification_file.r
{:
r.getDependencyDefinitionList().insertChild(d, 0); return r;
:}
| mapping_definition.d connect_specification_file.r
{:
r.getMappingDefinitionList().insertChild(d, 0); return r;
:}
| comment connect_specification_file.r
{:
return r;
:}
| {: return new ConnectSpecificationFile(); :}
;
%embed {:
......
......@@ -204,14 +204,13 @@ public class Compiler extends AbstractCompiler {
case "ast":
case "relast":
// processGrammar
parseGrammar(program, filename);
program.addGrammarFile(parseGrammar(filename));
atLeastOneGrammar = true;
break;
case "connect":
case "ragconnect":
// process ragConnect
RagConnect parsedRagConnect = parseRagConnect(program, filename);
mergeRagConnectDefinitions(ragConnect, parsedRagConnect);
ragConnect.addConnectSpecificationFile(parseConnectSpec(filename));
atLeastOneRagConnect = true;
break;
default:
......@@ -247,7 +246,7 @@ public class Compiler extends AbstractCompiler {
return ragConnect;
}
private void parseGrammar(Program program, String filename) throws CompilerException {
private GrammarFile parseGrammar(String filename) throws CompilerException {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) {
RagConnectScanner scanner = new RagConnectScanner(reader);
RagConnectParser parser = new RagConnectParser();
......@@ -255,21 +254,20 @@ public class Compiler extends AbstractCompiler {
if (optionVerbose.value()) {
LOGGER.fine(grammarFile::dumpTree);
}
program.addGrammarFile(grammarFile);
grammarFile.setFileName(toBaseName(filename));
return grammarFile;
} catch (IOException | Parser.Exception e) {
throw new CompilerException("Could not parse grammar file " + filename, e);
}
}
private RagConnect parseRagConnect(Program program, String filename) throws CompilerException {
private ConnectSpecificationFile parseConnectSpec(String filename) throws CompilerException {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) {
RagConnectScanner scanner = new RagConnectScanner(reader);
RagConnectParser parser = new RagConnectParser();
RagConnect ragConnect = (RagConnect) parser.parse(scanner, RagConnectParser.AltGoals.ragconnect);
ragConnect.setProgram(program);
ragConnect.setFileName(toBaseName(filename));
return ragConnect;
ConnectSpecificationFile specificationFile = (ConnectSpecificationFile) parser.parse(scanner, RagConnectParser.AltGoals.connect_specification_file);
specificationFile.setFileName(toBaseName(filename));
return specificationFile;
} catch (IOException | Parser.Exception e) {
throw new CompilerException("Could not parse connect file " + filename, e);
}
......@@ -284,13 +282,6 @@ public class Compiler extends AbstractCompiler {
return new File(filename).getName();
}
private void mergeRagConnectDefinitions(RagConnect ragConnect, RagConnect ragConnectToIntegrate) {
ragConnectToIntegrate.getEndpointDefinitionList().forEach(ragConnect::addEndpointDefinition);
ragConnectToIntegrate.getMappingDefinitionList().forEach(ragConnect::addMappingDefinition);
ragConnectToIntegrate.getDependencyDefinitionList().forEach(ragConnect::addDependencyDefinition);
ragConnect.setFileName(ragConnect.getFileName().isEmpty() ? ragConnectToIntegrate.getFileName() : ragConnect.getFileName() + " + " + ragConnectToIntegrate.getFileName());
}
// protected void printUsage() {
// System.out.println("Usage: java -jar ragconnect.jar [--option1] [--option2=value] ... <filename1> <filename2> ... ");
// System.out.println("Options:");
......
Part1.connect Line 3, column 1: Receive definition already defined for DoubledValue
Part1.connect Line 4, column 1: Receive definition already defined for DoubledValue
Part1.connect Line 10, column 1: Receiving target token must not be an NTA token!
Part1.connect Line 13, column 1: No suitable default mapping found for type java.util.List
Part1.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the Token (String)!
Part1.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the Token (String)!
Part1.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the Token (String)!
Part2.connect Line 5, column 1: Send definition already defined for DoubledValue
Part2.connect Line 6, column 1: Send definition already defined for DoubledValue
Part2.connect Line 17, column 1: The name of a dependency definition must not be equal to a list-node on the source
Part2.connect Line 22, column 1: Dependency definition already defined for D with name DoubledValue
// --- update receive definitions ---
// Error: there must not be two receive definitions for the same token
receive B.DoubledValue ;
receive B.DoubledValue using IntToInt ;
// NOT HANDLED \\ Error: the token must be resolvable within the parent type
// NOT HANDLED \\ receive B.NonExisting ;
// Error: the Token must not be a TokenNTA (i.e., check for !Token.getNTA())
receive B.ErrorNTA ;
// Error: from-type of first mapping must be byte[] or a supported primitive type
receive B.ErrorTypeOfFirstMapping using ListToList ;
// Error: to-type of last mapping must be type of the Token
receive B.ErrorTypeOfLastMapping using StringToList ;
// Error: types of mappings must match (modulo inheritance)
receive B.ErrorTypeMismatch using StringToList, IntToInt ;
// --- update send definitions ---
// NOT HANDLED \\ Error: the token must be resolvable within the parent type
// NOT HANDLED \\ receive C.NonExisting ;
// Error: Token must be a TokenNTA (i.e., check for Token.getNTA())
send C.ErrorNotNTA ;
// Error: from-type of first mapping must be type of Token
send C.ErrorTypeOfFirstMapping using IntToInt ;
// Error: to-type of last mapping must be byte[] or a supported primitive type
send C.ErrorTypeOfLastMapping1 using StringToList ;
send C.ErrorTypeOfLastMapping2 ;
// Error: types of mappings must match (modulo inheritance)
send C.ErrorTypeMismatch using StringToList, IntToInt ;
// Error: no more than one send mapping for each TokenComponent
send C.DoubledValue ;
send C.DoubledValue using IntToInt ;
// --- dependency definitions ---
// NOT HANDLED \\ Error: Both, source and target must be resolvable within the parent type
// NOT HANDLED \\ D.SourceNonExistingTarget canDependOn D.NonExisting as NonExistingTarget ;
// NOT HANDLED \\ D.NonExisting canDependOn D.TargetNonExistingSource as NonExistingSource ;
// Error: There must be a send update definition for the target token
D.SourceNoWriteDef canDependOn D.TargetNoWriteDef as NoWriteDef ;
// Error: The name of a dependency definition must not be equal to a list-node on the source
D.SourceSameAsListNode canDependOn D.TargetSameAsListNode as MyList ;
send D.TargetSameAsListNode;
// Error: There must not be two dependency definitions with the same name
D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ;
D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ;
send D.TargetDoubledValue;
// --- mapping definitions ---
ListToList maps java.util.List<String> list to java.util.List<String> {:
return list;
:}
StringToList maps String s to List<String> {:
java.util.List<String> result = new java.util.ArrayList<>();
result.add(s);
return result;
:}
IntToInt maps int number to int {:
return number + 1;
:}
Standard.connect Line 3, column 1: Receive definition already defined for DoubledValue
Standard.connect Line 4, column 1: Receive definition already defined for DoubledValue
Standard.connect Line 10, column 1: Receiving target token must not be an NTA token!
Standard.connect Line 13, column 1: No suitable default mapping found for type java.util.List
Standard.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the Token (String)!
Standard.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the Token (String)!
Standard.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the Token (String)!
Standard.connect Line 39, column 1: Send definition already defined for DoubledValue
Standard.connect Line 40, column 1: Send definition already defined for DoubledValue
Standard.connect Line 51, column 1: The name of a dependency definition must not be equal to a list-node on the source
Standard.connect Line 56, column 1: Dependency definition already defined for D with name DoubledValue
......@@ -10,11 +10,13 @@ import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.jastadd.ragconnect.tests.TestUtils.exec;
import static org.jastadd.ragconnect.tests.TestUtils.readFile;
import static org.junit.jupiter.api.Assertions.assertTrue;
......@@ -26,6 +28,8 @@ public class Errors {
private static final String INPUT_DIRECTORY = "./src/test/01-input/errors/";
private static final String OUTPUT_DIRECTORY = "./src/test/02-after-ragconnect/errors/";
private static final String DEFAULT_GRAMMAR_NAME = "Errors";
@BeforeAll
public static void createOutputDirectory() {
File outputDirectory = new File(OUTPUT_DIRECTORY);
......@@ -34,35 +38,49 @@ public class Errors {
@Test
void testStandardErrors() throws IOException {
test("Errors", "A");
test("Standard", "A","Standard");
}
@Test
void testTwoPartsErrors() throws IOException {
test("Part", "A","Part1", "Part2");
}
@SuppressWarnings("SameParameterValue")
private void test(String name, String rootNode) throws IOException {
String grammarFile = INPUT_DIRECTORY + name + ".relast";
String ragconnectFile = INPUT_DIRECTORY + name + ".connect";
String outFile = OUTPUT_DIRECTORY + name + ".out";
String expectedFile = INPUT_DIRECTORY + name + ".expected";
private void test(String expectedName, String rootNode, String... connectNames) throws IOException {
String grammarFile = INPUT_DIRECTORY + DEFAULT_GRAMMAR_NAME + ".relast";
// String ragconnectFile = INPUT_DIRECTORY + name + ".connect";
String outFile = OUTPUT_DIRECTORY + expectedName + ".out";
String expectedFile = INPUT_DIRECTORY + expectedName + ".expected";
assertThat(connectNames).isNotEmpty();
try {
logger.debug("user.dir: {}", System.getProperty("user.dir"));
String[] args = {
"--o=" + OUTPUT_DIRECTORY,
grammarFile,
ragconnectFile,
"--rootNode=" + rootNode,
"--verbose"
};
int returnValue = exec(Compiler.class, args, new File(outFile));
List<String> args = new ArrayList<>() {{
add("--o=" + OUTPUT_DIRECTORY);
add("--rootNode=" + rootNode);
add("--verbose");
add(grammarFile);
}};
for (String connectName : connectNames) {
args.add(INPUT_DIRECTORY + connectName + ".connect");
}
int returnValue = exec(Compiler.class, args.toArray(new String[0]), new File(outFile));
Assertions.assertEquals(1, returnValue, "RagConnect did not return with value 1");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
final String startOfErrorsPattern = "SEVERE: Errors:";
String out = readFile(outFile, Charset.defaultCharset());
assertThat(out).contains(startOfErrorsPattern);
out = out.substring(out.indexOf(startOfErrorsPattern) + 16);
String expected = readFile(expectedFile, Charset.defaultCharset());
// if (inFiles.size() == 1) {
expected = expected.replace(FILENAME_PATTERN, name);
// expected = expected.replace(FILENAME_PATTERN, name + ".connect");
// } else {
// for (int i = 0; i < inFiles.size(); i++) {
// expected = expected.replace(FILENAME_PATTERN + (i + 1), inFiles.get(i));
......@@ -75,10 +93,9 @@ public class Errors {
.filter(s -> !s.isEmpty() && !s.startsWith("//"))
.collect(Collectors.toList());
// FIXME errors not handled correctly at the moment
// Assertions.assertLinesMatch(expectedList, outList);
Assertions.assertLinesMatch(expectedList, outList);
logger.info("ragconnect for " + name + " returned:\n{}", out);
logger.info("ragconnect for " + expectedName + " returned:\n{}", out);
}
}
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