To recap the status detail on this error-- a portion of the statistics parser is broken. We've made a bit of headway, in that the critical piece used to deadlock on initialization, but it still crashes when it is attempted to be used. The statistics parser is composed of three subrules (for both ints and doubles)-- "statistic_1", "statistic_2" and "statistic_3". In all cases they assess something over a range of objects selected by a condition; the condition parser portion is used in other places as well and seems fine. "statistic_1" is only for Count and If. It seems to be working fine, with numerous working <int> examples. "statistic_2" is for statistics on an object property (like "Industry"); it also seems to be working fine, with a couple <double> type empire statistics examples. "statistic_3" is for statistics on a ValueRef, broken into 4 subtypes. The first two we imagine work but haven't really bothered testing because they may not even be sensible for a statistic-- they are for Constants and FreeVariable (like CurrentTurn or MaxAIAggression). The third is for BoundVariables, and empire statistics has a working example (albeit rather contrived) towards the end, assessing MAX Value = LocalCandidate.SystemID; this same example also demonstrates that the basic parsing for JumpsBetween is working.
In writing this now I just realized that we haven't yet attempted coverage for statistics on expressions (like "(blah1 + 3*blah2)"), which we should probably try adding. The current 4th subgroup of "statistic_3" covers statistics on "complex" variables like the main one of current interest, JumpsBetween; this is the part that is broken, causing a segfault when the parser attempts to parse something meeting this pattern-- specifically when the statistic_3 rule tries to apply the complex_variable parser.
One of the things I've figured out was how to add a lot of debugging info into the parser, together with some additional logging in various ValueRef and Condition constructors this has helped a lot; these changes are in the attached "snapshot" patch if anyone else wants to experiment. That's how I could determine the statistic_3 failure point, the stat 3 code is
Code: Select all
statistic_3
= parse::enum_parser<ValueRef::StatisticType>() [ std::cout << phx::val("trying Statistic3 type(") << _1 << phx::val(")\n") << std::flush, _b = _1 ]
>> parse::label(Value_token)
>> (
(
( constant [_c = _1 ] // match only a subset of ValueRef types here, because parsing as a top-level
| free_variable [_c = _1 ] // ValueRef here causes deadlocks on parser init on some systems
| bound_variable [_c = _1 ] // todo: try allowing parsing of complex variables here
)
>> parse::label(Condition_token) > parse::detail::condition_parser
[ std::cout << phx::val(" Statistic3 finishing after const, free or bound.\n") << std::flush, _val = new_<ValueRef::Statistic<T> >(_c, _b, _1) ])
| ( eps [std::cout << phx::val(" Statistic3 trying complex var.\n") << std::flush]
>> complex_variable [ std::cout << phx::val(" Statistic3 parsed complex var.\n") << std::flush, _c = _1 ]
>> parse::label(Condition_token) > parse::detail::condition_parser
[ _val = new_<ValueRef::Statistic<T> >(_c, _b, _1) ])
)
;
For a successful parse, like for the the second Object ref of this JumpsBetween, which triggers the Statistic3 parser
Code: Select all
Statistic name = "STATISTICS_TEST_1" value =
JumpsBetween object = source.SystemID object = MAX Value = LocalCandidate.SystemID
condition = And [
Planet
OwnedBy empire = Source.Owner
]
the key portion of the debugging output is
Code: Select all
double ref parser trying int stats
double ref parser trying int complex var
found JumpsBetween
Constructing VariableRef property name: Source.SystemID)
===============
Constructing VariableRef property name: Source.SystemID)
===============
JumpsBetween got first object ID ref
trying Statistic2 type(7)
trying Statistic3 type(7)
Constructing VariableRef property name: LocalCandidate.SystemID)
===============
Constructing And Condition1: [ that is a Planet and that belongs to source's owner empire]
======================
Statistic3 finishing after const, free or bound.
-----
Constructing Max Statistic on valueref-- statistic: [(stat type: 7)type(int) (MAX)(value ref: local condition candidate's system id)(property name: )(sampling condition: that is a Planet and that belongs to source's owner empire)]
=================
JumpsBetween got second object ID ref
---------
Constructing ComplexVariable: Complex Variable: [(Variable Name: JumpsBetween) ((ir1: source's system id), (ir2: statistic: [(stat type: 7)type(int) (MAX)(value ref: local condition candidate's system id)(property name: )(sampling condition: that is a Planet and that belongs to source's owner empire)])]==================
double ref parser finishing int complex var
Constructing StaticCast from(int) to (double) of [Complex Variable: [(Variable Name: JumpsBetween) ((ir1: source's system id), (ir2: statistic: [(stat type: 7)type(int) (MAX)(value ref: local condition candidate's system id)(property name: )(sampling condition: that is a Planet and that belongs to source's owner empire)])]]
======
There is some doubling up (or more) of ValueRef & Condition constructions due to deep copies being made by the parser (even more than is shown, I redacted some), but at least it parses ok.
for the problem child statistic, though,
Code: Select all
// The following currently causes a crash upon parsing
Statistic name = "STATISTICS_TEST_3" value =
MAX Value = JumpsBetween object = source.SystemID object = LocalCandidate.SystemID
condition = And [
OwnedBy empire = Source.Owner
Planet
]
the debug output for this whole statistic is just
Code: Select all
double ref parser trying int stats
trying Statistic2 type(7)
trying Statistic3 type(7)
Statistic3 trying complex var.
The thing that is particularly perplexing here is that at this point, where the complex variable parser causes a segfault, it has already been used successfully many times. It appears to me that somehow when stat3 is initialized it is not getting a proper reference to the complex variable parser, but instead is working with a reference to some temporary copy which later has gone out of scope. I've tried doing everything I can to avoid that, but haven't been able to figure it out.
I did notice that the complex variable parser is handles a bit differently than the other parsers (i.e., not kept as a function local static), and tried restructuring along those lines, but to no avail. That attempt is attached is a "restructured" patch; it seems partially successful in that it apparently avoids the crash, but unless I stick with having the stats and complex_variable parsers use only the most simplistic int refs (which is too restrictive for either of the above examples), then I get initialization deadlock like we used to have.
So, at least this should be some helpful info for other future parser debugging needs, but I think I need to take a long break from any more attempts on this stat3 of a complex variable.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0