Aufgrund einer Störung des s3 Storage, könnten in nächster Zeit folgende GitLab Funktionen nicht zur Verfügung stehen: LFS, Container Registry, Job Artifacs, Uploads (Wiki, Bilder, Projekt-Exporte). Wir bitten um Verständnis. Es wird mit Hochdruck an der Behebung des Problems gearbeitet. Weitere Informationen zur Störung des Object Storage finden Sie hier: https://maintenance.itc.rwth-aachen.de/ticket/status/messages/59-object-storage-pilot

Commit 0b54574b authored by Thomas Michael Timmermanns's avatar Thomas Michael Timmermanns
Browse files

Refactoring and added tests

parent 87a112a5
......@@ -16,9 +16,9 @@ Variables which occur only in form of parameters are seemingly untyped.
However, the correctness of their values is checked at compile time.
The header of the architecture declares architecture parameters that can be used in all following expressions.
In this way, different instances of the same architecture can be created.
The top part of the architecture consists of input, output and method declarations.
The main part is the actual architecture definition in the form of a collection of layers which are connected through the two operators "->" and "|".
A layer can either be a method, an input or an output.
The top part of the architecture consists of input, output and layer declarations.
The main part is the actual architecture definition in the form of a collection of architecture elements which are connected through the two operators "->" and "|".
An architecture element can either be a layer, an input or an output.
The following is a complete example of the original version of Alexnet by A. Krizhevsky.
There are more compact versions of the same architecture but we will get to that later.
All predefined methods are listed at the end of this document.
......@@ -82,16 +82,16 @@ This is done for the sake of simplicity. However, this change should not affect
## Data Flow Operators
This language does not use symbols to denote a connections between layers like most deep learning frameworks but instead uses a approach which describes the data flow through the network.
The first operator is the serial connection "->". The operator simply connects the output of the first layer to the input of the second layer.
The first operator is the serial connection "->". The operator simply connects the output of the first element to the input of the second element.
Despite being sequential in nature, CNNArch is still able to describe complex networks like ResNeXt through the use of the parallelization operator "|".
This operator splits the network into parallel data streams.
The serial connection operator has a higher precedence than the parallel connection operator.
Therefore it is necessary to use brackets around each parallel group of layers.
Therefore, it is necessary to use brackets around parallel groups of layers.
Each element in a parallel group has the same input stream as the whole group.
The output of a parallel group is a list of streams which can be merged into a single stream through use of the following methods:
The output of a parallelization block is a list of streams which can be merged into a single stream through use of the following layers:
`Concatenate()`, `Add()` or `Get(index)`.
Note: `Get(index=i)` can be abbreviated by `[i]`.
The method `Split(n)` in the example above creates multiple output streams from a single input stream by splitting the channels of the input data into *n* streams.
The layer `Split(n)` in the example above creates multiple output streams from a single input stream by splitting the channels of the input data into *n* streams.
## Inputs and Outputs
......@@ -103,7 +103,7 @@ def input Z(0:255)^{3, h, w} image[2]
def input Q(-oo:+oo)^{10} additionalData
def output Q(0:1)^{3} predictions
```
The first line defines the input *image* as an array of two rgb (or bgr) images with a resolution of `h` x `w`.
The first line defines the input *image* as an array of two color images with a resolution of `h` x `w`.
The part `Z(0:255)`, which corresponds to the type definition in EmbeddedMontiArc, restricts the values to integers between 0 and 255.
The following line `{3, h, w}` declares the shape of the input.
The shape denotes the dimensionality in form of depth (number of channels), height and width.
......@@ -120,34 +120,38 @@ Inputs and outputs can also be used in the middle of an architecture.
In general, inputs create new streams and outputs consume existing streams.
## Layer Construction
It is possible to declare and construct new layer methods. The method declaration is similar to python.
It is possible to declare and construct new layers. The declaration of a layer is similar to methods in python.
Each parameter can have a default value that makes it an optional argument.
The method call is also similar to python but, in contrast to python, it is necessary to specify the name of each argument.
The body of a new layer is constructed from other layers including other constructed layers. However, recursion is not allowed.
A new layer is constructed from other layers including other constructed layers. However, recursion is not allowed.
The compiler will throw an error if recursion occurs.
The following is a example of multiple method declarations.
The following is a example of multiple layer declarations.
```
def conv(kernel, channels, stride=1, act=true){
Convolution(kernel=(filter,filter), channels=channels, stride=(stride,stride)) ->
BatchNorm() ->
Relu(?=act)
}
def resLayer(channels, stride=1){
def resLayer(channels, stride=1, addSkipConv=false){
(
conv(kernel=3, channels=channels, stride=stride) ->
conv(kernel=3, channels=channels, act=false)
|
conv(kernel=1, channels=channels, stride=stride, act=false, ?=(stride!=1))
conv(kernel=1, channels=channels, stride=stride, act=false, ?=addSkipConv)
) ->
Add() ->
Relu()
}
```
The method `resLayer` in this example corresponds to a building block of a Residual Network.
The constructed layer `resLayer` in this example corresponds to a building block of a Residual Network.
The `?` argument is a special argument which is explained in the next section.
## Structural Arguments
Structural arguments are special arguments which can be set for each layer and which do not correspond to a layer parameter. The three structural arguments are "?", "->" and "|". The conditional argument "?" is a boolean. It does nothing if it is true and it removes the layer completely if it is false. This argument is only useful for layer construction. The other two structural arguments are non-negative integers which repeat the layer *x* number of times where *x* is equal to their value. The layer operator between each repetition has the same symbol as the argument.
Structural arguments are special arguments which can be set for each layer and which do not correspond to a layer parameter.
The three structural arguments are "?", "->" and "|". The conditional argument "?" is a boolean.
It does nothing if it is true and it removes the layer completely if it is false.
This argument is only useful for layer construction.
The other two structural arguments are non-negative integers which repeat the layer *x* number of times where *x* is equal to their value.
The layer operator between each repetition has the same symbol as the argument.
Assuming `a` is a method without required arguments,
then `a(-> = 3)->` is equal to `a()->a()->a()->`,
......@@ -155,9 +159,20 @@ then `a(-> = 3)->` is equal to `a()->a()->a()->`,
`a(-> = 3, | = 2)->` is equal to `(a()->a()->a() | a()->a()->a())->`.
## Argument Sequences
Argument sequences can be used instead of regular arguments to declare that a layer should be repeated with the values of the given sequence. The operator between these so stacked layers is also given by the sequence. Other arguments that only have a single value are neutral to the repetition which means that the single value will be repeated an arbitrary number of times without having influence on the number of repetitions.
The following are valid sequences: `[1->2->3->4]`, `[true | false]`, `{[1 | 3->2]`, `[ |2->3]` and `[1->..->4]`. All values in these examples could also be replaced by variable names or arithmetic or logical expressions. The last sequence is defined as a range and equal to the first one. A range in CNNArch is closed which means the start and end value are both in the sequence. Moreover, a range has always a step size of +1. Thus, the range `[0|..|-4]` would be empty. The data flow operators can be used both in the same argument sequence in which case a single parallelization block is created. A parallel group in this block can be empty, which is why `[ |2->3]` is a valid sequence. If a method contains multiple argument sequences, the language will try to combine them by expanding the smaller one and will throw an error at model creation if this fails. Let `m` be a layer with parameters `a`, `b` and `c`, then the expression `m(a=[3->2],b=1)` is equal to `m(a=3,b=1)->m(a=2,b=1)`. Furthermore, the line `m(a=[5->3],b=[3|4|2],c=2)->` is equal to:
Argument sequences can be used instead of regular arguments to declare that a layer should be repeated with the values of the given sequence.
The operator between these so stacked layers is also given by the sequence.
Other arguments that only have a single value are neutral to the repetition
which means that the single value will be repeated an arbitrary number of times without having an influence on the number of repetitions.
The following are valid sequences: `[1->2->3->4]`, `[true | false]`, `{[1 | 3->2]`, `[ |2->3]` and `[1->..->4]`.
All values in these examples could also be replaced by variable names or arithmetic or logical expressions.
The last sequence is defined as a range and equal to the first one. A range in CNNArch is closed which means the start and end value are both in the sequence.
Moreover, a range has always a step size of +1. Thus, the range `[0|..|-4]` would be empty.
The data flow operators can be used both in the same argument sequence in which case a single parallelization block is created.
A parallel group in this block can be empty, which is why `[ |2->3]` is a valid sequence.
If a method contains multiple argument sequences, the language will try to combine them by expanding the smaller one and will throw an error at model creation if this fails.
Let `m` be a layer with parameters `a`, `b` and `c`, then the expression `m(a=[3->2],b=1)` is equal to `m(a=3,b=1)->m(a=2,b=1)`.
Furthermore, the line `m(a=[5->3],b=[3|4|2],c=2)->` is equal to:
```
(
m(a=5, b=3, c=2) ->
......@@ -186,7 +201,8 @@ However, `m(a=[5->3], b=[2|4->6], c=2)->` and `m(a=[5->3], b=[2->4->6], c=2)->`
## Expressions
This language supports the basic arithmetic operators "+", "-", "\*", "/", the logical operators "&&", "||" and the comparison operators "==", "!=", "<", ">", "<=", ">=".
This language supports the basic arithmetic operators "+", "-", "\*", "/", the logical operators "&&", "||", the comparison operators "==", "!=", "<", ">", "<=", ">="
and the constants `true` and `false`.
At the moment, it is sometimes necessary to use parentheses around an expression to avoid a parsing error.
For example, the line `someMethod(booleanArg = (1!=1))` does not parse without the parentheses around `1!=1`.
......@@ -234,7 +250,7 @@ architecture Alexnet_alt2(img_height=224, img_width=224, img_channels=3, classes
}
```
The following architecture defines ResNet-152.
The following architecture is the extremely deep ResNet-152.
```
architecture ResNet152(img_height=224, img_width=224, img_channels=3, classes=1000){
def input Z(0:255)^{img_channels, img_height, img_width} data
......
This source diff could not be displayed because it is too large. You can view the blob instead.
File added
......@@ -18,21 +18,21 @@ grammar CNNArch extends de.monticore.lang.math.Math {
Use nonterminal Architecture for embedding in another language (e.g. EmbeddedMontiArc)
*/
symbol scope CNNArchCompilationUnit = "architecture"
name:Name&
name:Name
( "(" (ArchitectureParameter || ",")* ")" )? "{"
ioDeclarations:IODeclaration*
Architecture
"}";
MethodDeclaration = NEWLINETOKEN* "def"
Name& "("
parameters:(MethodParameter || ",")* ")" "{" NEWLINETOKEN*
body:ArchBody NEWLINETOKEN* "}";
LayerDeclaration = NEWLINETOKEN* "def"
Name "("
parameters:(LayerParameter || ",")* ")" "{" NEWLINETOKEN*
body:ArchBody NEWLINETOKEN* "}";
IODeclaration = NEWLINETOKEN* "def"
(in:"input" | out:"output")
type:ArchType
Name&
Name
(ArrayDeclaration)?;
......@@ -53,22 +53,24 @@ grammar CNNArch extends de.monticore.lang.math.Math {
Defines the architecture of the neural network.
This NT is used for integration in EmbeddedMontiArc.
@attribute methodDeclaration*
A list of new methods/layers which can be used in the architecture.
A list of new layers which can be used in the architecture.
@attribute body
The architecture of the neural network.
*/
Architecture = NEWLINETOKEN* methodDeclaration:MethodDeclaration* NEWLINETOKEN*
Architecture = NEWLINETOKEN* methodDeclaration:LayerDeclaration* NEWLINETOKEN*
body:ArchBody NEWLINETOKEN*;
scope ArchBody = elements:(ArchitectureElement || "->")*;
interface ArchitectureElement;
IOLayer implements ArchitectureElement = NEWLINETOKEN* Name& ("[" index:ArchSimpleExpression "]")?;
IOElement implements ArchitectureElement = NEWLINETOKEN* Name ("[" index:ArchSimpleExpression "]")?;
MethodLayer implements ArchitectureElement = NEWLINETOKEN* Name& "(" arguments:(ArchArgument || ",")* ")";
Layer implements ArchitectureElement = NEWLINETOKEN* Name "(" arguments:(ArchArgument || ",")* ")";
ParallelLayer implements ArchitectureElement = NEWLINETOKEN* "(" NEWLINETOKEN* groups:ArchBody NEWLINETOKEN* "|" NEWLINETOKEN* groups:(ArchBody || "|")+ NEWLINETOKEN* ")";
ParallelBlock implements ArchitectureElement = NEWLINETOKEN* "(" NEWLINETOKEN*
groups:ArchBody NEWLINETOKEN* "|" NEWLINETOKEN*
groups:(ArchBody || "|")+ NEWLINETOKEN* ")";
ArrayAccessLayer implements ArchitectureElement = NEWLINETOKEN* "[" index:ArchSimpleExpression "]";
......@@ -77,16 +79,17 @@ grammar CNNArch extends de.monticore.lang.math.Math {
interface Variable;
ArchitectureParameter implements Variable = NEWLINETOKEN* Name& ("=" default:ArchSimpleExpression)? NEWLINETOKEN*;
ArchitectureParameter implements Variable = NEWLINETOKEN* Name ("=" default:ArchSimpleExpression)? NEWLINETOKEN*;
MethodParameter implements Variable = NEWLINETOKEN* Name& ("=" default:ArchSimpleExpression)? NEWLINETOKEN*;
LayerParameter implements Variable = NEWLINETOKEN* Name ("=" default:ArchSimpleExpression)? NEWLINETOKEN*;
interface ArchArgument;
ArchParameterArgument implements ArchArgument = NEWLINETOKEN* Name "=" rhs:ArchExpression NEWLINETOKEN*;
ArchSpecialArgument implements ArchArgument = NEWLINETOKEN* (serial:"->" | parallel:"|" | conditional:"?") "="
rhs:ArchExpression NEWLINETOKEN*;
ArchSpecialArgument implements ArchArgument = NEWLINETOKEN*
(serial:"->" | parallel:"|" | conditional:"?") "="
rhs:ArchExpression NEWLINETOKEN*;
/* ======= Value Expressions =======*/
......@@ -108,14 +111,14 @@ grammar CNNArch extends de.monticore.lang.math.Math {
(serial2:"->" | parallel2:"|")
end:ArchSimpleExpression "]";
/**
Expression for variable values.
Expressions for variable values.
*/
ArchSimpleExpression = (arithmeticExpression:MathArithmeticExpression
| booleanExpression:MathBooleanExpression
| tupleExpression:TupleExpression
| string:StringLiteral);
TupleExpression = "(" expressions:MathExpression "," expressions:(MathExpression || ",")* ")";
TupleExpression = "(" expressions:MathArithmeticExpression "," expressions:(MathArithmeticExpression || ",")* ")";
/* =================================*/
......
......@@ -62,7 +62,7 @@ public class CNNArchCocos {
public static CNNArchSymbolCoCoChecker createCNNArchPostResolveSymbolChecker() {
return new CNNArchSymbolCoCoChecker()
.addCoCo(new CheckIOType())
.addCoCo(new CheckLayerInputs())
.addCoCo(new CheckElementInputs())
.addCoCo(new CheckIOAccessAndIOMissing())
.addCoCo(new CheckArchitectureFinished());
}
......@@ -71,17 +71,17 @@ public class CNNArchCocos {
public static CNNArchSymbolCoCoChecker createCNNArchPreResolveSymbolChecker() {
return new CNNArchSymbolCoCoChecker()
.addCoCo(new CheckIOName())
.addCoCo(new CheckNameExpression());
.addCoCo(new CheckExpressions());
}
//checks all normal cocos
public static CNNArchCoCoChecker createASTChecker() {
return new CNNArchCoCoChecker()
.addCoCo(new CheckMethodLayer())
.addCoCo(new CheckLayer())
.addCoCo(new CheckRangeOperators())
.addCoCo(new CheckVariableName())
.addCoCo(new CheckMethodName())
.addCoCo(new CheckLayerName())
.addCoCo(new CheckArgument())
.addCoCo(new CheckMethodRecursion());
.addCoCo(new CheckLayerRecursion());
}
}
......@@ -30,11 +30,11 @@ public class CNNArchSymbolCoCo {
if (sym instanceof ArchitectureSymbol){
check((ArchitectureSymbol) sym);
}
else if (sym instanceof MethodDeclarationSymbol){
check((MethodDeclarationSymbol) sym);
else if (sym instanceof LayerDeclarationSymbol){
check((LayerDeclarationSymbol) sym);
}
else if (sym instanceof LayerSymbol){
check((LayerSymbol) sym);
else if (sym instanceof ArchitectureElementSymbol){
check((ArchitectureElementSymbol) sym);
}
else if (sym instanceof ArchExpressionSymbol){
check((ArchExpressionSymbol) sym);
......@@ -68,11 +68,11 @@ public class CNNArchSymbolCoCo {
//Override if needed
}
public void check(MethodDeclarationSymbol sym){
public void check(LayerDeclarationSymbol sym){
//Override if needed
}
public void check(LayerSymbol sym){
public void check(ArchitectureElementSymbol sym){
//Override if needed
}
......
......@@ -22,7 +22,7 @@ package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._ast.ASTArchArgument;
import de.monticore.lang.monticar.cnnarch._symboltable.ArgumentSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.MethodDeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerDeclarationSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.Joiners;
import de.se_rwth.commons.logging.Log;
......@@ -32,11 +32,11 @@ public class CheckArgument implements CNNArchASTArchArgumentCoCo {
@Override
public void check(ASTArchArgument node) {
ArgumentSymbol argument = (ArgumentSymbol) node.getSymbol().get();
MethodDeclarationSymbol method = argument.getMethodLayer().getMethod();
if (method != null && argument.getParameter() == null){
LayerDeclarationSymbol layerDeclaration = argument.getLayer().getDeclaration();
if (layerDeclaration != null && argument.getParameter() == null){
Log.error("0"+ ErrorCodes.UNKNOWN_ARGUMENT + " Unknown Argument. " +
"Parameter with name '" + node.getName() + "' does not exist. " +
"Possible arguments are: " + Joiners.COMMA.join(method.getParameters())
"Possible arguments are: " + Joiners.COMMA.join(layerDeclaration.getParameters())
, node.get_SourcePositionStart());
}
}
......
......@@ -22,7 +22,7 @@ package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureSymbol;
public class CheckLayerInputs extends CNNArchSymbolCoCo {
public class CheckElementInputs extends CNNArchSymbolCoCo {
@Override
public void check(ArchitectureSymbol architecture) {
......
......@@ -31,16 +31,16 @@ import de.se_rwth.commons.logging.Log;
import java.util.Collection;
public class CheckNameExpression extends CNNArchSymbolCoCo {
public class CheckExpressions extends CNNArchSymbolCoCo {
@Override
public void check(ArchExpressionSymbol sym) {
if (sym instanceof ArchSimpleExpressionSymbol){
checkSimpleExpression((ArchSimpleExpressionSymbol) sym);
checkNamesInExpression((ArchSimpleExpressionSymbol) sym);
}
}
public void checkSimpleExpression(ArchSimpleExpressionSymbol expression) {
public void checkNamesInExpression(ArchSimpleExpressionSymbol expression) {
if (expression.getMathExpression().isPresent()){
MathExpressionSymbol mathExpression = expression.getMathExpression().get();
......@@ -56,8 +56,6 @@ public class CheckNameExpression extends CNNArchSymbolCoCo {
}
}
}
}
}
}
......@@ -22,7 +22,7 @@ package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IODeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IOLayerSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IOSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.Joiners;
import de.se_rwth.commons.logging.Log;
......@@ -48,16 +48,16 @@ public class CheckIOAccessAndIOMissing extends CNNArchSymbolCoCo {
}
private void checkSingleIO(IODeclarationSymbol ioDeclaration){
if (ioDeclaration.getConnectedLayers().isEmpty()){
if (ioDeclaration.getConnectedElements().isEmpty()){
Log.error("0" + ErrorCodes.MISSING_IO + " Input or output '" + ioDeclaration.getName() + "' was declared but never used."
, ioDeclaration.getSourcePosition());
}
else {
for (IOLayerSymbol layer : ioDeclaration.getConnectedLayers()){
if (layer.getArrayAccess().isPresent()){
for (IOSymbol ioElement : ioDeclaration.getConnectedElements()){
if (ioElement.getArrayAccess().isPresent()){
Log.error("0" + ErrorCodes.INVALID_ARRAY_ACCESS + " Invalid IO array access. " +
"This input or output is not an array."
, layer.getSourcePosition());
, ioElement.getSourcePosition());
}
}
}
......@@ -67,17 +67,17 @@ public class CheckIOAccessAndIOMissing extends CNNArchSymbolCoCo {
private void checkIOArray(IODeclarationSymbol ioDeclaration){
List<Integer> unusedIndices = IntStream.range(0, ioDeclaration.getArrayLength()).boxed().collect(Collectors.toList());
for (IOLayerSymbol layer : ioDeclaration.getConnectedLayers()){
if (layer.getArrayAccess().isPresent()){
Optional<Integer> arrayAccess = layer.getArrayAccess().get().getIntValue();
for (IOSymbol ioElement : ioDeclaration.getConnectedElements()){
if (ioElement.getArrayAccess().isPresent()){
Optional<Integer> arrayAccess = ioElement.getArrayAccess().get().getIntValue();
if (arrayAccess.isPresent() && arrayAccess.get() >= 0 && arrayAccess.get() < ioDeclaration.getArrayLength()){
unusedIndices.remove(arrayAccess.get());
}
else {
Log.error("0" + ErrorCodes.INVALID_ARRAY_ACCESS + " The IO array access value of '" + layer.getName() +
Log.error("0" + ErrorCodes.INVALID_ARRAY_ACCESS + " The IO array access value of '" + ioElement.getName() +
"' must be an integer between 0 and " + (ioDeclaration.getArrayLength()-1) + ". " +
"The current value is: " + layer.getArrayAccess().get().getValue().get().toString()
, layer.getSourcePosition());
"The current value is: " + ioElement.getArrayAccess().get().getValue().get().toString()
, ioElement.getSourcePosition());
}
}
else{
......
......@@ -20,9 +20,9 @@
*/
package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureElementSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IODeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IOLayerSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IOSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.logging.Log;
......@@ -35,19 +35,19 @@ public class CheckIOName extends CNNArchSymbolCoCo {
private Set<IODeclarationSymbol> checkedIODeclarations = new HashSet<>();
@Override
public void check(LayerSymbol sym) {
if (sym instanceof IOLayerSymbol){
checkIOLayer((IOLayerSymbol) sym);
public void check(ArchitectureElementSymbol sym) {
if (sym instanceof IOSymbol){
checkIOElement((IOSymbol) sym);
}
}
public void checkIOLayer(IOLayerSymbol ioLayer) {
Collection<IODeclarationSymbol> ioDeclarations = ioLayer.getEnclosingScope().resolveMany(ioLayer.getName(), IODeclarationSymbol.KIND);
public void checkIOElement(IOSymbol ioElement) {
Collection<IODeclarationSymbol> ioDeclarations = ioElement.getEnclosingScope().resolveMany(ioElement.getName(), IODeclarationSymbol.KIND);
if (ioDeclarations.isEmpty()){
Log.error("0" + ErrorCodes.UNKNOWN_IO + " Unknown input or output name. " +
"The input or output '" + ioLayer.getName() + "' does not exist"
, ioLayer.getSourcePosition());
"The input or output '" + ioElement.getName() + "' does not exist"
, ioElement.getSourcePosition());
}
else {
IODeclarationSymbol ioDeclaration = ioDeclarations.iterator().next();
......
......@@ -41,7 +41,7 @@ public class CheckIOType extends CNNArchSymbolCoCo {
public void checkIO(IODeclarationSymbol ioDeclaration) {
ArchTypeSymbol type = ioDeclaration.getType();
if (type.getElementType().isIsComplex() || type.getElementType().isIsBoolean()){
if (type.getDomain().isIsComplex() || type.getDomain().isIsBoolean()){
Log.error("0" + ErrorCodes.INVALID_IO_TYPE + " Invalid IO element type. " +
"Type has to be rational or whole number.");
}
......
......@@ -21,10 +21,10 @@
package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._ast.ASTArchArgument;
import de.monticore.lang.monticar.cnnarch._ast.ASTMethodLayer;
import de.monticore.lang.monticar.cnnarch._ast.ASTLayer;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.MethodDeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.MethodLayerSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerDeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.VariableSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.Joiners;
......@@ -33,10 +33,10 @@ import de.se_rwth.commons.logging.Log;
import java.util.HashSet;
import java.util.Set;
public class CheckMethodLayer implements CNNArchASTMethodLayerCoCo{
public class CheckLayer implements CNNArchASTLayerCoCo{
@Override
public void check(ASTMethodLayer node) {
public void check(ASTLayer node) {
Set<String> nameSet = new HashSet<>();
for (ASTArchArgument argument : node.getArguments()){
String name = argument.getName();
......@@ -50,17 +50,17 @@ public class CheckMethodLayer implements CNNArchASTMethodLayerCoCo{
}
}
MethodDeclarationSymbol method = ((MethodLayerSymbol) node.getSymbol().get()).getMethod();
if (method == null){
LayerDeclarationSymbol layerDeclaration = ((LayerSymbol) node.getSymbol().get()).getDeclaration();
if (layerDeclaration == null){
ArchitectureSymbol architecture = node.getSymbol().get().getEnclosingScope().<ArchitectureSymbol>resolve("", ArchitectureSymbol.KIND).get();
Log.error("0" + ErrorCodes.UNKNOWN_METHOD + " Unknown method error. " +
"Method with name '" + node.getName() + "' does not exist. " +
"Existing methods: " + Joiners.COMMA.join(architecture.getMethodDeclarations()) + "."
Log.error("0" + ErrorCodes.UNKNOWN_LAYER + " Unknown layer. " +
"Layer with name '" + node.getName() + "' does not exist. " +
"Existing layers: " + Joiners.COMMA.join(architecture.getLayerDeclarations()) + "."
, node.get_SourcePositionStart());
}
else {
Set<String> requiredArguments = new HashSet<>();
for (VariableSymbol param : method.getParameters()){
for (VariableSymbol param : layerDeclaration.getParameters()){
if (!param.getDefaultExpression().isPresent()){
requiredArguments.add(param.getName());
}
......
......@@ -20,19 +20,19 @@
*/
package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._ast.ASTMethodDeclaration;
import de.monticore.lang.monticar.cnnarch._ast.ASTLayerDeclaration;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.logging.Log;
import java.util.HashSet;
import java.util.Set;
public class CheckMethodName implements CNNArchASTMethodDeclarationCoCo {
public class CheckLayerName implements CNNArchASTLayerDeclarationCoCo {
Set<String> methodNames = new HashSet<>();
@Override
public void check(ASTMethodDeclaration node) {
public void check(ASTLayerDeclaration node) {
String name = node.getName();
if (name.isEmpty() || !Character.isLowerCase(name.codePointAt(0))){
Log.error("0" + ErrorCodes.ILLEGAL_NAME + " Illegal name: " + name +
......
......@@ -20,48 +20,48 @@
*/
package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._ast.ASTMethodDeclaration;
import de.monticore.lang.monticar.cnnarch._symboltable.CompositeLayerSymbol;
import de.monticore.lang.monticar.cnnarch._ast.ASTLayerDeclaration;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureElementSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.CompositeElementSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerDeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.MethodDeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.MethodLayerSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.logging.Log;
import java.util.HashSet;
import java.util.Set;
public class CheckMethodRecursion implements CNNArchASTMethodDeclarationCoCo {
public class CheckLayerRecursion implements CNNArchASTLayerDeclarationCoCo {
Set<MethodDeclarationSymbol> seenMethods = new HashSet<>();
Set<LayerDeclarationSymbol> seenLayers = new HashSet<>();
boolean done;
@Override