Skip to content
Snippets Groups Projects
Commit 202083ed authored by Jesper's avatar Jesper
Browse files

Add NTA collection contribution statement

see #256 (bitbucket)
parent 040530d5
No related branches found
No related tags found
No related merge requests found
2016-03-23 Jesper Öqvist <jesper.oqvist@cs.lth.se>
* Added a new variation of the contributes statement to allow NTA children
to contribute to a collection attribute.
2016-03-22 Jesper Öqvist <jesper.oqvist@cs.lth.se> 2016-03-22 Jesper Öqvist <jesper.oqvist@cs.lth.se>
* Added code generation for getXNoTransform(int) to access list children * Added code generation for getXNoTransform(int) to access list children
......
...@@ -1474,6 +1474,18 @@ For example, if the collection attribute is declared as `coll ...@@ -1474,6 +1474,18 @@ For example, if the collection attribute is declared as `coll
LinkedList<String> ...` then `value-exp` should have the type LinkedList<String> ...` then `value-exp` should have the type
`Iterable<String>`. `Iterable<String>`.
#### NTA Contributions
It is possible to add contributions from an NTA child to a collection attribute
using the following variation of the `contributes` statement:
N1 contributes getMyNta() to N2.a();
The above statement means that the NTA child named `MyNta` in node type `N1` is
also searched for contributions during the survey phase of the evaluation of
the collection attribute `N2.a()`.
#### Custom Collection Survey #### Custom Collection Survey
It is possible to customize the tree traversal used to search for contributions It is possible to customize the tree traversal used to search for contributions
......
...@@ -225,22 +225,80 @@ aspect CollectionAttributes { ...@@ -225,22 +225,80 @@ aspect CollectionAttributes {
} }
} }
class BlockSurveyContribution implements SurveyContribution { abstract class CustomSurveyContribution implements SurveyContribution {
private final CustomSurveyBlock block; protected final String collName;
public BlockSurveyContribution(CustomSurveyBlock block) { protected final String collHost;
this.block = block; protected final String fileName;
protected final int startLine;
protected final int endLine;
protected final String comment;
protected final String aspectName;
public CustomSurveyContribution(String collName, String collHost,
String fileName, int startLine, int endLine, String comment,
String aspectName) {
this.collName = collName;
this.collHost = collHost;
this.fileName = fileName;
this.startLine = startLine;
this.endLine = endLine;
this.comment = comment;
this.aspectName = aspectName;
}
public CollDecl lookupCollDecl(Grammar grammar) {
CollDecl decl = grammar.lookupCollDecl(collHost, collName);
if (decl == null) {
throw new Error(String.format(
"%s:%d: Can not add custom survey code for unknown collection attribute: %s.%s()",
fileName, startLine, collHost, collName));
}
return decl;
}
}
class BlockSurveyContribution extends CustomSurveyContribution {
private final String surveyCode;
public BlockSurveyContribution(String collName, String collHost, String surveyCode,
String fileName, int startLine, int endLine, String comment,
String aspectName) {
super(collName, collHost, fileName, startLine, endLine, comment, aspectName);
this.surveyCode = surveyCode;
} }
@Override @Override
public void emitSurveyCode(CollDecl decl, PrintStream out) { public void emitSurveyCode(CollDecl decl, PrintStream out) {
out.println(block.comment); out.println(comment);
String replacement; String replacement;
if (decl.onePhase()) { if (decl.onePhase()) {
replacement = String.format(".collect_contributors_%s(_root);", decl.collectionId()); replacement = String.format(".collect_contributors_%s(_root);", decl.collectionId());
} else { } else {
replacement = String.format(".collect_contributors_%s(_root, _map);", decl.collectionId()); replacement = String.format(".collect_contributors_%s(_root, _map);", decl.collectionId());
} }
out.println(block.surveyCode.replaceAll("\\.collectContributions\\(\\);", replacement)); out.println(surveyCode.replaceAll("\\.collectContributions\\(\\);", replacement));
}
}
class ExpressionSurveyContribution extends CustomSurveyContribution {
private final String ntaExpression;
public ExpressionSurveyContribution(String collName, String collHost, String ntaExpression,
String fileName, int startLine, int endLine, String comment,
String aspectName) {
super(collName, collHost, fileName, startLine, endLine, comment, aspectName);
this.ntaExpression = ntaExpression;
}
@Override
public void emitSurveyCode(CollDecl decl, PrintStream out) {
out.println(comment);
if (decl.onePhase()) {
out.format("%s.collect_contributors_%s(_root);%n", ntaExpression, decl.collectionId());
} else {
out.format("%s.collect_contributors_%s(_root, _map);%n",
ntaExpression, decl.collectionId());
}
} }
} }
...@@ -262,19 +320,14 @@ aspect CollectionAttributes { ...@@ -262,19 +320,14 @@ aspect CollectionAttributes {
equations.add(new EqSurveyContribution(attr)); equations.add(new EqSurveyContribution(attr));
} }
for (CustomSurveyBlock block : customSurveyBlocks) { for (CustomSurveyContribution survey : surveyContributions) {
CollDecl decl = grammar().lookupCollDecl(block.collHost, block.collName); CollDecl decl = survey.lookupCollDecl(grammar());
if (decl == null) { Collection<SurveyContribution> contributions = map.get(decl);
throw new Error(String.format( if (contributions == null) {
"%s:%d: Can not add custom survey code for unknown collection attribute: %s.%s()", contributions = new ArrayList<SurveyContribution>();
block.fileName, block.startLine, block.collHost, block.collName)); map.put(decl, contributions);
}
Collection<SurveyContribution> equations = map.get(decl);
if (equations == null) {
equations = new ArrayList<SurveyContribution>();
map.put(decl, equations);
} }
equations.add(new BlockSurveyContribution(block)); contributions.add(survey);
} }
for (Map.Entry<CollDecl, Collection<SurveyContribution>> entry : map.entrySet()) { for (Map.Entry<CollDecl, Collection<SurveyContribution>> entry : map.entrySet()) {
...@@ -516,32 +569,8 @@ aspect CollectionAttributes { ...@@ -516,32 +569,8 @@ aspect CollectionAttributes {
return null; return null;
} }
public class CustomSurveyBlock { public final Collection<CustomSurveyContribution> ASTDecl.surveyContributions =
public final String collName; new LinkedList<CustomSurveyContribution>();
public final String collHost;
public final String surveyCode;
public final String fileName;
public final int startLine;
public final int endLine;
public final String comment;
public final String aspectName;
public CustomSurveyBlock(String collName, String collHost, String surveyCode,
String fileName, int startLine, int endLine, String comment,
String aspectName) {
this.collName = collName;
this.collHost = collHost;
this.surveyCode = surveyCode;
this.fileName = fileName;
this.startLine = startLine;
this.endLine = endLine;
this.comment = comment;
this.aspectName = aspectName;
}
}
public final Collection<CustomSurveyBlock> ASTDecl.customSurveyBlocks =
new LinkedList<CustomSurveyBlock>();
/** /**
* Adds code to the survey method for a particular collection attribute in the * Adds code to the survey method for a particular collection attribute in the
...@@ -559,7 +588,7 @@ aspect CollectionAttributes { ...@@ -559,7 +588,7 @@ aspect CollectionAttributes {
ArrayList<String> annotations) { ArrayList<String> annotations) {
TypeDecl type = lookup(nodeType); TypeDecl type = lookup(nodeType);
if (type != null && type instanceof ASTDecl) { if (type != null && type instanceof ASTDecl) {
((ASTDecl) type).customSurveyBlocks.add(new CustomSurveyBlock( ((ASTDecl) type).surveyContributions.add(new BlockSurveyContribution(
collName, collName,
collHost, collHost,
codeBlock, codeBlock,
...@@ -577,6 +606,40 @@ aspect CollectionAttributes { ...@@ -577,6 +606,40 @@ aspect CollectionAttributes {
} }
} }
/**
* Adds an expression for an NTA child which should be searched during the
* survey phase of a collection attribute.
*/
public void Grammar.addCustomSurveyExpression(String collHost,
String collName,
String nodeType,
String ntaExpression,
String fileName,
int startLine,
int endLine,
org.jastadd.jrag.AST.SimpleNode commentNode,
String aspectName,
ArrayList<String> annotations) {
TypeDecl type = lookup(nodeType);
if (type != null && type instanceof ASTDecl) {
((ASTDecl) type).surveyContributions.add(new ExpressionSurveyContribution(
collName,
collHost,
ntaExpression,
fileName,
startLine,
endLine,
Unparser.unparseComment(commentNode),
aspectName));
for (String annotation : annotations) {
errorf("annotation %s not allowed for custom survey blocks.", annotation);
}
} else {
errorf("Can not add custom collection survey code to unknown class %s in %s at line %d",
nodeType, fileName, startLine);
}
}
public CollEq Grammar.addCollEq(String collHost, public CollEq Grammar.addCollEq(String collHost,
String collName, String collName,
String nodeType, String reference, String fileName, String nodeType, String reference, String fileName,
......
...@@ -1374,6 +1374,7 @@ void CollectionContribution(): ...@@ -1374,6 +1374,7 @@ void CollectionContribution():
SimpleNode block; SimpleNode block;
SimpleNode value = null; SimpleNode value = null;
SimpleNode condition = null; SimpleNode condition = null;
SimpleNode ntaExpression = null;
String targetName; String targetName;
String targetAttributeName; String targetAttributeName;
String attributeType; String attributeType;
...@@ -1390,7 +1391,10 @@ void CollectionContribution(): ...@@ -1390,7 +1391,10 @@ void CollectionContribution():
t = <IDENTIFIER> { first = token; attributeType = t.image; } t = <IDENTIFIER> { first = token; attributeType = t.image; }
"contributes" "contributes"
( (
[ LOOKAHEAD("each") "each" { iterableValue = true; } ] LOOKAHEAD("nta") "nta"
ntaExpression = Expression()
"to" t = <IDENTIFIER> "." { targetName = t.image; } t = AttributeName() { targetAttributeName = t.image; } "(" ")"
| [ LOOKAHEAD("each") "each" { iterableValue = true; } ]
value = Expression() value = Expression()
[ "when" condition = Expression() ] [ "when" condition = Expression() ]
"to" t = <IDENTIFIER> "." { targetName = t.image; } t = AttributeName() { targetAttributeName = t.image; } "(" ")" "to" t = <IDENTIFIER> "." { targetName = t.image; } t = AttributeName() { targetAttributeName = t.image; } "(" ")"
...@@ -1411,6 +1415,17 @@ void CollectionContribution(): ...@@ -1411,6 +1415,17 @@ void CollectionContribution():
jjtThis, jjtThis,
enclosingAspect, enclosingAspect,
annotations); annotations);
} else if (ntaExpression != null) {
root.addCustomSurveyExpression(targetName,
targetAttributeName,
attributeType,
Unparser.unparse(ntaExpression),
fileName,
first.beginLine,
last.endLine,
jjtThis,
enclosingAspect,
annotations);
} else { } else {
org.jastadd.ast.AST.CollEq equ = root.addCollEq(targetName, org.jastadd.ast.AST.CollEq equ = root.addCollEq(targetName,
targetAttributeName, targetAttributeName,
...@@ -1424,7 +1439,7 @@ void CollectionContribution(): ...@@ -1424,7 +1439,7 @@ void CollectionContribution():
jjtThis, jjtThis,
enclosingAspect, enclosingAspect,
annotations); annotations);
// TODO(joqvist): make equ non-null. // TODO(joqvist): make the returned equ non-null.
if (equ != null) { if (equ != null) {
equ.setValue(Unparser.unparse(value)); equ.setValue(Unparser.unparse(value));
if (condition != null) { if (condition != null) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment