Commit 0ceeba09 authored by Alexander Ryndin's avatar Alexander Ryndin
Browse files

impl. struct and enum gen

parent cb87fa39
......@@ -8,6 +8,8 @@ import de.monticore.lang.monticar.generator.Generator;
import de.monticore.lang.monticar.generator.Helper;
import de.monticore.lang.monticar.generator.MathCommandRegister;
import de.monticore.lang.monticar.generator.cpp.converter.MathConverter;
import de.monticore.lang.monticar.generator.cpp.converter.TypeConverter;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.monticore.symboltable.Scope;
import de.se_rwth.commons.logging.Log;
......@@ -18,6 +20,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
......@@ -42,6 +45,7 @@ public class GeneratorCPP implements Generator {
public GeneratorCPP() {
this.mathCommandRegister = new MathCommandRegisterCPP();
useOctaveBackend();
TypeConverter.clearTypeSymbols();
}
public void useArmadilloBackend() {
......@@ -137,6 +141,7 @@ public class GeneratorCPP implements Generator {
public List<File> generateFiles(TaggingResolver taggingResolver, ExpandedComponentInstanceSymbol componentSymbol,
Scope symtab) throws IOException {
List<FileContent> fileContents = generateStrings(taggingResolver, componentSymbol, symtab);
fileContents.addAll(generateTypes(TypeConverter.getTypeSymbols()));
if (isGenerateTests()) {
TestsGeneratorCPP g = new TestsGeneratorCPP(this);
fileContents.addAll(g.generateStreamTests(symtab));
......@@ -263,4 +268,9 @@ public class GeneratorCPP implements Generator {
public List<BluePrintCPP> getBluePrints() {
return Collections.unmodifiableList(bluePrints);
}
private static List<FileContent> generateTypes(Collection<MCTypeSymbol> typeSymbols) {
TypesGeneratorCPP tg = new TypesGeneratorCPP();
return tg.generateTypes(typeSymbols);
}
}
package de.monticore.lang.monticar.generator.cpp;
import de.monticore.lang.monticar.enumlang._symboltable.EnumDeclarationSymbol;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.cpp.template.AllTemplates;
import de.monticore.lang.monticar.generator.cpp.viewmodel.EnumViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.StructViewModel;
import de.monticore.lang.monticar.struct._symboltable.StructFieldDefinitionSymbol;
import de.monticore.lang.monticar.struct._symboltable.StructSymbol;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.se_rwth.commons.logging.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public final class TypesGeneratorCPP {
public static final String TYPES_DIRECTORY_NAME = "types";
private List<FileContent> files;
public List<FileContent> generateTypes(Collection<MCTypeSymbol> typeSymbols) {
Set<String> processedTypes = new HashSet<>();
files = new ArrayList<>();
for (MCTypeSymbol s : typeSymbols) {
if (processedTypes.add(s.getFullName())) {
processSymbol(s);
}
}
return Collections.unmodifiableList(files);
}
private void processSymbol(MCTypeSymbol s) {
if (s instanceof StructSymbol) {
processStruct((StructSymbol) s);
} else if (s instanceof EnumDeclarationSymbol) {
processEnum((EnumDeclarationSymbol) s);
} else {
Log.warn("unknown type symbol: " + s.getFullName());
}
}
private void processStruct(StructSymbol s) {
for (StructFieldDefinitionSymbol sfd : s.getStructFieldDefinitions()) {
processSymbol(sfd.getType().getReferencedSymbol());
}
StructViewModel vm = StructViewModel.fromSymbol(s);
files.add(new FileContent(AllTemplates.generateStruct(vm), TYPES_DIRECTORY_NAME + "/" + vm.getIncludeName() + ".h"));
}
private void processEnum(EnumDeclarationSymbol s) {
EnumViewModel vm = EnumViewModel.fromSymbol(s);
files.add(new FileContent(AllTemplates.generateEnum(vm), TYPES_DIRECTORY_NAME + "/" + vm.getIncludeName() + ".h"));
}
}
......@@ -13,14 +13,18 @@ import de.monticore.lang.monticar.common2._ast.ASTCommonMatrixType;
import de.monticore.lang.monticar.generator.Variable;
import de.monticore.lang.monticar.generator.VariableType;
import de.monticore.lang.monticar.generator.cpp.GeneralHelperMethods;
import de.monticore.lang.monticar.generator.cpp.TypesGeneratorCPP;
import de.monticore.lang.monticar.generator.cpp.viewmodel.Utils;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.monticore.lang.monticar.ts.references.MCTypeReference;
import de.monticore.lang.monticar.types2._ast.ASTType;
import de.se_rwth.commons.logging.Log;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* This is used to convert port types to their cpp equivalent
......@@ -29,6 +33,7 @@ import java.util.Optional;
*/
public class TypeConverter {
private static List<VariableType> nonPrimitiveVariableTypes = new ArrayList<>();
private static Set<MCTypeSymbol> typeSymbols = new HashSet<>();
@Deprecated
......@@ -163,6 +168,17 @@ public class TypeConverter {
return Optional.of(variableType);
}
}
MCTypeSymbol s = portSymbol.getTypeReference().getReferencedSymbol();
String name = s.getName();
String fullName = s.getFullName();
if (typeNameMontiCar != null && (typeNameMontiCar.equals(name) || typeNameMontiCar.equals(fullName))) {
String cppName = Utils.getIncludeName(s);
String includeName = TypesGeneratorCPP.TYPES_DIRECTORY_NAME + "/" + cppName;
typeSymbols.add(s);
VariableType vt = new VariableType(fullName, cppName, includeName);
addNonPrimitiveVariableType(vt);
return Optional.of(vt);
}
Log.info(typeNameMontiCar, "Unknown Type:");
//Log.error("0xUNPOTYFOBYGE Unknown Port Type found by generator");
return Optional.empty();
......@@ -231,6 +247,14 @@ public class TypeConverter {
return type;
}
public static void clearTypeSymbols() {
typeSymbols = new HashSet<>();
}
public static Set<MCTypeSymbol> getTypeSymbols() {
return Collections.unmodifiableSet(typeSymbols);
}
static {
addNonPrimitiveVariableType("SIUnitRangesType", "double", "");
addNonPrimitiveVariableType("B", "bool", "");
......
package de.monticore.lang.monticar.generator.cpp.template;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ComponentStreamTestViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.EnumViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.StructViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.TestsMainEntryViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ViewModelBase;
import de.se_rwth.commons.logging.Log;
......@@ -16,6 +18,8 @@ public final class AllTemplates {
private static final Template COMPONENT_STREAM_TEST;
private static final Template TESTS_MAIN_ENTRY;
private static final Template STRUCT;
private static final Template ENUM;
static {
Configuration conf = new Configuration(Configuration.VERSION_2_3_23);
......@@ -26,6 +30,8 @@ public final class AllTemplates {
try {
COMPONENT_STREAM_TEST = conf.getTemplate("/test/ComponentStreamTest.ftl");
TESTS_MAIN_ENTRY = conf.getTemplate("/test/TestsMainEntry.ftl");
STRUCT = conf.getTemplate("/type/Struct.ftl");
ENUM = conf.getTemplate("/type/Enum.ftl");
} catch (IOException e) {
String msg = "could not load templates";
Log.error(msg, e);
......@@ -44,6 +50,14 @@ public final class AllTemplates {
return generate(TESTS_MAIN_ENTRY, viewModel);
}
public static String generateStruct(StructViewModel viewModel) {
return generate(STRUCT, viewModel);
}
public static String generateEnum(EnumViewModel viewModel) {
return generate(ENUM, viewModel);
}
private static String generate(Template template, ViewModelBase viewModelBase) {
return generate(template, TemplateHelper.getDataForTemplate(viewModelBase));
}
......
package de.monticore.lang.monticar.generator.cpp.viewmodel;
import de.monticore.lang.monticar.enumlang._symboltable.EnumConstantDeclarationSymbol;
import de.monticore.lang.monticar.enumlang._symboltable.EnumDeclarationSymbol;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class EnumViewModel extends ViewModelBase {
private String includeName = "";
private List<String> constants = Collections.emptyList();
public String getIncludeName() {
return includeName;
}
public void setIncludeName(String includeName) {
this.includeName = includeName;
}
public List<String> getConstants() {
return constants;
}
public void setConstants(List<String> constants) {
this.constants = constants;
}
public static EnumViewModel fromSymbol(EnumDeclarationSymbol s) {
EnumViewModel vm = new EnumViewModel();
vm.setIncludeName(Utils.getIncludeName(s));
List<String> c = new ArrayList<>();
for (EnumConstantDeclarationSymbol ec : s.getEnumConstants()) {
c.add(ec.getName());
}
vm.setConstants(c);
return vm;
}
}
package de.monticore.lang.monticar.generator.cpp.viewmodel;
import de.monticore.lang.monticar.enumlang._symboltable.EnumDeclarationSymbol;
import de.monticore.lang.monticar.struct._symboltable.StructFieldDefinitionSymbol;
import de.monticore.lang.monticar.struct._symboltable.StructSymbol;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.se_rwth.commons.logging.Log;
public class StructFieldViewModel extends ViewModelBase {
private String name = "";
private String type = "";
private String initializer = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getInitializer() {
return initializer;
}
public void setInitializer(String initializer) {
this.initializer = initializer;
}
public static StructFieldViewModel fromSymbol(StructFieldDefinitionSymbol s) {
StructFieldViewModel vm = new StructFieldViewModel();
vm.setName(s.getName());
MCTypeSymbol ts = s.getType().getReferencedSymbol();
String fullName = ts.getFullName();
if ("Q".equals(fullName)) {
vm.setType("double");
vm.setInitializer("0.0");
} else if ("B".equals(fullName)) {
vm.setType("bool");
vm.setInitializer("false");
} else if ("Z".equals(fullName)) {
vm.setType("int");
vm.setInitializer("0");
} else if (ts instanceof StructSymbol) {
vm.setType(Utils.getIncludeName(ts));
} else if (ts instanceof EnumDeclarationSymbol) {
vm.setType(Utils.getIncludeName(ts));
} else {
Log.error("unknown type: " + ts.getFullName());
}
return vm;
}
}
package de.monticore.lang.monticar.generator.cpp.viewmodel;
import de.monticore.lang.monticar.enumlang._symboltable.EnumDeclarationSymbol;
import de.monticore.lang.monticar.struct._symboltable.StructFieldDefinitionSymbol;
import de.monticore.lang.monticar.struct._symboltable.StructSymbol;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class StructViewModel extends ViewModelBase {
private String includeName = "";
private Set<String> additionalIncludes = Collections.emptySet();
private List<StructFieldViewModel> fields = Collections.emptyList();
public String getIncludeName() {
return includeName;
}
public void setIncludeName(String includeName) {
this.includeName = includeName;
}
public Set<String> getAdditionalIncludes() {
return additionalIncludes;
}
public void setAdditionalIncludes(Set<String> additionalIncludes) {
this.additionalIncludes = additionalIncludes;
}
public List<StructFieldViewModel> getFields() {
return fields;
}
public void setFields(List<StructFieldViewModel> fields) {
this.fields = fields;
}
public static StructViewModel fromSymbol(StructSymbol s) {
StructViewModel vm = new StructViewModel();
vm.setIncludeName(Utils.getIncludeName(s));
Set<String> additionalIncludes = new HashSet<>();
List<StructFieldViewModel> fields = new ArrayList<>();
for (StructFieldDefinitionSymbol sfd : s.getStructFieldDefinitions()) {
MCTypeSymbol fieldTypeSym = sfd.getType().getReferencedSymbol();
if (fieldTypeSym instanceof StructSymbol || fieldTypeSym instanceof EnumDeclarationSymbol) {
additionalIncludes.add(Utils.getIncludeName(fieldTypeSym));
}
fields.add(StructFieldViewModel.fromSymbol(sfd));
}
vm.setAdditionalIncludes(additionalIncludes);
vm.setFields(fields);
return vm;
}
}
package de.monticore.lang.monticar.generator.cpp.viewmodel;
import de.monticore.symboltable.Symbol;
public final class Utils {
private Utils() {
}
public static String getIncludeName(Symbol s) {
return s.getFullName().replace('.', '_');
}
}
......@@ -10,6 +10,7 @@ import de.monticore.io.paths.ModelPath;
import de.monticore.lang.embeddedmontiarc.LogConfig;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ConstantPortSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarcmath._symboltable.EmbeddedMontiArcMathLanguage;
import de.monticore.lang.monticar.enumlang._symboltable.EnumLangLanguage;
import de.monticore.lang.monticar.generator.cpp.converter.MathConverter;
import de.monticore.lang.monticar.generator.optimization.ThreadingOptimizer;
import de.monticore.lang.monticar.generator.order.nfp.TagBreakpointsTagSchema.TagBreakpointsTagSchema;
......@@ -20,6 +21,7 @@ import de.monticore.lang.monticar.generator.order.nfp.TagMinMaxTagSchema.TagMinM
import de.monticore.lang.monticar.generator.order.nfp.TagTableTagSchema.TagTableTagSchema;
import de.monticore.lang.monticar.generator.order.nfp.TagThresholdTagSchema.TagThresholdTagSchema;
import de.monticore.lang.monticar.streamunits._symboltable.StreamUnitsLanguage;
import de.monticore.lang.monticar.struct._symboltable.StructLanguage;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.monticore.symboltable.GlobalScope;
import de.monticore.symboltable.Scope;
......@@ -55,6 +57,8 @@ public class AbstractSymtab {
fam.addModelingLanguage(montiArcLanguage);
fam.addModelingLanguage(new StreamUnitsLanguage());
fam.addModelingLanguage(new StructLanguage());
fam.addModelingLanguage(new EnumLangLanguage());
final ModelPath mp = new ModelPath();
for (String m : modelPath) {
mp.addEntry(Paths.get(m));
......
<#include "/Common.ftl">
#ifndef ${viewModel.includeName?upper_case}
#define ${viewModel.includeName?upper_case}
enum ${viewModel.includeName} {
<#list viewModel.constants as ec>
${ec}<#sep>,</#sep>
</#list>
};
#endif
<#include "/Common.ftl">
#ifndef ${viewModel.includeName?upper_case}
#define ${viewModel.includeName?upper_case}
<#list viewModel.additionalIncludes as inc>
#include "${inc}.h"
</#list>
struct ${viewModel.includeName} {
<#list viewModel.fields as f>
${f.type} ${f.name}<#if f.initializer?has_content> = ${f.initializer}</#if>;
</#list>
};
#endif
......@@ -11,6 +11,7 @@ import org.junit.Assert;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
......@@ -29,6 +30,14 @@ public class AbstractSymtabTest extends AbstractSymtab {
}
}
public static void checkFilesAreEqual(List<File> generatedFiles, Path generatedFilesBasePath, String resultsPath) {
for (File f : generatedFiles) {
Path relativePath = generatedFilesBasePath.relativize(f.toPath());
File fileTarget = new File("./src/test/resources/results/" + resultsPath + relativePath.toString());
assertTrue(areBothFilesEqual(f, fileTarget));
}
}
public static boolean areBothFilesEqual(File file1, File file2) {
if (!file1.exists()) {
Assert.fail("file does not exist: " + file1.getAbsolutePath());
......
......@@ -13,6 +13,7 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import static org.junit.Assert.assertEquals;
......@@ -445,7 +446,6 @@ public class GenerationTest extends AbstractSymtabTest {
}
@Test
@Ignore("https://github.com/EmbeddedMontiArc/EMAM2Cpp/issues/11")
public void testMyComponent2() throws IOException {
TaggingResolver symTab = createSymTabAndTaggingResolver("src/test/resources");
ExpandedComponentInstanceSymbol componentSymbol = symTab.<ExpandedComponentInstanceSymbol>resolve(
......@@ -456,7 +456,12 @@ public class GenerationTest extends AbstractSymtabTest {
GeneratorCPP generatorCPP = new GeneratorCPP();
generatorCPP.setGenerationTargetPath("./target/generated-sources-cpp/testing/MyComponent2");
List<File> files = generatorCPP.generateFiles(componentSymbol, symTab);
Assert.assertEquals(2, files.size());
Assert.assertFalse(files.isEmpty());
checkFilesAreEqual(
files,
Paths.get("./target/generated-sources-cpp/testing/MyComponent2"),
"testing/MyComponent2/"
);
}
@Test
......
package de.monticore.lang.monticar.generator.cpp.template;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ComponentStreamTestViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.EnumViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.StreamViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.StructFieldViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.StructViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.TestsMainEntryViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.check.BooleanOutputPortCheck;
import de.monticore.lang.monticar.generator.cpp.viewmodel.check.ComponentCheckViewModel;
......@@ -12,6 +15,7 @@ import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class AllTemplatesTest {
......@@ -99,4 +103,78 @@ public class AllTemplatesTest {
Assert.assertTrue("fragment " + f + " was expected", result.contains(f));
}
}
@Test
public void testGenerateEnum() {
EnumViewModel vm = new EnumViewModel();
vm.setIncludeName("de_project_modeling_autopilot_TestEnum");
vm.setConstants(Arrays.asList(
"UNO", "DOS", "TRES"
));
String result = AllTemplates.generateEnum(vm);
Assert.assertNotNull(result);
String[] expectedFragments = new String[]{
"#ifndef DE_PROJECT_MODELING_AUTOPILOT_TESTENUM",
"#define DE_PROJECT_MODELING_AUTOPILOT_TESTENUM",
"#endif",
"enum de_project_modeling_autopilot_TestEnum {",
"UNO",
"DOS",
"TRES"
};
for (String f : expectedFragments) {
Assert.assertTrue("fragment " + f + " was expected", result.contains(f));
}
}
@Test
public void testGenerateStruct() {
StructViewModel vm = new StructViewModel();
vm.setIncludeName("de_project_modeling_autopilot_TestStruct1");
vm.setAdditionalIncludes(new HashSet<>(Arrays.asList(
"de_project_modeling_autopilot_TestEnum1",
"de_project_modeling_autopilot_TestStruct2"
)));
vm.setFields(new ArrayList<>());
StructFieldViewModel f1 = new StructFieldViewModel();
f1.setName("field1");
f1.setType("double");
f1.setInitializer("0.0");
vm.getFields().add(f1);
StructFieldViewModel f2 = new StructFieldViewModel();
f2.setName("field2");
f2.setType("bool");
f2.setInitializer("false");
vm.getFields().add(f2);
StructFieldViewModel f3 = new StructFieldViewModel();
f3.setName("field3");
f3.setType("int");
f3.setInitializer("0");
vm.getFields().add(f3);
StructFieldViewModel f4 = new StructFieldViewModel();
f4.setName("field4");
f4.setType("de_project_modeling_autopilot_TestEnum1");
vm.getFields().add(f4);
StructFieldViewModel f5 = new StructFieldViewModel();
f5.setName("field5");