Verified Commit 1b497621 authored by Stefan Brunecker's avatar Stefan Brunecker
Browse files

Move getDimension to GeneratorUtil

parent 19b087cc
......@@ -3,8 +3,16 @@ package de.monticore.lang.monticar.generator;
import static de.monticore.lang.monticar.contract.Precondition.requiresNotNull;
import static de.monticore.lang.monticar.contract.StringPrecondition.requiresNotBlank;
import com.google.common.annotations.VisibleForTesting;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymbol;
import de.monticore.lang.monticar.common2._ast.ASTCommonDimensionElement;
import de.monticore.lang.monticar.common2._ast.ASTCommonMatrixType;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.monticore.lang.monticar.ts.references.MCASTTypeSymbolReference;
import de.monticore.lang.monticar.ts.references.MCTypeReference;
import de.monticore.lang.monticar.types2._ast.ASTType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.springframework.util.StringUtils;
......@@ -45,4 +53,62 @@ public class GeneratorUtil {
public static String getGetterMethodName(String portName) {
return GETTER_PREFIX + StringUtils.capitalize(requiresNotBlank(portName));
}
@VisibleForTesting
public static String[] getDimension(Collection<PortSymbol> ports, PortSymbol port) {
int arrayDimension = port.isPartOfPortArray() ?
getArrayDimension(ports, port.getNameWithoutArrayBracketPart()) : 0;
int[] matrixDimension = getMatrixDimension(port);
return combineDimensions(arrayDimension, matrixDimension);
}
private static String[] combineDimensions(int arrayDimension, int[] matrixDimension) {
if (arrayDimension > 0 && matrixDimension.length > 0) {
int[] dimension = new int[matrixDimension.length + 1];
dimension[0] = arrayDimension;
System.arraycopy(matrixDimension, 0, dimension, 1, matrixDimension.length);
return toStringArray(dimension);
} else if (matrixDimension.length > 0) {
return toStringArray(matrixDimension);
} else if (arrayDimension > 0) {
return new String[]{String.valueOf(arrayDimension)};
} else {
return new String[0];
}
}
private static int getArrayDimension(Collection<PortSymbol> ports, String arrayName) {
int dimension = 0;
for (PortSymbol port : ports) {
if (port.getNameWithoutArrayBracketPart().equals(arrayName)) {
dimension++;
}
}
return dimension;
}
private static int[] getMatrixDimension(PortSymbol port) {
MCTypeReference<? extends MCTypeSymbol> typeReference = port.getTypeReference();
if (typeReference instanceof MCASTTypeSymbolReference) {
ASTType type = ((MCASTTypeSymbolReference) typeReference).getAstType();
if (type instanceof ASTCommonMatrixType) {
ASTCommonMatrixType matrixType = (ASTCommonMatrixType) type;
List<ASTCommonDimensionElement> dimensionElements = matrixType.getCommonDimension()
.getCommonDimensionElements();
int[] dimensions = new int[dimensionElements.size()];
for (int i = 0; i < dimensionElements.size(); i++) {
final int index = i;
dimensionElements.get(i).getUnitNumber().ifPresent(unitNumber -> {
unitNumber.getNumber().ifPresent(dim -> dimensions[index] = dim.intValue());
});
}
return dimensions;
}
}
return new int[0];
}
private static String[] toStringArray(int[] array) {
return Arrays.stream(array).mapToObj(String::valueOf).toArray(String[]::new);
}
}
package de.monticore.lang.monticar.generator.js;
import static de.monticore.lang.monticar.generator.GeneratorUtil.filterMultipleArrayPorts;
import static de.monticore.lang.monticar.generator.GeneratorUtil.getDimension;
import static de.monticore.lang.monticar.generator.GeneratorUtil.getGetterMethodName;
import static de.monticore.lang.monticar.generator.GeneratorUtil.getSetterMethodName;
import com.google.common.annotations.VisibleForTesting;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymbol;
import de.monticore.lang.monticar.common2._ast.ASTCommonDimensionElement;
import de.monticore.lang.monticar.common2._ast.ASTCommonMatrixType;
import de.monticore.lang.monticar.freemarker.TemplateProcessor;
import de.monticore.lang.monticar.ranges._ast.ASTRange;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.monticore.lang.monticar.ts.references.MCASTTypeSymbolReference;
import de.monticore.lang.monticar.ts.references.MCTypeReference;
import de.monticore.lang.monticar.types2._ast.ASTElementType;
import de.monticore.lang.monticar.types2._ast.ASTType;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.measure.unit.Unit;
import org.jscience.mathematics.number.Rational;
public class JsGenerator {
private static final String PARAMETER_NAME = "param";
private final TemplateProcessor templateProcessor;
public JsGenerator(TemplateProcessor templateProcessor) {
......@@ -68,60 +62,6 @@ public class JsGenerator {
return null;
}
@VisibleForTesting
static String[] getDimension(Collection<PortSymbol> ports, PortSymbol port) {
int arrayDimension = port.isPartOfPortArray() ?
getArrayDimension(ports, port.getNameWithoutArrayBracketPart()) : 0;
int[] matrixDimension = getMatrixDimension(port);
return combineDimensions(arrayDimension, matrixDimension);
}
private static String[] combineDimensions(int arrayDimension, int[] matrixDimension) {
if (arrayDimension > 0 && matrixDimension.length > 0) {
int[] dimension = new int[matrixDimension.length + 1];
dimension[0] = arrayDimension;
System.arraycopy(matrixDimension, 0, dimension, 1, matrixDimension.length);
return toStringArray(dimension);
} else if (matrixDimension.length > 0) {
return toStringArray(matrixDimension);
} else if (arrayDimension > 0) {
return new String[]{String.valueOf(arrayDimension)};
} else {
return null;
}
}
private static int getArrayDimension(Collection<PortSymbol> ports, String arrayName) {
int dimension = 0;
for (PortSymbol port : ports) {
if (port.getNameWithoutArrayBracketPart().equals(arrayName)) {
dimension++;
}
}
return dimension;
}
private static int[] getMatrixDimension(PortSymbol port) {
MCTypeReference<? extends MCTypeSymbol> typeReference = port.getTypeReference();
if (typeReference instanceof MCASTTypeSymbolReference) {
ASTType type = ((MCASTTypeSymbolReference) typeReference).getAstType();
if (type instanceof ASTCommonMatrixType) {
ASTCommonMatrixType matrixType = (ASTCommonMatrixType) type;
List<ASTCommonDimensionElement> dimensionElements = matrixType.getCommonDimension()
.getCommonDimensionElements();
int[] dimensions = new int[dimensionElements.size()];
for (int i = 0; i < dimensionElements.size(); i++) {
final int index = i;
dimensionElements.get(i).getUnitNumber().ifPresent(unitNumber -> {
unitNumber.getNumber().ifPresent(dim -> dimensions[index] = dim.intValue());
});
}
return dimensions;
}
}
return new int[0];
}
private static Optional<ASTRange> getRange(PortSymbol port) {
MCASTTypeSymbolReference typeReference = (MCASTTypeSymbolReference) port.getTypeReference();
ASTType astType = typeReference.getAstType();
......@@ -136,14 +76,6 @@ public class JsGenerator {
}
}
private static String join(String delimiter, String... elements) {
return Arrays.stream(elements).filter(s -> !s.isEmpty()).collect(Collectors.joining(delimiter));
}
private static <T> String[] toStringArray(int[] array) {
return Arrays.stream(array).mapToObj(String::valueOf).toArray(String[]::new);
}
private static String format(Unit<?> unit) {
return unit.toString()
.replaceAll("²", "^2")
......
......@@ -53,7 +53,7 @@ function execute() {
throw "${portName}: Could not evaluate input";
}
<#if setter.dimension??>
<#if setter.dimension?has_content>
//check dimension
var dim = math.matrix([${setter.dimension?join(", ")}]);
if (!math.deepEqual(math.size(${varName}), dim)) {
......
package de.monticore.lang.monticar.generator;
import static de.monticore.lang.monticar.generator.GeneratorUtil.filterMultipleArrayPorts;
import static de.monticore.lang.monticar.generator.GeneratorUtil.getDimension;
import static de.monticore.lang.monticar.generator.GeneratorUtil.getGetterMethodName;
import static de.monticore.lang.monticar.generator.GeneratorUtil.getSetterMethodName;
import static org.assertj.core.api.Assertions.assertThat;
......@@ -15,6 +16,7 @@ import de.monticore.lang.monticar.resolver.Resolver;
import de.monticore.lang.monticar.resolver.ResolverFactory;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
......@@ -37,6 +39,21 @@ class GeneratorUtilTest {
private static final String ARRAY_BASE_NAME = "array";
private static final String NOT_ARRAY_NAME = "somePort";
private static final String IN = "in";
private static final String OUT = "out";
private static final String DIMENSION_MODEL = "models.dimensions";
private static final String SCALAR = "Scalar";
private static final String ARRAY = "Array[1]";
private static final String ROW_VECTOR = "RowVector";
private static final String COLUMN_VECTOR = "ColumnVector";
private static final String MATRIX = "Matrix";
private static final String MATRIX_ARRAY = "MatrixArray[2]";
private static String portName(String direction, String name) {
return direction + name;
}
@Nested
class FilterMultipleArrayPorts {
......@@ -275,4 +292,137 @@ class GeneratorUtilTest {
}
}
@Nested
class GetDimension {
private ExpandedComponentInstanceSymbol dimensionModel;
@BeforeEach
void setUp() {
ResolverFactory resolverFactory = new ResolverFactory(RESOLVING_BASE_DIR);
Resolver resolver = resolverFactory.get();
dimensionModel = resolver.getExpandedComponentInstanceSymbol(DIMENSION_MODEL);
}
@Nested
class ShouldReturnEmptyArray {
@Nested
class GivenIncomingPort {
@Test
void whenScalar() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, SCALAR)).get();
assertThat(getDimension(ports, port)).isEmpty();
}
}
@Nested
class GivenOutgoingPort {
@Test
void whenScalar() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, SCALAR)).get();
assertThat(getDimension(ports, port)).isEmpty();
}
}
}
@Nested
class ShouldReturnDimensionArray {
@Nested
class GivenIncomingPort {
@Test
void whenArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("3");
}
@Test
void whenRowVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, ROW_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("1", "3");
}
@Test
void whenColumnVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, COLUMN_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("4", "1");
}
@Test
void whenMatrix() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, MATRIX)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3");
}
@Test
void whenMatrixArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, MATRIX_ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3", "4");
}
}
@Nested
class GivenOutgoingPort {
@Test
void whenArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("3");
}
@Test
void whenRowVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, ROW_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("1", "3");
}
@Test
void whenColumnVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, COLUMN_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("4", "1");
}
@Test
void whenMatrix() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, MATRIX)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3");
}
@Test
void whenMatrixArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, MATRIX_ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3", "4");
}
}
}
}
}
\ No newline at end of file
package de.monticore.lang.monticar.generator.js;
import static de.monticore.lang.monticar.generator.js.JsGenerator.getDimension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymbol;
import de.monticore.lang.monticar.freemarker.TemplateProcessor;
import de.monticore.lang.monticar.resolver.Resolver;
import de.monticore.lang.monticar.resolver.ResolverFactory;
......@@ -15,40 +12,15 @@ import freemarker.template.TemplateException;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@SuppressWarnings("ConstantConditions")
class JsGeneratorTest {
private static final Path RESOLVING_BASE_DIR = Paths.get("src/test/resources/jsfilegeneration");
private static final String IN = "in";
private static final String OUT = "out";
private static final String RANGE_MODEL = "models.multiplePorts";
private static final String DIMENSION_MODEL = "models.dimensions";
private static final String SCALAR = "Scalar";
private static final String ARRAY = "Array[1]";
private static final String ROW_VECTOR = "RowVector";
private static final String COLUMN_VECTOR = "ColumnVector";
private static final String MATRIX = "Matrix";
private static final String MATRIX_ARRAY = "MatrixArray[2]";
private ExpandedComponentInstanceSymbol model;
private static String portName(String direction, String name) {
return direction + name;
}
@BeforeEach
void setUp() {
ResolverFactory resolverFactory = new ResolverFactory(RESOLVING_BASE_DIR);
model = resolverFactory.get().getExpandedComponentInstanceSymbol(RANGE_MODEL);
}
@Nested
class Generate {
......@@ -71,137 +43,4 @@ class JsGeneratorTest {
verify(templateProcessor).process(any());
}
}
@Nested
class GetDimension {
private ExpandedComponentInstanceSymbol dimensionModel;
@BeforeEach
void setUp() {
ResolverFactory resolverFactory = new ResolverFactory(RESOLVING_BASE_DIR);
Resolver resolver = resolverFactory.get();
dimensionModel = resolver.getExpandedComponentInstanceSymbol(DIMENSION_MODEL);
}
@Nested
class ShouldReturnNull {
@Nested
class GivenIncomingPort {
@Test
void whenScalar() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, SCALAR)).get();
assertThat(getDimension(ports, port)).isNull();
}
}
@Nested
class GivenOutgoingPort {
@Test
void whenScalar() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, SCALAR)).get();
assertThat(getDimension(ports, port)).isNull();
}
}
}
@Nested
class ShouldReturnDimensionArray {
@Nested
class GivenIncomingPort {
@Test
void whenArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("3");
}
@Test
void whenRowVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, ROW_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("1", "3");
}
@Test
void whenColumnVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, COLUMN_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("4", "1");
}
@Test
void whenMatrix() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, MATRIX)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3");
}
@Test
void whenMatrixArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getIncomingPort(portName(IN, MATRIX_ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3", "4");
}
}
@Nested
class GivenOutgoingPort {
@Test
void whenArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("3");
}
@Test
void whenRowVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, ROW_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("1", "3");
}
@Test
void whenColumnVector() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, COLUMN_VECTOR)).get();
assertThat(getDimension(ports, port)).containsExactly("4", "1");
}
@Test
void whenMatrix() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, MATRIX)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3");
}
@Test
void whenMatrixArray() {
Collection<PortSymbol> ports = dimensionModel.getPorts();
PortSymbol port = dimensionModel.getOutgoingPort(portName(OUT, MATRIX_ARRAY)).get();
assertThat(getDimension(ports, port)).containsExactly("2", "3", "4");
}
}
}
}