Alright it's been a number of months since I've dabbled in D, but my<br>spare time is slowly increasing... for now. Fingers crossed.<br><br>So I'm going to attack this property lowering thing again.<br><br>Here is a reminder of what I'm talking about:<br>
<a href="http://prowiki.org/wiki4d/wiki.cgi?DocComments/Property">http://prowiki.org/wiki4d/wiki.cgi?DocComments/Property</a><br><br>When I did this first I got 95% of the way there and hit a corner-case<br>in DMD's code. This chicken-and-egg problem is what happened:<br>
<br>(1) e->semantic(sc) is called. (e is an Expression)<br>- This will call e's children's semantic.<br><br>(2) resolveProperties must come after e->semantic(sc).<br>- It needs e->semantic to get the type info and<br>
- to know if e contains properties (recursively).<br><br>(3) If e has side effects and the mutated value(s) contain properties,<br>then resolveProperties turns the mutated value(s) into multiple<br>expressions within a comma expression such that no properties are in a<br>
side-effectful expression.<br><br>(4) The resulting CommaExp's (and other generated Exps) must have<br>semantic(sc) run on them to create type information.<br>- This will call e's children's semantic(sc), again.<br>
<br>(5) semantic(sc) must not be run on an Expression more than once.<br>- This is why my 95%-of-the-way-there code would work perfectly most<br>of the time and then fail in very rare instances.<br><br>4 and 5 contradict each other.<br>
<br>I'm wondering if there is some canonically accepted way of dealing with<br>this kind of stuff in DMD. I'd hate to write this and have it go to<br>waste because I missed an idiom or coding convention.<br><br>
I've considered these possibilities:<br>
<br>- I could guard the execution of semantic to make sure it is never done<br>more than once:<br><br>Expression *FooExp::semantic( Scope *sc )<br>{<br> if ( semanticAlreadyCalledOnThis )<br> return this;<br><br>
... etc<br>}<br><br>- I could do the above, but place that in a non-virtual semantic so that<br>the code isn't duplicated everywhere. I would have to make all calls to<br>semantic point to the non-virtual version. For sake of description,<br>
I'll call the non-virtual one "semantic" and the current virtual one<br>"onSemantic".<br><br>Expression *FooExp::semantic( Scope *sc )<br>{<br> if ( semanticAlreadyCalledOnThis )<br> return this;<br>
<br> return onSemantic(sc)<br>}<br><br>Expression *FooExp::onSemantic( Scope *sc )<br>{<br> ... (previous semantic code for FooExp) ...<br>}<br><br>- I write a "shallowSemantic" method for the CommaExp, VarDeclaration,<br>
DeclarationExp, AssignExp, and anything else generated by the property<br>rewrite. This would have to be called manually as its generated. This<br>may not touch as many things as the above possibilities, but I suspect<br>
it will be much uglier.<br><br><br>Please advise.<br>- Chad<br><br>