Feature #1745
Feature #9635: TRPL 2.0
review, decide upon and document the 1.0 features which will be retained in 2.0
90%
Related issues
History
#1 Updated by Greg Shah over 13 years ago
- Target version set to Code Improvements
#2 Updated by Greg Shah over 9 years ago
- Target version changed from Code Improvements to TRPL 2.0
#3 Updated by Greg Shah over 9 years ago
- Estimated time changed from 24.00 to 40.00
#4 Updated by Greg Shah over 1 year ago
- Parent task set to #9635
#5 Updated by Greg Shah over 1 year ago
- Assignee set to Octavian Adrian Gavril
#6 Updated by Greg Shah over 1 year ago
Our existing documentation is here:
- Writing TRPL Rule-Sets - This defines the language at the level of statements, control flow and program structure. All of this is defined in XML format and is read by the
ConfigLoaderclass. Overall these parts of TRPL are implemented in thecom.goldencode.p2j.pattern.*package, see thePatternEnginefor the main "runner" of a TRPL ruleset. - Writing TRPL Expressions - This defines the expressions executed (as part of control flow or as a standalone rule/action) to actually do something. We compile these expressions using the
com.goldencode.expr.Compilerwhich uses theexpression.ggrammar (see theexpression()rule) to parse each expression.
Please review the documentation and code in detail. Make sure every TRPL v1 feature is documented somewhere in that documentation so that we have a complete list.
After that, we want to instrument the ConfigLoader and expression Compiler to track the usage of each feature. We can process all of the TRPL rules we have to then see what features are critical and what features can possibly be dropped.
#7 Updated by Octavian Adrian Gavril over 1 year ago
I reviewed ConfigLoader.java along with Writing_TRPL_Rule-Sets and these are some features that I found undocumented:
| ATTRIBUTES | CONSTANT VALUES | FUNCTIONALITIES |
|---|---|---|
execute-condition |
view |
parameter() doesn't extract init attribute |
drop-condition |
tree(no usage) |
ruleSet(): depth is used but not documented |
depth |
ruleSet(): execute-condition is used but not documented |
|
optional(ATTR_OPTIONAL/ATTR_OPT) |
ruleSet(): drop-condition is used but not documented |
|
namespace |
ruleSet(): optional is used but not documented |
|
mode(no usages) |
worker(): namespace is used but not documented |
Continue the same with Compiler and Writing_TRPL_Expressions.
#8 Updated by Octavian Adrian Gavril over 1 year ago
- Status changed from New to WIP
#9 Updated by Octavian Adrian Gavril over 1 year ago
I've reviewed Writing_TRPL_Expressions along with the associated code and it seems fully documented to me. I'm moving on to find a way to track the usage of each TRPL feature.
#10 Updated by Octavian Adrian Gavril over 1 year ago
Greg, where is PatternEngine.main called in order to run the entire TRPL rule-set? I saw some targets in build_db.xml but I don't think this is related as it ran for import.db.pg.
#11 Updated by Greg Shah over 1 year ago
Look for any location that instantiates new PatternEngine(). For example, in TransformDriver.processTrees().
#12 Updated by Greg Shah over 1 year ago
Octavian Adrian Gavril wrote:
I've reviewed Writing_TRPL_Expressions along with the associated code and it seems fully documented to me. I'm moving on to find a way to track the usage of each TRPL feature.
I'm worried that these Expression Features are not documented in detail. We mention that they are available but we provide no comprehensive explanation. Worse: the features are hidden deep in the compiler because they are implemented directly in the generated bytecode. Please take a look at these features (auto-boxing, automatic type conversion, automatic null checking and property notatation).
#13 Updated by Octavian Adrian Gavril over 1 year ago
Greg Shah wrote:
I'm worried that these Expression Features are not documented in detail. We mention that they are available but we provide no comprehensive explanation. Worse: the features are hidden deep in the compiler because they are implemented directly in the generated bytecode. Please take a look at these features (auto-boxing, automatic type conversion, automatic null checking and property notatation).
I've updated the description of the first two features from Expression Features. Should I include more details about the used methods? (e.g. Compiler.convertToRequiredType and how the bytecode is generated using those helper classes)
Greg, please let me know if I should use the same structure for the others or if improvements are needed.
#14 Updated by Octavian Adrian Gavril over 1 year ago
I added some documentation for Property Notation feature. Still looking for the Automatic Null Checking implementation to expand its documentation.
#15 Updated by Greg Shah over 1 year ago
I've updated the description of the first two features from Expression Features.
The changes are really good.
Should I include more details about the used methods? (e.g.
Compiler.convertToRequiredTypeand how the bytecode is generated using those helper classes)
More details are always useful, especially when we are going to rework the language to reimplement these features.
Greg, please let me know if I should use the same structure for the others or if improvements are needed.
Your approach is really good.
#16 Updated by Greg Shah over 1 year ago
Still looking for the Automatic Null Checking implementation to expand its documentation.
Eric: Can you please point us to the proper code?
#17 Updated by Octavian Adrian Gavril over 1 year ago
Eric, is Automatic Null Checking related to code sections similar to this?
// Create a bogus AST which represents the destination of a jump // in the case where the object reference under test is determined // to be non-null. ExtraAst notNullDest = new ExtraAst(); notNullDest.setType(NOT_NULL); notNullDest.setText("null check dest"); notNullDest.setExtra(finishUnit);
#18 Updated by Greg Shah over 1 year ago
Question from Octavian:
Should I configure ConfigLoader and Compiler to track each .rules file/.xml file/rule-set/function? Is there something I missed?
We might need that information (eventually) but for now I am more worried about getting a count of how many times each language feature is used. It seems to me that some features are parsed via the ConfigLoader and some parsed by the expression.g. We can count many features by instrumenting these pieces of code and then loading all the rules. There are also features that can only be seen by the compiler because they are implemented implicitly during compilation, so it seems that some instrumentation there could also be needed to get a full count.
The objective is to see if there are features of the language that are not really being used. Dropping those features would make it easier to implement TRPL v2.
#19 Updated by Octavian Adrian Gavril over 1 year ago
Is it OK if I start with the items mentioned in the table in Writing TRPL Rule-Sets, as these are methods implemented in ConfigLoader.java. Then I continue with features mentioned in Features section. After that, we'll see what else can be included.
#20 Updated by Greg Shah over 1 year ago
Yes, that works.
#21 Updated by Eric Faulhaber over 1 year ago
Octavian Adrian Gavril wrote:
Eric, is Automatic Null Checking related to code sections similar to this?
[...]
Wow, this is some of the oldest code in FWD. I wrote that almost 20 years ago.
But yes, this implements the behavior that a boolean (sub-)expression which evaluates to null is treated as evaluating to false, so we can avoid NPEs being thrown from within TRPL expressions. One has to be aware of this behavior when writing those TRPL expressions.
If we want to get rid of this, the treatment of (branches of) logical expressions evaluating to null will need to be handled more explicitly somehow.
#22 Updated by Eric Faulhaber over 1 year ago
Greg Shah wrote:
Still looking for the Automatic Null Checking implementation to expand its documentation.
Eric: Can you please point us to the proper code?
I don't recall that well from so long ago, but I think the implementation is mostly in the Compiler.convertToRequiredType method (which Octavian already found). Look also at the Compiler.assembleNullTest method, though I think that may only be used for explicit null tests (not the implicit auto null-check).
It may be elsewhere as well. Review places where the IS_NULL and NOT_NULL constants are used (though these may be used for other purposes as well, which are not auto null-check related).
#23 Updated by Octavian Adrian Gavril over 1 year ago
Updated the Expression Features documentation. I added an introduction to the classes used as tools to implement these features. Then I detailed each feature and described what the core implementation looks like. I have also included code sections for a better understanding of the behavior of the features.
#24 Updated by Octavian Adrian Gavril over 1 year ago
Please, let me know if improvements are needed.
#25 Updated by Octavian Adrian Gavril over 1 year ago
I committed the initial implementation of TRPL feature tracking system into task branch 1745a/15792. I added a class responsible for logging, another for handling the results in a map, and another class for deciding which features are critical or not.
I converted this file start.p:
message "Hello world!".
The csv output file looks like this:
| Feature | Number of usages |
|---|---|
| <parameter> | 69148 |
| <rule> | 263591 |
| <walk-rules> | 258 |
| <cfg> | 28 |
| <worker> | 1704 |
| <variable> | 77889 |
| <action> | 195980 |
| <post-rules> | 110 |
| <ast-spec> | 0 |
| <return> | 49110 |
| <continue> | 203 |
| <rule-set> | 853 |
| <expression> | 5607 |
| <ascent-rules> | 132 |
| <init-rules> | 184 |
| <while> | 8593 |
| <include> | 348 |
| <next-child-rules> | 9 |
| <descent-rules> | 50 |
| <break> | 1287 |
| <func-library> | 439 |
| <function> | 65815 |
| Observation: Usage statistics: {<parameter>=69148, <rule>=263591, <walk-rules>=258, <cfg>=28, <worker>=1704, <variable>=77889, <action>=195980, <post-rules>=110, <ast-spec>=0, <return>=49110, <continue>=203, <rule-set>=853, <expression>=5607, <ascent-rules>=132, <init-rules>=184, <while>=8593, <include>=348, <next-child-rules>=9, <descent-rules>=50, <break>=1287, <func-library>=439, <function>=65815} | |
| Observation: Critical features: [<parameter>, <rule>, <walk-rules>, <cfg>, <worker>, <variable>, <action>, <post-rules>, <return>, <continue>, <rule-set>, <expression>, <ascent-rules>, <init-rules>, <while>, <include>, <descent-rules>, <break>, <func-library>, <function>] | |
| Observation: Features that can be removed: [<ast-spec>, <next-child-rules>] |
Not sure if these results should differ from the converted project. Basically, I don't know if the conversion goes through all the rules regardless of the project.
Please take a look to see if I can go ahead with this.
#26 Updated by Greg Shah over 1 year ago
Updated the Expression Features documentation. I added an introduction to the classes used as tools to implement these features. Then I detailed each feature and described what the core implementation looks like. I have also included code sections for a better understanding of the behavior of the features.
This is really good.
#27 Updated by Greg Shah over 1 year ago
I committed the initial implementation of TRPL feature tracking system
These are interesting results. Some feedback:
1. We can't just run conversion, that will only load rules files that are used in that pipeline. This is most of the rule files, but not all. It would be missing things like the rules used for reports, database import, AST search, customer-specific rules and so forth.
Instead of relying upon conversion, we should dynamically lookup all .xml and .rules files in the pattern path and load them using your instrumented loader.
2. Some of the numbers are quite accurate while others are not obvious. For example, there aren't 8593 <while> elements in all our rules. The actual number is closer to 550. The number of <function instances is similarly incorrect (there should be around 1000 of them and instead nearly 70000 are reported). I suspect this comes from referencing some rules (e.g. common-progress.rules) from many places. This suggests 2 things:
- Once we've loaded a given file, don't add to our numbers when the file is processed again.
- Do we have an optimization opportunity here? Why would we load and compile the same rules file more than once? I think we should be able to reuse the same loaded code in many places, though we will have to ensure that we fix usage of "global data" such that we don't rely upon any variable references outside of the current file-level scope. I wonder what performance improvement we can get by this.
Observation: Features that can be removed: [<ast-spec>, <next-child-rules>]
ast-spec is a deprecated feature and definitely will be dropped.
next-child-rules is actually needed. 9 instances just means that only 9 rulesets use it, but those rules are quite helpful.
#28 Updated by Octavian Adrian Gavril over 1 year ago
- File tracker_20250324_154648.log
added - File trpl_feature_errors.txt
added
I added another class (TRPLFeatureTracker) to search for all .xml files and process them with the processTrees method. This way all .xml files from p2j/rules are loaded. Therefore, we will have 58 <cfg> tags because 58 .xml files were found. Now, the results are increased compared to #1745-25. This happens because all files are involved, but I need to check if .rules are loaded more than once. (they can be called from two different .xml files).
I also added an error trace while processing the .xml files and logged the errors to trpl_feature_errors.txt. This way I discovered files like dbref/collect_refs.xml which uses "dbref.xml". This file doesn't exist.
I continue implementing multiple load checking for .rules files.
I made these changes in the task branch 1745a/15793.
The new results look like this:
| Feature | Number of usages |
|---|---|
| <parameter> | 77036 |
| <rule> | 293021 |
| <walk-rules> | 270 |
| <cfg> | 58 |
| <worker> | 1917 |
| <variable> | 86545 |
| <action> | 217423 |
| <post-rules> | 130 |
| <ast-spec> | 0 |
| <return> | 54805 |
| <continue> | 221 |
| <rule-set> | 903 |
| <expression> | 6222 |
| <ascent-rules> | 134 |
| <init-rules> | 215 |
| <while> | 9531 |
| <include> | 393 |
| <next-child-rules> | 7 |
| <descent-rules> | 43 |
| <break> | 1425 |
| <func-library> | 491 |
| <function> | 73335 |
| Observation: Usage statistics: {<parameter>=77036, <rule>=293021, <walk-rules>=270, <cfg>=58, <worker>=1917, <variable>=86545, <action>=217423, <post-rules>=130, <ast-spec>=0, <return>=54805, <continue>=221, <rule-set>=903, <expression>=6222, <ascent-rules>=134, <init-rules>=215, <while>=9531, <include>=393, <next-child-rules>=7, <descent-rules>=43, <break>=1425, <func-library>=491, <function>=73335} | |
| Observation: Critical features: [<parameter>, <rule>, <walk-rules>, <cfg>, <worker>, <variable>, <action>, <post-rules>, <return>, <continue>, <rule-set>, <expression>, <ascent-rules>, <init-rules>, <while>, <include>, <descent-rules>, <break>, <func-library>, <function>] | |
| Observation: Features that can be removed: [<ast-spec>, <next-child-rules>] |
I attached the tracker log and trpl_feature_errors.txt.
#29 Updated by Octavian Adrian Gavril over 1 year ago
I've added some changes to avoid multiple uploads of the same .rules file. The numbers seem accurate, so I hope I've found the right places for this check.
| Feature | Number of usages |
|---|---|
| <parameter> | 1318 |
| <rule> | 17717 |
| <walk-rules> | 257 |
| <cfg> | 58 |
| <worker> | 631 |
| <variable> | 5476 |
| <action> | 21163 |
| <post-rules> | 124 |
| <ast-spec> | 0 |
| <return> | 674 |
| <continue> | 17 |
| <rule-set> | 508 |
| <expression> | 209 |
| <ascent-rules> | 126 |
| <init-rules> | 207 |
| <while> | 481 |
| <include> | 196 |
| <next-child-rules> | 7 |
| <descent-rules> | 39 |
| <break> | 50 |
| <func-library> | 102 |
| <function> | 990 |
| Observation: Usage statistics: {<parameter>=1318, <rule>=17717, <walk-rules>=257, <cfg>=58, <worker>=631, <variable>=5476, <action>=21163, <post-rules>=124, <ast-spec>=0, <return>=674, <continue>=17, <rule-set>=508, <expression>=209, <ascent-rules>=126, <init-rules>=207, <while>=481, <include>=196, <next-child-rules>=7, <descent-rules>=39, <break>=50, <func-library>=102, <function>=990} | |
| Observation: Critical features: [<parameter>, <rule>, <walk-rules>, <cfg>, <worker>, <variable>, <action>, <post-rules>, <return>, <continue>, <rule-set>, <expression>, <ascent-rules>, <init-rules>, <while>, <include>, <descent-rules>, <break>, <func-library>, <function>] | |
| Observation: Features that can be removed: [<ast-spec>, <next-child-rules>] |
I committed the changes in revision 15794.
#30 Updated by Octavian Adrian Gavril over 1 year ago
- Related to Bug #9835: The same rules files are loaded and compiled multiple times added
#31 Updated by Octavian Adrian Gavril over 1 year ago
Greg, as you suggested in the last call, I created a new task about that performance gap described in #1745-27.
#32 Updated by Octavian Adrian Gavril over 1 year ago
- % Done changed from 0 to 70
I've added the elements mentioned in Features to be tracked. I've also included customer-specific rules, and the new results look like this:
| Feature | Number of usages |
|---|---|
| <parameter> | 1328 |
| <walk-rules> | 260 |
| <variable> | 5601 |
| <action> | 21915 |
| <post-rules> | 124 |
| PROPERTY NOTATION | 3103 |
| <continue> | 17 |
| <rule-set> | 515 |
| <ascent-rules> | 128 |
| <while> | 485 |
| <next-child-rules> | 7 |
| <descent-rules> | 39 |
| <rule> | 18041 |
| <cfg> | 64 |
| <worker> | 653 |
| AUTO-BOXING | 4904 |
| <ast-spec> | 5 |
| <return> | 680 |
| AUTO TYPE CONVERSION | 189 |
| AUTOMATIC NULL CHECKING | 49 |
| <expression> | 217 |
| <init-rules> | 211 |
| <include> | 204 |
| <break> | 50 |
| <func-library> | 104 |
| <function> | 1000 |
I've committed these changes to 1745a/15795.
Greg, what do you think about the numbers above? Also, what should I continue tracking with?
#33 Updated by Octavian Adrian Gavril over 1 year ago
Octavian Adrian Gavril wrote:
I reviewed
ConfigLoader.javaalong with Writing_TRPL_Rule-Sets and these are some features that I found undocumented:
ATTRIBUTES CONSTANT VALUES FUNCTIONALITIES execute-conditionviewparameter()doesn't extractinitattributedrop-conditiontree(no usage)ruleSet():depthis used but not documenteddepthruleSet():execute-conditionis used but not documentedoptional(ATTR_OPTIONAL/ATTR_OPT)ruleSet():drop-conditionis used but not documentednamespaceruleSet():optionalis used but not documentedmode(no usages)worker():namespaceis used but not documentedContinue the same with
Compilerand Writing_TRPL_Expressions.
Added properly documentation for parameters of rule-set/worker from Writing TRPL Rule-Sets.
#34 Updated by Greg Shah over 1 year ago
Greg, what do you think about the numbers above? Also, what should I continue tracking with?
Please instrument expression.g and add those numbers to the results. This will tell us which expression features are used and how much.
#35 Updated by Octavian Adrian Gavril over 1 year ago
Greg Shah wrote:
Greg, what do you think about the numbers above? Also, what should I continue tracking with?
Please instrument
expression.gand add those numbers to the results. This will tell us which expression features are used and how much.
Sure!
#36 Updated by Octavian Adrian Gavril over 1 year ago
- Status changed from WIP to Review
- % Done changed from 70 to 100
- reviewer Greg Shah added
Instrumented expression.g, both rules and tokens, into 1745a/15796. Now, the results look like this:
| Feature | Number of usages |
|---|---|
| <action> | 21915 |
| <ascent-rules> | 128 |
| <ast-spec> | 5 |
| <break> | 50 |
| <cfg> | 64 |
| <continue> | 17 |
| <descent-rules> | 39 |
| <expression> | 217 |
| <func-library> | 104 |
| <function> | 1000 |
| <include> | 204 |
| <init-rules> | 211 |
| <next-child-rules> | 7 |
| <parameter> | 1328 |
| <post-rules> | 124 |
| <return> | 680 |
| <rule-set> | 515 |
| <rule> | 18041 |
| <variable> | 5601 |
| <walk-rules> | 260 |
| <while> | 485 |
| <worker> | 653 |
| AUTO TYPE CONVERSION | 189 |
| AUTO-BOXING | 4904 |
| AUTOMATIC NULL CHECKING | 49 |
| PROPERTY NOTATION | 3103 |
| RULE: bit_and_expr | 12600 |
| RULE: bit_or_expr | 10233 |
| RULE: bit_xor_expr | 12600 |
| RULE: cast | 207 |
| RULE: compare_expr | 12640 |
| RULE: equality_expr | 12600 |
| RULE: expr | 10196 |
| RULE: expression | 4268 |
| RULE: literal | 9353 |
| RULE: log_and_expr | 10215 |
| RULE: method | 6266 |
| RULE: primary_expr | 12828 |
| RULE: prod_expr | 12651 |
| RULE: shift_expr | 12651 |
| RULE: sum_expr | 12651 |
| RULE: un_expr | 12651 |
| Token: ASSIGN | 176 |
| Token: BIT_OR | 2366 |
| Token: COMMA | 2794 |
| Token: DIGIT | 556 |
| Token: DSTRING | 559 |
| Token: EQUALS | 27 |
| Token: GT | 0 |
| Token: GTE | 9 |
| Token: HASH | 207 |
| Token: LETTER | 120659 |
| Token: LPARENS | 3379 |
| Token: MINUS | 6 |
| Token: NOT | 12 |
| Token: NOT_EQ | 11 |
| Token: NUM_LITERAL | 10522 |
| Token: RPARENS | 3380 |
| Token: SSTRING | 806 |
| Token: STRING | 1366 |
| Token: SYMBOL | 21371 |
| Token: SYM_CHAR | 13920 |
| Token: VALID_SYM_CHAR | 113335 |
| Token: WS | 9304 |
| Observation: | Usage statistics: {<parameter>=1328, RULE: expr=10196, Token: ASSIGN=176, <walk-rules>=260, <action>=21915, PROPERTY NOTATION=3103, Token: LPARENS=3379, RULE: bit_and_expr=12600, Token: WS=9304, <continue>=17, RULE: log_and_expr=10215, RULE: bit_or_expr=10233, <while>=485, <next-child-rules>=7, Token: EQUALS=27, Token: RPARENS=3380, RULE: equality_expr=12600, Token: STRING=1366, Token: DIGIT=556, RULE: method=6266, AUTO TYPE CONVERSION=189, RULE: prod_expr=12651, AUTOMATIC NULL CHECKING=49, RULE: expression=4268, Token: NUM_LITERAL=10522, Token: GT=0, <include>=204, Token: NOT=12, <func-library>=104, Token: LETTER=120659, <variable>=5601, <post-rules>=124, RULE: compare_expr=12640, <rule-set>=515, Token: HASH=207, <ascent-rules>=128, Token: NOT_EQ=11, Token: COMMA=2794, Token: SSTRING=806, RULE: un_expr=12651, <descent-rules>=39, Token: BIT_OR=2366, Token: DSTRING=559, RULE: sum_expr=12651, Token: SYMBOL=21371, RULE: shift_expr=12651, <rule>=18041, RULE: literal=9353, Token: SYM_CHAR=13920, <cfg>=64, <worker>=653, AUTO-BOXING=4904, RULE: bit_xor_expr=12600, <ast-spec>=5, <return>=680, RULE: cast=207, <expression>=217, <init-rules>=211, Token: VALID_SYM_CHAR=113335, RULE: primary_expr=12828, Token: GTE=9, Token: MINUS=6, <break>=50, <function>=1000} |
| Observation: | Critical features: [<parameter>, RULE: expr, Token: ASSIGN, <walk-rules>, <action>, PROPERTY NOTATION, Token: LPARENS, RULE: bit_and_expr, Token: WS, <continue>, RULE: log_and_expr, RULE: bit_or_expr, <while>, Token: EQUALS, Token: RPARENS, RULE: equality_expr, Token: STRING, Token: DIGIT, RULE: method, AUTO TYPE CONVERSION, RULE: prod_expr, AUTOMATIC NULL CHECKING, RULE: expression, Token: NUM_LITERAL, <include>, Token: NOT, <func-library>, Token: LETTER, <variable>, <post-rules>, RULE: compare_expr, <rule-set>, Token: HASH, <ascent-rules>, Token: NOT_EQ, Token: COMMA, Token: SSTRING, RULE: un_expr, <descent-rules>, Token: BIT_OR, Token: DSTRING, RULE: sum_expr, Token: SYMBOL, RULE: shift_expr, <rule>, RULE: literal, Token: SYM_CHAR, <cfg>, <worker>, AUTO-BOXING, RULE: bit_xor_expr, <return>, RULE: cast, <expression>, <init-rules>, Token: VALID_SYM_CHAR, RULE: primary_expr, <break>, <function>] |
| Observation: | Features that can be removed: [<next-child-rules>, Token: GT, <ast-spec>, Token: GTE, Token: MINUS] |
#37 Updated by Greg Shah over 1 year ago
Please try to confirm all of your numbers using other matching techniques (even something like grep). Many of the numbers don't seem correct. There are thousands of token NOT_EQ which is the text != but the numbers above say there are 11. There are thousands of CAST nodes (not 207) and even the next-child should be 8 not 7.
#38 Updated by Octavian Adrian Gavril over 1 year ago
- % Done changed from 100 to 90
- Status changed from Review to WIP
#39 Updated by Octavian Adrian Gavril over 1 year ago
Greg Shah wrote:
Please try to confirm all of your numbers using other matching techniques (even something like grep). Many of the numbers don't seem correct. There are thousands of token
NOT_EQwhich is the text!=but the numbers above say there are 11. There are thousands of CAST nodes (not 207) and even thenext-childshould be 8 not 7.
I think there might be some .rules files that are not referenced by any .xml files. dmo_common.rules, for example, has many uses of !=, but this file is not referenced. I'm working to fix this.
#40 Updated by Octavian Adrian Gavril over 1 year ago
After some investigation, I believe the only way the TRPL expression can be compiled is by processing it together with a specific AST.
See PatternEngine.run(String profile):
// Run global init rules.
applyGlobal(RULE_INIT);
Configuration config = Configuration.getInstance();
// Process each stored AST or walk call graph, depending on the mode of operation.
Iterator<String> iter = targetPaths.iterator();
while (iter.hasNext())
{
String path = iter.next();
config.withFileProfile(path);
if (graph != null)
{
Aast ast = AstManager.get().loadTree(path);
long id = ast.getId();
Vertex node = nodeFilter.acceptNode(id);
if (node != null)
{
walkGraph(node);
}
}
else
{
processAst(path);
}
}Those countered occurrences of
NOT_EQ only come from the applyGlobal(RULE_INIT); call. If I track the usages during a conversion, then the results are totally different because processAst() is called and Compiler is involved.
Greg, what do you think?
#41 Updated by Octavian Adrian Gavril over 1 year ago
ast, but without success. I used AstSymbolResolver.getResolver() in these cases:
- In
ConfigLoader.rule()I wanted to compile only the rule condition:// at this point, lastRule is the rule that was just created, now we // set whether this new rule is a WHILE or an IF/ELSE lastRule.setLoop(loop); new Expression(AstSymbolResolver.getResolver(), expr).execute(); boolean oldInLoop = inLoop;
Here I had some problems with using namespaces because they were not yet compiled.
- In
ConfigLoader.loadImpl()I wanted to apply all the rules fromlastRuleContainerafter the load is finished:if (Objects.equals(suffix, SUFFIX_RULES)) { lastRuleContainer.apply(AstSymbolResolver.getResolver(), RuleContainer.RULE_WALK); loadedRules.add(name); }
Here I had some problems withrule type. InRuleContainer.apply(), each rule is applied with the same type. Therefore, compiling with only one rule type was not a good idea:RuleListElement next; for (int i = 0; i < size; i++) { next = rules.get(i); next.apply(resolver, type); }
In both cases, I get many NEP as there are some usage of CommonAstSupport.getSource() and CommonAstSupport.getCopy() are used during compiling.
#42 Updated by Octavian Adrian Gavril over 1 year ago
I'm starting a new approach similar to Expression.main() to compile expression rules.
#43 Updated by Greg Shah over 1 year ago
I think we will need a custom driver that loads everything (all rule set files) and forces all content to parse and all expressions to compile.
#44 Updated by Octavian Adrian Gavril over 1 year ago
- Status changed from WIP to Review
- File trpl_feature_errors.txt
added - % Done changed from 90 to 100
Greg Shah wrote:
I think we will need a custom driver that loads everything (all rule set files) and forces all content to parse and all expressions to compile.
I created TRPLFeatureTracker to be the driver that loads everything using processTrees. I added trackerOn to indicate whether tracker mode is enabled or not. Using this flag, the ConfigLoader, Compiler, SymbolResolver, Verifier classes and expressiong.g are instrumented to track the usages of each TRPL tag, expression feature and expression rule. At the same time, TestResolver is used to simulate a compilation for each expression rule (see SymbolResolver.TestResolver.resolveFunction). This is implemented in ConfigLoader.rule. The Verifier class mocks the type of the operands when the environment is in tracker mode. The new results look like this:
| Feature | Number of usages | Feature | Number of usages |
|---|---|---|---|
| <action> | 21635 | <rule-set> | 592 |
| <ascent-rules> | 127 | <rule> | 17964 |
| <ast-spec> | 5 | <variable> | 5576 |
| <break> | 50 | <walk-rules> | 259 |
| <cfg> | 65 | <while> | 480 |
| <continue> | 17 | <worker> | 656 |
| <descent-rules> | 39 | AUTO TYPE CONVERSION | 236 |
| <expression> | 213 | AUTO-BOXING | 4898 |
| <func-library> | 104 | AUTOMATIC NULL CHECKING | 5 |
| <function> | 1004 | PROPERTY NOTATION | 73341 |
| <include> | 203 | RULE: bit_and_expr | 64673 |
| <init-rules> | 211 | RULE: bit_or_expr | 59907 |
| <next-child-rules> | 7 | RULE: bit_xor_expr | 64673 |
| <parameter> | 1333 | RULE: cast | 758 |
| <post-rules> | 122 | RULE: compare_expr | 76120 |
| <return> | 685 | RULE: equality_expr | 64680 |
| RULE: expr | 50544 | RULE: expression | 18789 |
| RULE: literal | 23258 | RULE: log_and_expr | 54799 |
| RULE: method | 89043 | RULE: primary_expr | 78113 |
| RULE: prod_expr | 76602 | RULE: shift_expr | 76563 |
| RULE: sum_expr | 76563 | RULE: un_expr | 76612 |
| Token: AND | 0 | Token: ASSIGN | 1501 |
| Token: BIT_AND | 7 | Token: BIT_COMP | 0 |
| Token: BIT_OR | 4766 | Token: BIT_XOR | 0 |
| Token: COMMA | 14654 | Token: DIGIT | 3508 |
| Token: DIVIDE | 8 | Token: DSTRING | 8435 |
| Token: EQUALS | 9419 | Token: GT | 270 |
| Token: GTE | 59 | Token: HASH | 758 |
| Token: HEXDIGIT | 0 | Token: LETTER | 666247 |
| Token: LPARENS | 18431 | Token: LSHIFT | 0 |
| Token: LT | 102 | Token: LTE | 12 |
| Token: MINUS | 358 | Token: MODULO | 2 |
| Token: MULTIPLY | 0 | Token: NOT | 1145 |
| Token: NOT_EQ | 2021 | Token: NUM_LITERAL | 46166 |
| Token: OR | 41 | Token: PLUS | 23 |
| Token: POSPARM | 0 | Token: RPARENS | 18468 |
| Token: RSHIFT | 0 | Token: SSTRING | 1486 |
| Token: STRING | 9921 | Token: SYMBOL | 118015 |
| Token: SYM_CHAR | 42791 | Token: VALID_SYM_CHAR | 592114 |
| Token: WS | 75764 | Token: ZRSHIFT | 0 |
Both load rule errors and expression compilation errors are logged in trpl_feature_errors.txt. In the current version, there are no expression compilation errors (thanks to mocking). The only errors detected are attached in trpl_feature_errors.txt. Please let me know if these are expected (some of them are related to some database-related schema or data structure issues) or if we should fix them ourselves. Perhaps these errors influence the current results.
I've committed these changes into task branch 1745/15798.
#45 Updated by Octavian Adrian Gavril over 1 year ago
#46 Updated by Greg Shah over 1 year ago
I've done some quick checking of the results. Most of the numbers look pretty reasonable, even the ones that are very low.
For example, the bitwise operator counts look accurate (or at least close) as do the LTE, DIVIDE (maybe should be 9 not 8?).
On the other hand, CAST looks wrong (there should be around 2100) and LT seems wrong.
In addition to this, the matching in the expression.g rules is a problem because the counting is not done only for matches. It is unconditionally executed on exit from the rule. Since the expression precedence processing in ANTLR v2 requires nesting of the precedence levels in sepaarate rules, this leads to some rules getting very large counts which have no relation to the actual number of matches.
We are also missing counts for the keyword matching that happens here:
keywords.put( "and", Integer.valueOf(AND) );
keywords.put( "false", Integer.valueOf(BOOL_FALSE) );
keywords.put( "not", Integer.valueOf(NOT) );
keywords.put( "null", Integer.valueOf(NULL) );
keywords.put( "or", Integer.valueOf(OR) );
keywords.put( "true", Integer.valueOf(BOOL_TRUE) );
#47 Updated by Octavian Adrian Gavril over 1 year ago
- % Done changed from 100 to 90
- Status changed from Review to WIP
Greg Shah wrote:
On the other hand,
CASTlooks wrong (there should be around 2100) andLTseems wrong.
I continue investigating in this regard.
In addition to this, the matching in the
expression.grules is a problem because the counting is not done only for matches. It is unconditionally executed on exit from the rule. Since the expression precedence processing in ANTLR v2 requires nesting of the precedence levels in sepaarate rules, this leads to some rules getting very large counts which have no relation to the actual number of matches.
I assumed that if logging occurs within the try block and no exception is thrown by match() up to that point, we could treat it as a valid match. I'm still exploring whether there's a more reliable approach.
We are also missing counts for the keyword matching that happens here:
[...]
I've committed some changes to fix this into 1745a/15799.
#48 Updated by Greg Shah over 1 year ago
I assumed that if logging occurs within the
tryblock and no exception is thrown bymatch()up to that point, we could treat it as a valid match. I'm still exploring whether there's a more reliable approach.
You can still put the counter processing in the exit action, but you should only increment the count if the match has been made. The way to check this is to add a conditon like this:
un_expr
:
{
String cls = null;
}
(
m:MINUS^ { #m.setType( UN_MINUS ); }
| BIT_COMP^
| NOT^
| h:HASH^ cls=cast! { #h.setType(CAST); #h.setText(cls); }
| // empty alternative
)
primary_expr[false]
{
int type = (## == null) ? -1 : ##.getType();
// HASH is counted in the cast rule
if (TRPLFeatureTracker.trackerOn && (type == MINUS || type == BIT_COMP || type == NOT))
{
FeatureLogger.logFeatureUsage("RULE: un_expr");
}
}
;
This takes advantage of the fact that the root node for the returned AST can be referenced via ##.
#49 Updated by Greg Shah over 1 year ago
Also, we don't need to track protected lexer rules since they don't actually generate tokens used by the parser. I'm not even sure we want to track the token generation itself, but instead would rather count things at the parser level.
#50 Updated by Octavian Adrian Gavril over 1 year ago
Greg Shah wrote:
Also, we don't need to track
protectedlexer rules since they don't actually generate tokens used by the parser. I'm not even sure we want to track the token generation itself, but instead would rather count things at the parser level.
So, should I remove the logging of token rules?
#51 Updated by Greg Shah over 1 year ago
Octavian Adrian Gavril wrote:
Greg Shah wrote:
Also, we don't need to track
protectedlexer rules since they don't actually generate tokens used by the parser. I'm not even sure we want to track the token generation itself, but instead would rather count things at the parser level.So, should I remove the logging of token rules?
Yes, as long as you have logging for the "feature" at the parser level. For example, instead of the DIVIDE or MULTIPY tokens we should count the matches of those operators in the parser.
#52 Updated by Greg Shah over 1 year ago
The idea here is that the language features match the parser structure, not the individual tokens.
#53 Updated by Octavian Adrian Gavril over 1 year ago
- Added compilation support for
<action>expressions. This improves logging forCASTand other problematic rules. - Changed the caching of compiled expressions by using a more reliable key. (Considering column numbers might also be beneficial.)
I still need to address to this issue:
Greg Shah wrote:
In addition to this, the matching in the
expression.grules is a problem because the counting is not done only for matches. It is unconditionally executed on exit from the rule. Since the expression precedence processing in ANTLR v2 requires nesting of the precedence levels in sepaarate rules, this leads to some rules getting very large counts which have no relation to the actual number of matches.
I did some experiments but I need to continue.
I've also updated some .rules files that weren't compiling correctly due to syntax issues—specifically, rules/annotations/native_api.rules and rules/include/report.rules.
The new results look like this:
| Feature | Number of usages |
|---|---|
| <action> | 21275 |
| <ascent-rules> | 119 |
| <ast-spec> | 5 |
| <break> | 50 |
| <cfg> | 65 |
| <continue> | 23 |
| <descent-rules> | 36 |
| <expression> | 243 |
| <func-library> | 100 |
| <function> | 1019 |
| <include> | 203 |
| <init-rules> | 203 |
| <next-child-rules> | 6 |
| <parameter> | 1372 |
| <post-rules> | 118 |
| <return> | 691 |
| <rule-set> | 549 |
| <rule> | 17760 |
| <variable> | 5573 |
| <walk-rules> | 245 |
| <while> | 479 |
| <worker> | 639 |
| AUTO TYPE CONVERSION | 223 |
| AUTO-BOXING | 4893 |
| AUTOMATIC NULL CHECKING | 5 |
| PROPERTY NOTATION | 157328 |
| Rule: bit_and_expr | 149478 |
| Rule: bit_or_expr | 144641 |
| Rule: bit_xor_expr | 149478 |
| Rule: cast | 2698 |
| Rule: compare_expr | 166959 |
| Rule: equality_expr | 149492 |
| Rule: expr | 131033 |
| Rule: expression | 50751 |
| Rule: literal | 54910 |
| Rule: log_and_expr | 137460 |
| Rule: method | 198009 |
| Rule: primary_expr | 187912 |
| Rule: prod_expr | 168147 |
| Rule: shift_expr | 167651 |
| Rule: sum_expr | 167651 |
| Rule: un_expr | 168170 |
| Token: AND | 14363 |
| Token: ASSIGN | 39489 |
| Token: BIT_AND | 14 |
| Token: BIT_COMP | 0 |
| Token: BIT_OR | 4837 |
| Token: BIT_XOR | 0 |
| Token: BOOL_FALSE | 3177 |
| Token: BOOL_TRUE | 6478 |
| Token: COMMA | 39835 |
| Token: DEC_LITERAL | 0 |
| Token: DIVIDE | 11 |
| Token: EQUALS | 14015 |
| Token: GT | 416 |
| Token: GTE | 111 |
| Token: HASH | 2698 |
| Token: HEX_LITERAL | 41 |
| Token: LPARENS | 46292 |
| Token: LSHIFT | 0 |
| Token: LT | 151 |
| Token: LTE | 14 |
| Token: MINUS | 944 |
| Token: MODULO | 4 |
| Token: MULTIPLY | 8 |
| Token: NOT | 2031 |
| Token: NOT_EQ | 3452 |
| Token: NULL | 12215 |
| Token: NUM_LITERAL | 12895 |
| Token: OR | 12789 |
| Token: PLUS | 364 |
| Token: RPARENS | 46288 |
| Token: RSHIFT | 0 |
| Token: STRING | 31036 |
| Token: SYMBOL | 53580 |
| Token: WS | 0 |
| Token: ZRSHIFT | 0 |
It's clear that there are still some unnecessary logs that need to be excluded—even for CAST. As for WS, its count is 0 because it's not directly referenced by any other rule.
#54 Updated by Greg Shah over 1 year ago
Is AUTOMATIC NULL CHECKING really only used 5 times? That is suspicious.
#55 Updated by Octavian Adrian Gavril about 1 year ago
I've completed some rules testcases covering all the expression/token/tag rules I monitor. These are not loaded in 1745a. Based on these findings, I have added some other changes to the tracker to make the results more accurate. I'm continuing with this approach. The most recent changes are committed into task branch 1745a/15801.
#56 Updated by Octavian Adrian Gavril about 1 year ago
- avoided double logging of keywords from
SYMBOLrule; - turned off the tracking mode for included files to avoid double logging of
function-library,includeandworkertags; - fixed
reports/rpt_nullable_vars.xmlsyntax as this file generated some syntax errors (anactionused insidework-rules); - cleaned up
expression.g.
| Feature | Number of usages |
|---|---|
| <action> | 22590 |
| <ascent-rules> | 136 |
| <ast-spec> | 5 |
| <break> | 62 |
| <cfg> | 66 |
| <continue> | 26 |
| <descent-rules> | 46 |
| <expression> | 216 |
| <func-library> | 119 |
| <function> | 1049 |
| <include> | 219 |
| <init-rules> | 239 |
| <next-child-rules> | 7 |
| <parameter> | 1422 |
| <post-rules> | 138 |
| <return> | 714 |
| <rule-set> | 780 |
| <rule> | 19145 |
| <variable> | 5953 |
| <walk-rules> | 287 |
| <while> | 541 |
| <worker> | 705 |
| AUTO TYPE CONVERSION | 13 |
| AUTO-BOXING | 4919 |
| AUTOMATIC NULL CHECKING | 6 |
| PROPERTY NOTATION | 153160 |
| Rule: bit_and_expr | 6 |
| Rule: bit_or_expr | 4768 |
| Rule: cast | 2735 |
| Rule: compare_expr | 710 |
| Rule: equality_expr | 17012 |
| Rule: expr | 2904 |
| Rule: literal | 52899 |
| Rule: log_and_expr | 6227 |
| Rule: method | 194589 |
| Rule: primary_expr | 3103 |
| Rule: prod_expr | 71 |
| Rule: sum_expr | 508 |
| Rule: un_expr | 5591 |
| Token: AND | 7560 |
| Token: ASSIGN | 17608 |
| Token: BIT_AND | 6 |
| Token: BIT_OR | 4767 |
| Token: BOOL_FALSE | 1275 |
| Token: BOOL_TRUE | 2533 |
| Token: COMMA | 40439 |
| Token: DEC_LITERAL | 3 |
| Token: DIVIDE | 15 |
| Token: EQUALS | 13628 |
| Token: GT | 428 |
| Token: GTE | 87 |
| Token: HASH | 2735 |
| Token: HEX_LITERAL | 20 |
| Token: LPARENS | 47316 |
| Token: LT | 157 |
| Token: LTE | 19 |
| Token: MINUS | 1032 |
| Token: MODULO | 6 |
| Token: MULTIPLY | 35 |
| Token: NOT | 1938 |
| Token: NOT_EQ | 3269 |
| Token: NULL | 5869 |
| Token: NUM_LITERAL | 12476 |
| Token: OR | 6321 |
| Token: PLUS | 343 |
| Token: RPARENS | 47313 |
| Token: STRING | 30717 |
| Token: SYMBOL | 54642 |
- I found some rules that use data types from
org.hibernate.*. These cause some files not to load. - When
CallGraphWorkerthere were some errors related to the failure to open the db connection withJanusGraphFactory.open:
public static JanusGraph open(ReadConfiguration configuration, String backupName) {
ModifiableConfiguration config = new ModifiableConfiguration(GraphDatabaseConfiguration.ROOT_NS, (WriteConfiguration)configuration, Restriction.NONE);
String graphName = config.has(GraphDatabaseConfiguration.GRAPH_NAME, new String[0]) ? (String)config.get(GraphDatabaseConfiguration.GRAPH_NAME, new String[0]) : backupName;
JanusGraphManager jgm = JanusGraphManagerUtility.getInstance();
if (null != graphName) {
Preconditions.checkNotNull(jgm, "Gremlin Server must be configured to use the JanusGraphManager.");
return (JanusGraph)jgm.openGraph(graphName, (gName) -> new StandardJanusGraph((new GraphDatabaseConfigurationBuilder()).build(configuration)));
} else {
if (jgm != null) {
log.warn("You should supply \"graph.graphname\" in your .properties file configuration if you are opening a graph that has not already been opened at server start, i.e. it was defined in your YAML file. This will ensure the graph is tracked by the JanusGraphManager, which will enable autocommit and rollback functionality upon all gremlin script executions. Note that JanusGraphFactory#open(String === shortcut notation) does not support consuming the property \"graph.graphname\" so these graphs should be accessed dynamically by supplying a .properties file here or by using the ConfiguredGraphFactory.");
}
return new StandardJanusGraph((new GraphDatabaseConfigurationBuilder()).build(configuration));
}
}In this case,
graphName was null and graph.graphName was not accessible. To fix this, I ran CallGraphGenerator.main in TRPLFeatureTracker.main and it worked. After that, I removed the CallGraphGenerator.main call, but the tracker system still has a reference to that callgraph. This is the content of the trace log when CallGraphWorker is needed:
[java] Generated unique-instance-id=c0a802c052490-aog1
[java] Configuring index [search]
[java] Initiated fixed thread pool of size 24
[java] Configuring total store cache size: 5028244622
[java] Gremlin script evaluation is disabled
[java] Loaded unidentified ReadMarker start time 2025-04-28T13:58:04.321937Z into org.janusgraph.diskstorage.log.kcvs.KCVSLog$MessagePuller@24f3830c
All of these changes are committed into 1745a/15803.
#57 Updated by Octavian Adrian Gavril about 1 year ago
I believe that generating/using callgraph is necessary to make rules from rules/reports and rules/callgraph load/compile correctly. Since this feature has not been used before, the error log contains new errors about other rule syntax that have not been loaded before.
#58 Updated by Octavian Adrian Gavril about 1 year ago
- Fixed the usage of
CallGraphWorker; - Fixed logging for included files;
- Avoided getting type for
variableandparameterto ignore the usage of deprecated classes; - Cleaned up some
.rules/.xmlfiles which generated syntax errors; - Avoided applying rules from
PatternEngine.runbecause the copy/sourceastisnull.
#59 Updated by Octavian Adrian Gavril about 1 year ago
I made some additional changes that fixed the way func-library children are processed. The main idea was to keep track of elements whether they are included or just loaded and take this into account the next time those elements appear. These changes are committed into 1745a/15805.
The current results are as follows:
| Feature | Number of usages |
|---|---|
| <action> | 22584 |
| <ascent-rules> | 138 |
| <ast-spec> | 5 |
| <break> | 63 |
| <cfg> | 65 |
| <continue> | 26 |
| <descent-rules> | 46 |
| <expression> | 220 |
| <func-library> | 116 |
| <function> | 1044 |
| <include> | 198 |
| <init-rules> | 250 |
| <next-child-rules> | 8 |
| <parameter> | 1420 |
| <post-rules> | 148 |
| <return> | 713 |
| <rule-set> | 569 |
| <rule> | 19197 |
| <variable> | 5977 |
| <walk-rules> | 302 |
| <while> | 545 |
| <worker> | 434 |
| AUTO TYPE CONVERSION | 0 |
| AUTO-BOXING | 0 |
| AUTOMATIC NULL CHECKING | 0 |
| PROPERTY NOTATION | 140501 |
| Rule: bit_and_expr | 15 |
| Rule: bit_or_expr | 2410 |
| Rule: bit_xor_expr | 1 |
| Rule: cast | 2196 |
| Rule: compare_expr | 641 |
| Rule: equality_expr | 16636 |
| Rule: expr | 2580 |
| Rule: expression | 0 |
| Rule: literal | 40425 |
| Rule: log_and_expr | 5332 |
| Rule: method | 174129 |
| Rule: primary_expr | 2592 |
| Rule: prod_expr | 80 |
| Rule: shift_expr | 0 |
| Rule: sum_expr | 425 |
| Rule: un_expr | 4519 |
| Token: AND | 6421 |
| Token: ASSIGN | 16640 |
| Token: BIT_AND | 15 |
| Token: BIT_COMP | 0 |
| Token: BIT_OR | 2409 |
| Token: BIT_XOR | 1 |
| Token: BOOL_FALSE | 1147 |
| Token: BOOL_TRUE | 2512 |
| Token: COMMA | 34067 |
| Token: DEC_LITERAL | 5 |
| Token: DIVIDE | 24 |
| Token: EQUALS | 13680 |
| Token: GT | 376 |
| Token: GTE | 90 |
| Token: HASH | 2196 |
| Token: HEX_LITERAL | 42 |
| Token: LPARENS | 38448 |
| Token: LSHIFT | 0 |
| Token: LT | 151 |
| Token: LTE | 14 |
| Token: MINUS | 802 |
| Token: MODULO | 10 |
| Token: MULTIPLY | 37 |
| Token: NOT | 1615 |
| Token: NOT_EQ | 2853 |
| Token: NULL | 5357 |
| Token: NUM_LITERAL | 4505 |
| Token: OR | 6722 |
| Token: PLUS | 294 |
| Token: RPARENS | 38448 |
| Token: RSHIFT | 0 |
| Token: STRING | 26857 |
| Token: SYMBOL | 38393 |
| Token: WS | 0 |
| Token: ZRSHIFT | 0 |
I think the tracker is in a safe state now, because the results are pretty close to the real numbers. Tracking AUTO TYPE CONVERSION, AUTO-BOXING, AUTOMATIC NULL CHECKING and PROPERTY NOTATION is a bit more complicated than I thought. I used a TestResolver that can only recognize methods (including getters/setters) of type METH_GET_VAR. This way, all expression parsing completed successfully, but expression compilation did not. This happens because all variables or functions are seen as METH_GET_VAR and signature mismatches occur.
I posted some results for these features in the notes above, but all of them were due to the applyGlobal(RULE_INIT) and applyGlobal(RULE_POST) methods in PatternEngine.run. This applies the init/post rules in each .xml file. These method calls were ignored in 15804. PROPERTY NOTATION gets those results because its tracking is implemented in expression.g (independent of Compiler.process).
Greg, seeing these results, do you think this task can be safely paused?