diff --git a/src/jastadd/ast/CollectionAttributes.jrag b/src/jastadd/ast/CollectionAttributes.jrag index 306084c6a43a2dd35174b0dcc9b9402988ca6c14..545f871930fb0cfc56b8335ccfd680babd59b2c9 100644 --- a/src/jastadd/ast/CollectionAttributes.jrag +++ b/src/jastadd/ast/CollectionAttributes.jrag @@ -36,8 +36,12 @@ aspect CollectionAttributes { eq CollDecl.isCollection() = true; + /** @return the type name of the collection root node */ syn String CollDecl.rootType() = root().name(); + /** @return the type name of the collection root node */ + syn String CollEq.rootType() = decl().rootType(); + /** @return the return type of the collection attribute */ syn String CollEq.getType() = decl().getType(); @@ -117,6 +121,7 @@ aspect CollectionAttributes { } syn TypeDecl AttrDecl.root() = grammar().root(); + eq CollDecl.root() = root != null ? grammar().lookup(root) : super.root(); // Only used by circular collection attributes. diff --git a/src/jastadd/ast/JragCodeGen.jrag b/src/jastadd/ast/JragCodeGen.jrag index 06c311ac361b3feb86747ff75e0071fa703569c7..eaf12b6eb7199fa55fe054f7fe844e3ed9cfd49c 100644 --- a/src/jastadd/ast/JragCodeGen.jrag +++ b/src/jastadd/ast/JragCodeGen.jrag @@ -220,17 +220,16 @@ aspect JragCodeGen { if (config().lazyMaps()) { if (!isCircular()) { if (getNumParameter() != 0 && config().visitCheckEnabled() && config().rewriteEnabled()) { - sb.append("if (" + signature() + "_visited == null) " + signature() - + "_visited = " + config().createDefaultMap() + ";\n"); - } - else if (getNumParameter() != 0 && config().visitCheckEnabled()) { - sb.append("if (" + signature() + "_visited == null) " + signature() - + "_visited = " + config().createDefaultSet() + ";\n"); + sb.append(String.format("if (%s_visited == null) %s_visited = %s;\n", + signature(), signature(), config().createDefaultMap())); + } else if (getNumParameter() != 0 && config().visitCheckEnabled()) { + sb.append(String.format("if (%s_visited == null) %s_visited = %s;\n", + signature(), signature(), config().createDefaultSet())); } } if (getNumParameter() != 0 && (isLazy() || isCircular())) { - sb.append("if (" + signature() + "_values == null) " + signature() - + "_values = " + config().createDefaultMap() + ";\n"); + sb.append(String.format("if (%s_values == null) %s_values = %s;\n", + signature(), signature(), config().createDefaultMap())); } } return sb.toString(); @@ -257,7 +256,9 @@ aspect JragCodeGen { * @return {@code true} if the attribute is declared as NTA in the aspect file */ syn boolean AttrDecl.declaredNTA() = false; + eq SynDecl.declaredNTA() = getNTA(); + eq InhDecl.declaredNTA() = getNTA(); public static String ASTNode.boxedType(String type) { @@ -413,7 +414,7 @@ aspect JragCodeGen { public boolean TypeDecl.hasLazySynEqFor(AttrDecl attr) { if (attr instanceof SynDecl) { SynEq synEq = lookupSynEq(attr.signature()); - return synEq != null && (synEq.decl().isLazy() || synEq.decl().isCircular()) ; + return synEq != null && (synEq.decl().isLazy() || synEq.decl().isCircular()); } return false; } @@ -663,7 +664,7 @@ aspect JragCodeGen { + " was affected by a bug causing the equation value to be discarded! " + "(fixed since version 2.1.11)"); } - String attrName = getName().substring(3); // remove get + String attrName = getName().substring(3); if (comp.name().equals(attrName) && comp instanceof AggregateComponentNTA || attrName.equals(comp.name() + "Opt") && comp instanceof OptionalComponentNTA || attrName.equals(comp.name() + "List") && comp instanceof ListComponentNTA) { diff --git a/src/template/ast/Circular.tt b/src/template/ast/Circular.tt index 30c338cc03abab63a1edc9c8d35ecc22d7d6a24b..e51626b118a85a1cabb9048343b42d37f10eced7 100644 --- a/src/template/ast/Circular.tt +++ b/src/template/ast/Circular.tt @@ -45,7 +45,7 @@ $if(#isCollection) while (_node != null && !(_node instanceof #rootType)) { _node = _node.getParent(); } - $include(collDebugCheck) + $include(CollDecl.collDebugCheck) #rootType root = (#rootType) _node; if (root.collecting_contributors_#collectionId) { throw new RuntimeException("Circularity during survey phase"); diff --git a/src/template/ast/Collections.tt b/src/template/ast/Collections.tt index df3cb9df9572588461e0e1f5b4c63380e9bf9664..afb127437f5f74e96cca289796ca98d6c43b3ab6 100644 --- a/src/template/ast/Collections.tt +++ b/src/template/ast/Collections.tt @@ -25,11 +25,11 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -collDebugCheck [[ +CollDecl.collDebugCheck [[ $if(DebugMode) if (node == null) { throw new RuntimeException( - "Trying to evaluate collection attribute in subtree not attached to main tree"); + "Trying to evaluate collection attribute #getTarget.#getName() in subtree not attached to main tree."); } $endif ]] @@ -41,7 +41,7 @@ CollDecl.computeMethod:onePhase [[ while (node != null && !(node instanceof #rootType)) { node = node.getParent(); } - $include(collDebugCheck) + $include(CollDecl.collDebugCheck) #rootType root = (#rootType) node; root.survey_#collectionId(); if (#(signature)_value == null) { @@ -58,7 +58,7 @@ CollDecl.computeMethod:twoPhase [[ while (node != null && !(node instanceof #rootType)) { node = node.getParent(); } - $include(collDebugCheck) + $include(CollDecl.collDebugCheck) #rootType root = (#rootType) node; root.survey_#collectionId(); #getType _computedValue = $BottomValue; @@ -71,7 +71,7 @@ CollDecl.computeMethod:twoPhase [[ } ]] -CollEq.collectContributors:onePhase = [[ +CollEq.collectContributors:onePhase [[ // #declaredat $if(HasCondition) if (#getCondition) { @@ -85,13 +85,12 @@ $endif CollEq.contribution:onePhase [[ $if(#iterableTarget) for (#getTargetName target : (Iterable<? extends #getTargetName>) (#getReference)) { - if (target != null) { - if (target.#(signature)_value == null) { - target.#(signature)_value = $BottomValue; - } - #getType collection = target.#(signature)_value; - $include(CollEq.addValueToCollection) + $include(CollEq.targetDebugCheck) + if (target.#(signature)_value == null) { + target.#(signature)_value = $BottomValue; } + #getType collection = target.#(signature)_value; + $include(CollEq.addValueToCollection) } $else { @@ -103,19 +102,18 @@ $if(#implicitTarget) $include(CollEq.addValueToCollection) $else #getTargetName target = #getReference; - if (target != null) { - if (target.#(signature)_value == null) { - target.#(signature)_value = $BottomValue; - } - #getType collection = target.#(signature)_value; - $include(CollEq.addValueToCollection) + $include(CollEq.targetDebugCheck) + if (target.#(signature)_value == null) { + target.#(signature)_value = $BottomValue; } + #getType collection = target.#(signature)_value; + $include(CollEq.addValueToCollection) $endif } $endif ]] -CollEq.collectContributors:twoPhase = [[ +CollEq.collectContributors:twoPhase [[ // #declaredat $if(HasCondition) if (#getCondition) { @@ -129,41 +127,62 @@ $endif CollEq.contribution:twoPhase [[ $if(#iterableTarget) for (#getTargetName target : (Iterable<? extends #getTargetName>) (#getReference)) { - if (target != null) { - java.util.Set<$ASTNode> contributors = _map.get(target); - if (contributors == null) { - contributors = new java.util.HashSet<$ASTNode>(); - _map.put(($ASTNode) target, contributors); - } - contributors.add(this); + $include(CollEq.targetDebugCheck) + java.util.Set<$ASTNode> contributors = _map.get(target); + if (contributors == null) { + contributors = new java.util.HashSet<$ASTNode>(); + _map.put(($ASTNode) target, contributors); } + contributors.add(this); } $else { $if(#implicitTarget) - if (_root != null) { - java.util.Set<$ASTNode> contributors = _map.get(_root); - if (contributors == null) { - contributors = new java.util.HashSet<$ASTNode>(); - _map.put(($ASTNode) _root, contributors); - } - contributors.add(this); + java.util.Set<$ASTNode> contributors = _map.get(_root); + if (contributors == null) { + contributors = new java.util.HashSet<$ASTNode>(); + _map.put(($ASTNode) _root, contributors); } + contributors.add(this); $else #getTargetName target = (#getTargetName) (#getReference); - if (target != null) { - java.util.Set<$ASTNode> contributors = _map.get(target); - if (contributors == null) { - contributors = new java.util.HashSet<$ASTNode>(); - _map.put(($ASTNode) target, contributors); - } - contributors.add(this); + $include(CollEq.targetDebugCheck) + java.util.Set<$ASTNode> contributors = _map.get(target); + if (contributors == null) { + contributors = new java.util.HashSet<$ASTNode>(); + _map.put(($ASTNode) target, contributors); } + contributors.add(this); $endif } $endif ]] +CollEq.targetDebugCheck [[ +$if(DebugMode) +ASTNode _targetRoot = target; +ASTNode _targetParent = target; +while (_targetParent != null) { + _targetParent = _targetParent.getParent(); + if (_targetParent instanceof #rootType) { + _targetRoot = _targetParent; + } +} +ASTNode _sourceRoot = _root; +ASTNode _sourceParent = _root; +while (_sourceParent != null) { + _sourceParent = _sourceParent.getParent(); + if (_sourceParent instanceof #rootType) { + _sourceRoot = _sourceParent; + } +} +if (_targetRoot != _sourceRoot) { + throw new RuntimeException("Contribution source and target do not share a common collection " + + "root node for collection attribute #getTargetName.#getTargetAttributeName()."); +} +$endif +]] + CollDecl.collectContributors:header [[ $if(#onePhase) protected void collect_contributors_#collectionId(#rootType _root) { @@ -188,7 +207,7 @@ $endif } ]] -CollDecl.contributeTo:default = [[ +CollDecl.contributeTo:default [[ protected void contributeTo_#(signature)(#getType collection) { } ]] @@ -255,7 +274,7 @@ $endif } ]] -Collection.flush = [[ +Collection.flush [[ $if(#onePhase) collect_contributors_#collectionId = false; $else