diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java index b167d5bf8cca1cceedb174f140545d30dd0466f8..be0a8742ba9e07ace5ef48b282edb7f62fff446c 100644 --- a/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java +++ b/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java @@ -1,24 +1,31 @@ package de.hhu.stups.codegenerator.generators; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + import de.hhu.stups.codegenerator.analyzers.DeferredSetAnalyzer; import de.hhu.stups.codegenerator.handlers.NameHandler; import de.hhu.stups.codegenerator.handlers.TemplateHandler; import de.prob.parser.ast.nodes.DeclarationNode; import de.prob.parser.ast.nodes.EnumeratedSetDeclarationNode; +import de.prob.parser.ast.nodes.FreetypeBaseElementNode; +import de.prob.parser.ast.nodes.FreetypeConstructorNode; +import de.prob.parser.ast.nodes.FreetypeDeclarationNode; +import de.prob.parser.ast.nodes.FreetypeElementNode; import de.prob.parser.ast.nodes.MachineNode; import de.prob.parser.ast.nodes.MachineReferenceNode; import de.prob.parser.ast.nodes.OperationNode; -import de.prob.parser.ast.types.CoupleType; import de.prob.parser.ast.types.SetType; + import org.stringtemplate.v4.ST; import org.stringtemplate.v4.STGroup; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - public class DeclarationGenerator { private final STGroup currentGroup; @@ -37,6 +44,8 @@ public class DeclarationGenerator { private final DeferredSetAnalyzer deferredSetAnalyzer; + private final Map<String, String> freetypeToMachine; + public DeclarationGenerator(final STGroup currentGroup, final MachineGenerator machineGenerator, final TypeGenerator typeGenerator, final ImportGenerator importGenerator, final NameHandler nameHandler, final DeferredSetAnalyzer deferredSetAnalyzer) { @@ -49,6 +58,7 @@ public class DeclarationGenerator { this.deferredSetAnalyzer = deferredSetAnalyzer; this.setToEnum = new HashMap<>(); this.enumToMachine = new HashMap<>(); + this.freetypeToMachine = new HashMap<>(); } /* @@ -354,4 +364,52 @@ public class DeclarationGenerator { return enumToMachine; } + public Map<String, String> getFreetypeToMachine() { + return freetypeToMachine; + } + + /* + * Generate all declarations for the freetypes included in the given machine. + */ + public List<String> generateFreetypeDeclarations(MachineNode node) { + node.getFreetypes().forEach(ft -> { + freetypeToMachine.put(ft.getFreetypeDeclarationNode().getName(), node.getName()); + }); + return node.getFreetypes().stream() + .flatMap(ft -> this.declareFreetype(ft).stream()) + .collect(Collectors.toList()); + } + + /* + * Generate the declaration for one freetype. + */ + private List<String> declareFreetype(FreetypeDeclarationNode node) { + List<String> result = new ArrayList<>(); + + String ftName = nameHandler.handleIdentifier(node.getFreetypeDeclarationNode().getName(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES); + + ST ftDeclaration = currentGroup.getInstanceOf("freetype_declaration"); + TemplateHandler.add(ftDeclaration, "name", ftName); + result.add(ftDeclaration.render()); + + for (FreetypeBaseElementNode element : node.getElements()) { + ST ftElement; + if (element instanceof FreetypeElementNode) { + ftElement = currentGroup.getInstanceOf("freetype_element_declaration"); + } else if (element instanceof FreetypeConstructorNode) { + FreetypeConstructorNode c = (FreetypeConstructorNode) element; + ftElement = currentGroup.getInstanceOf("freetype_constructor_declaration"); + SetType type = (SetType) c.getExpr().getType(); + TemplateHandler.add(ftElement, "subtype", typeGenerator.generate(type.getSubType())); + } else { + throw new AssertionError(); + } + + TemplateHandler.add(ftElement, "freetype", ftName); + TemplateHandler.add(ftElement, "name", nameHandler.handleIdentifier(element.getName(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES)); + result.add(ftElement.render()); + } + + return result; + } } diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java index 84cb6906c01027322cb58b1ce8c9ce58359e61d7..925b70a0941ac7c623d8679453cbb17fa214846a 100755 --- a/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java +++ b/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java @@ -1,5 +1,13 @@ package de.hhu.stups.codegenerator.generators; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + import de.hhu.stups.codegenerator.CodeGeneratorUtils; import de.hhu.stups.codegenerator.GeneratorMode; import de.hhu.stups.codegenerator.MachineConstantsOptimizer; @@ -11,7 +19,11 @@ import de.hhu.stups.codegenerator.handlers.NameHandler; import de.hhu.stups.codegenerator.handlers.ParallelConstructHandler; import de.hhu.stups.codegenerator.handlers.TemplateHandler; import de.hhu.stups.codegenerator.json.modelchecker.ModelCheckingInfo; -import de.prob.parser.ast.nodes.*; +import de.prob.parser.ast.nodes.DeclarationNode; +import de.prob.parser.ast.nodes.MachineNode; +import de.prob.parser.ast.nodes.MachineReferenceNode; +import de.prob.parser.ast.nodes.Node; +import de.prob.parser.ast.nodes.OperationNode; import de.prob.parser.ast.nodes.expression.ExprNode; import de.prob.parser.ast.nodes.expression.ExpressionOperatorNode; import de.prob.parser.ast.nodes.expression.IdentifierExprNode; @@ -54,12 +66,10 @@ import de.prob.parser.ast.nodes.substitution.WhileSubstitutionNode; import de.prob.parser.ast.types.CoupleType; import de.prob.parser.ast.types.UntypedType; import de.prob.parser.ast.visitors.AbstractVisitor; + import org.stringtemplate.v4.ST; import org.stringtemplate.v4.STGroup; -import java.util.*; -import java.util.stream.Collectors; - /* * The code generator is implemented by using the visitor pattern */ @@ -326,6 +336,7 @@ public class MachineGenerator implements AbstractVisitor<String, Void> { enumIdentifier.addAll(identifier); TemplateHandler.add(machine, "enum_imports", importGenerator.getImportedEnums()); TemplateHandler.add(machine, "sets", declarationGenerator.generateSetDeclarations(node)); + TemplateHandler.add(machine, "freetypes", declarationGenerator.generateFreetypeDeclarations(node)); TemplateHandler.add(machine, "declarations", declarationGenerator.visitDeclarations(node.getVariables())); TemplateHandler.add(machine, "includes", declarationGenerator.generateIncludes(node)); TemplateHandler.add(machine, "initialization", substitutionGenerator.visitInitialization(node)); diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java index bd79323f898faa11fee07f929fdcd130fa4f6348..6e9696a5768af0e6289ae3a71b7d8bbaae53d784 100644 --- a/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java +++ b/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java @@ -8,6 +8,7 @@ import de.prob.parser.ast.types.BoolType; import de.prob.parser.ast.types.CoupleType; import de.prob.parser.ast.types.DeferredSetElementType; import de.prob.parser.ast.types.EnumeratedSetElementType; +import de.prob.parser.ast.types.FreetypeType; import de.prob.parser.ast.types.IntegerType; import de.prob.parser.ast.types.RecordType; import de.prob.parser.ast.types.SetType; @@ -53,14 +54,17 @@ public class TypeGenerator { return generateEnumeratedSetElement((EnumeratedSetElementType) type); } else if(type instanceof DeferredSetElementType) { return generateDeferredSetElement((DeferredSetElementType) type); + } else if(type instanceof FreetypeType) { + return generateFreetype((FreetypeType) type); } else if(type instanceof CoupleType) { return generateBTuple((CoupleType) type); } else if(type instanceof RecordType) { return generateBStruct((RecordType) type); } else if(type instanceof UntypedType) { return generateUntyped(); + } else { + throw new IllegalArgumentException("Unsupported type: " + type); } - return ""; } /* @@ -165,6 +169,18 @@ public class TypeGenerator { return template.render(); } + /* + * This function generates code for the type of a freetype + */ + private String generateFreetype(FreetypeType type) { + ST template = group.getInstanceOf("type"); + TemplateHandler.add(template, "fromOtherMachine", declarationGenerator.getFreetypeToMachine().get(type.getName()) != null && !machineGenerator.getMachineName().equals(declarationGenerator.getFreetypeToMachine().get(type.getName()))); + TemplateHandler.add(template, "otherMachine", declarationGenerator.getFreetypeToMachine().get(type.getName())); + TemplateHandler.add(template, "fromOutside", fromOutside); + TemplateHandler.add(template, "type", nameHandler.handleIdentifier(type.toString(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES)); + return template.render(); + } + /* * This function generates code for untyped nodes. */ diff --git a/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java b/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java index a49f7a5a8f7026f88c976cdc643fd82b68d22591..03729fb05659341a234c5dc7d6ee1e37a3433870 100644 --- a/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java +++ b/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java @@ -1,12 +1,5 @@ package de.hhu.stups.codegenerator.handlers; -import de.hhu.stups.codegenerator.GeneratorMode; -import de.hhu.stups.codegenerator.generators.MachineGenerator; -import de.prob.parser.ast.nodes.DeclarationNode; -import de.prob.parser.ast.nodes.MachineNode; -import org.stringtemplate.v4.ST; -import org.stringtemplate.v4.STGroup; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -14,6 +7,14 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import de.hhu.stups.codegenerator.GeneratorMode; +import de.hhu.stups.codegenerator.generators.MachineGenerator; +import de.prob.parser.ast.nodes.DeclarationNode; +import de.prob.parser.ast.nodes.MachineNode; + +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; + import static de.hhu.stups.codegenerator.handlers.NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES; import static de.hhu.stups.codegenerator.handlers.NameHandler.IdentifierHandlingEnum.INCLUDED_MACHINES; import static de.hhu.stups.codegenerator.handlers.NameHandler.IdentifierHandlingEnum.MACHINES; @@ -51,12 +52,15 @@ public class NameHandler { private List<String> deferredTypes; + private Map<String, List<String>> freeTypes; + public NameHandler(final MachineGenerator machineGenerator, final STGroup group) { this.machineGenerator = machineGenerator; this.group = group; this.globals = new ArrayList<>(); this.enumTypes = new HashMap<>(); this.deferredTypes = new ArrayList<>(); + this.freeTypes = new HashMap<>(); this.reservedMachines = new ArrayList<>(); this.reservedMachinesWithIncludedMachines = new ArrayList<>(); this.reservedMachinesAndFunctions = new ArrayList<>(); @@ -75,6 +79,14 @@ public class NameHandler { } }); deferredTypes.addAll(node.getDeferredSets().stream().map(DeclarationNode::getName).collect(Collectors.toList())); + node.getFreetypes().forEach(ft -> { + List<String> elementsAsString = ft.getElements().stream().map(DeclarationNode::getName).collect(Collectors.toList()); + if (node.getPrefix() != null && !node.equals(machineGenerator.getMachineNode())) { + freeTypes.put(node.getPrefix() + "." + ft.getFreetypeDeclarationNode().getName(), elementsAsString); + } else { + freeTypes.put(ft.getFreetypeDeclarationNode().getName(), elementsAsString); + } + }); reservedMachines.addAll(node.getMachineReferences().stream() .map(reference -> handle(reference.getMachineName())) .collect(Collectors.toList())); @@ -199,6 +211,10 @@ public class NameHandler { return deferredTypes; } + public Map<String, List<String>> getFreeTypes() { + return freeTypes; + } + public Map<String, String> getEnumToMachine() { return machineGenerator.getDeclarationGenerator().getEnumToMachine(); } diff --git a/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg b/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg index c1a28afcb5d75dabc98bc788ad1a37aeddc6a8c3..2083b9dd0a129cbaecbc90392dbde5b0cb197f2d 100644 --- a/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg +++ b/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg @@ -3,7 +3,7 @@ abstract, assert, boolean, break, byte, case, catch, char, class, continue, defa >> -machine(forModelChecking, imports, machine, projectionClasses, structs, constants_declarations, includes, enums, sets, declarations, initialization, mainMethod, copyConstructor, operations, addition, getters, transitions, projection, invariant, copy, hash_equal, modelcheck, lambdaFunctions, choicePoints, choicePointsGetters, choicePointOperationFlags, choicePointOperationFlagGetters, choicePointOperationFlagResets, choicePointOperationTriggered, choicePointOperationTriggeredResets, choicePointOperationTriggeredFlags, choicePointOperationApplies, externalFunctions) ::= << +machine(forModelChecking, imports, machine, projectionClasses, structs, constants_declarations, includes, enums, freetypes, sets, declarations, initialization, mainMethod, copyConstructor, operations, addition, getters, transitions, projection, invariant, copy, hash_equal, modelcheck, lambdaFunctions, choicePoints, choicePointsGetters, choicePointOperationFlags, choicePointOperationFlagGetters, choicePointOperationFlagResets, choicePointOperationTriggered, choicePointOperationTriggeredResets, choicePointOperationTriggeredFlags, choicePointOperationApplies, externalFunctions) ::= << <imports; separator="\n"> <if(forModelChecking)> import java.util.HashMap; @@ -87,6 +87,8 @@ public class <machine> { <enums; separator="\n\n"> + <freetypes; separator="\n\n"> + <sets; separator="\n"> <declarations; separator="\n"> @@ -586,6 +588,91 @@ public enum <name> implements BObject { } >> +freetype_declaration(name) ::= << +public static abstract class <name> extends BFreetype { + + protected <name>() { + } +} +>> + +freetype_element_declaration(name,freetype) ::= << +public static final class <name> extends <freetype> { + + public static final <name> INSTANCE = new <name>(); + + private <name>() { + } + + public BBoolean equal(<freetype> o) { + return new BBoolean(this.equals(o)); + } + + public BBoolean unequal(<freetype> o) { + return this.equal(o).not(); + } + + @Override + public boolean equals(Object o) { + return o instanceof <name>; + } + + @Override + public int hashCode() { + return this.getClass().hashCode(); + } + + @Override + public String toString() { + return "<name>"; + } +} +>> + +freetype_constructor_declaration(name,freetype,subtype) ::= << +public final class <name> extends <freetype> { + + private final <subtype> value; + + public <name>(<subtype> value) { + this.value = value; + } + + public <subtype> getValue() { + return this.value; + } + + public BBoolean equal(<freetype> o) { + return new BBoolean(this.equals(o)); + } + + public BBoolean unequal(<freetype> o) { + return this.equal(o).not(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof <name>)) { + return false; + } else { + return this.value.equals(((<name>) o).value); + } + } + + @Override + public int hashCode() { + return Objects.hash(this.getClass(), this.value); + } + + @Override + public String toString() { + return "<name>(" + this.value + ")"; + } +} +>> + bool() ::= << BUtils.BOOL >>