Skip to content

Commit 776ca6b

Browse files
committed
separate ASTVisitor.visit for ExpressionNode
abstract classes should not have visitor functions, but rather only do dynamic dispatch. This becomes more important later with #409
1 parent 2490a81 commit 776ca6b

File tree

2 files changed

+67
-42
lines changed

2 files changed

+67
-42
lines changed

src/dparse/ast.d

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,32 @@ enum DeclarationListStyle : ubyte
9292
*/
9393
abstract class ASTVisitor
9494
{
95-
96-
/** */
95+
deprecated("Don't use or override visit(ExpressionNode). For usage: dynamicDispatch(ExpressionNode) is equivalent; "
96+
~ "for overriding: you should probably override more specific cases. If you need to override to inject some "
97+
~ "before/after code for all cases, make sure to call `super.dynamicDispatch(n)` instead of `n.accept(this)`!")
9798
void visit(const ExpressionNode n)
9899
{
99-
switch (typeMap[typeid(n)])
100+
dynamicDispatch(n);
101+
}
102+
103+
/**
104+
* Looks at the runtime type of `n`, then calls the appropriate `visit`
105+
* method at runtime.
106+
*
107+
* Rule of thumb: when the type is an abstract class, use `dynamicDispatch`,
108+
* otherwise use `visit`.
109+
*
110+
* For templated calls:
111+
* ---
112+
* static if (__traits(isAbstractClass, typeof(node)))
113+
* visitor.dynamicDispatch(node);
114+
* else
115+
* visitor.visit(node);
116+
* ---
117+
*/
118+
void dynamicDispatch(const ExpressionNode n)
119+
{
120+
switch (typeMap.get(typeid(n), 0))
100121
{
101122
case 1: visit(cast(AddExpression) n); break;
102123
case 2: visit(cast(AndAndExpression) n); break;
@@ -383,11 +404,15 @@ template visitIfNotNull(fields ...)
383404
{
384405
static if (typeof(fields[0]).stringof[$ - 2 .. $] == "[]")
385406
{
386-
static if (__traits(hasMember, typeof(fields[0][0]), "classinfo"))
407+
static if (__traits(isAbstractClass, typeof(fields[0][0])))
408+
immutable visitIfNotNull = "foreach (i; " ~ fields[0].stringof ~ ") if (i !is null) visitor.dynamicDispatch(i);\n";
409+
else static if (__traits(hasMember, typeof(fields[0][0]), "classinfo"))
387410
immutable visitIfNotNull = "foreach (i; " ~ fields[0].stringof ~ ") if (i !is null) visitor.visit(i);\n";
388411
else
389412
immutable visitIfNotNull = "foreach (i; " ~ fields[0].stringof ~ ") visitor.visit(i);\n";
390413
}
414+
else static if (__traits(isAbstractClass, typeof(fields[0])))
415+
immutable visitIfNotNull = "if (" ~ fields[0].stringof ~ " !is null) visitor.dynamicDispatch(" ~ fields[0].stringof ~ ");\n";
391416
else static if (__traits(hasMember, typeof(fields[0]), "classinfo"))
392417
immutable visitIfNotNull = "if (" ~ fields[0].stringof ~ " !is null) visitor.visit(" ~ fields[0].stringof ~ ");\n";
393418
else static if (is(Unqual!(typeof(fields[0])) == Token))

src/dparse/astprinter.d

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ class XMLPrinter : ASTVisitor
2323
{
2424
output.writeln("<addExpression operator=\"", str(addExpression.operator), "\">");
2525
output.writeln("<left>");
26-
visit(addExpression.left);
26+
dynamicDispatch(addExpression.left);
2727
output.writeln("</left>");
2828
if (addExpression.right !is null)
2929
{
3030
output.writeln("<right>");
31-
visit(addExpression.right);
31+
dynamicDispatch(addExpression.right);
3232
output.writeln("</right>");
3333
}
3434
output.writeln("</addExpression>");
@@ -58,12 +58,12 @@ class XMLPrinter : ASTVisitor
5858
{
5959
output.writeln("<andAndExpression>");
6060
output.writeln("<left>");
61-
visit(andAndExpression.left);
61+
dynamicDispatch(andAndExpression.left);
6262
output.writeln("</left>");
6363
if (andAndExpression.right !is null)
6464
{
6565
output.writeln("<right>");
66-
visit(andAndExpression.right);
66+
dynamicDispatch(andAndExpression.right);
6767
output.writeln("</right>");
6868
}
6969
output.writeln("</andAndExpression>");
@@ -73,12 +73,12 @@ class XMLPrinter : ASTVisitor
7373
{
7474
output.writeln("<andExpression>");
7575
output.writeln("<left>");
76-
visit(andExpression.left);
76+
dynamicDispatch(andExpression.left);
7777
output.writeln("</left>");
7878
if (andExpression.right !is null)
7979
{
8080
output.writeln("<right>");
81-
visit(andExpression.right);
81+
dynamicDispatch(andExpression.right);
8282
output.writeln("</right>");
8383
}
8484
output.writeln("</andExpression>");
@@ -191,13 +191,13 @@ class XMLPrinter : ASTVisitor
191191
if (caseRangeStatement.low !is null)
192192
{
193193
output.writeln("<low>");
194-
visit(caseRangeStatement.low);
194+
dynamicDispatch(caseRangeStatement.low);
195195
output.writeln("</low>");
196196
}
197197
if (caseRangeStatement.high !is null)
198198
{
199199
output.writeln("<high>");
200-
visit(caseRangeStatement.high);
200+
dynamicDispatch(caseRangeStatement.high);
201201
output.writeln("</high>");
202202
}
203203
if (caseRangeStatement.declarationsAndStatements !is null)
@@ -295,7 +295,7 @@ class XMLPrinter : ASTVisitor
295295
if (deprecated_.assignExpression !is null)
296296
{
297297
output.writeln("<deprecated>");
298-
visit(deprecated_.assignExpression);
298+
dynamicDispatch(deprecated_.assignExpression);
299299
output.writeln("</deprecated>");
300300
}
301301
else
@@ -320,7 +320,7 @@ class XMLPrinter : ASTVisitor
320320
visit(enumMember.type);
321321
output.write("<name>", enumMember.name.text, "</name>");
322322
if (enumMember.assignExpression !is null)
323-
visit(enumMember.assignExpression);
323+
dynamicDispatch(enumMember.assignExpression);
324324
output.writeln("</anonymousEnumMember>");
325325
}
326326

@@ -336,10 +336,10 @@ class XMLPrinter : ASTVisitor
336336
{
337337
output.writeln("<equalExpression operator=\"", str(equalExpression.operator), "\">");
338338
output.writeln("<left>");
339-
visit(equalExpression.left);
339+
dynamicDispatch(equalExpression.left);
340340
output.writeln("</left>");
341341
output.writeln("<right>");
342-
visit(equalExpression.right);
342+
dynamicDispatch(equalExpression.right);
343343
output.writeln("</right>");
344344
output.writeln("</equalExpression>");
345345
}
@@ -475,10 +475,10 @@ class XMLPrinter : ASTVisitor
475475
else
476476
output.writeln("<identityExpression operator=\"is\">");
477477
output.writeln("<left>");
478-
visit(identityExpression.left);
478+
dynamicDispatch(identityExpression.left);
479479
output.writeln("</left>");
480480
output.writeln("<right>");
481-
visit(identityExpression.right);
481+
dynamicDispatch(identityExpression.right);
482482
output.writeln("</right>");
483483
output.writeln("</identityExpression>");
484484
}
@@ -541,10 +541,10 @@ class XMLPrinter : ASTVisitor
541541
else
542542
output.writeln("<inExpression operator=\"in\">");
543543
output.writeln("<left>");
544-
visit(inExpression.left);
544+
dynamicDispatch(inExpression.left);
545545
output.writeln("</left>");
546546
output.writeln("<right>");
547-
visit(inExpression.right);
547+
dynamicDispatch(inExpression.right);
548548
output.writeln("</right>");
549549
output.writeln("</inExpression>");
550550
}
@@ -613,10 +613,10 @@ class XMLPrinter : ASTVisitor
613613
{
614614
output.writeln("<keyValuePair>");
615615
output.writeln("<key>");
616-
visit(keyValuePair.key);
616+
dynamicDispatch(keyValuePair.key);
617617
output.writeln("</key>");
618618
output.writeln("<value>");
619-
visit(keyValuePair.value);
619+
dynamicDispatch(keyValuePair.value);
620620
output.writeln("</value>");
621621
output.writeln("</keyValuePair>");
622622
}
@@ -676,12 +676,12 @@ class XMLPrinter : ASTVisitor
676676
{
677677
output.writeln("<mulExpression operator=\"", str(mulExpression.operator), "\">");
678678
output.writeln("<left>");
679-
visit(mulExpression.left);
679+
dynamicDispatch(mulExpression.left);
680680
output.writeln("</left>");
681681
if (mulExpression.right !is null)
682682
{
683683
output.writeln("<right>");
684-
visit(mulExpression.right);
684+
dynamicDispatch(mulExpression.right);
685685
output.writeln("</right>");
686686
}
687687
output.writeln("</mulExpression>");
@@ -691,12 +691,12 @@ class XMLPrinter : ASTVisitor
691691
{
692692
output.writeln("<orOrExpression>");
693693
output.writeln("<left>");
694-
visit(orOrExpression.left);
694+
dynamicDispatch(orOrExpression.left);
695695
output.writeln("</left>");
696696
if (orOrExpression.right !is null)
697697
{
698698
output.writeln("<right>");
699-
visit(orOrExpression.right);
699+
dynamicDispatch(orOrExpression.right);
700700
output.writeln("</right>");
701701
}
702702
output.writeln("</orOrExpression>");
@@ -727,12 +727,12 @@ class XMLPrinter : ASTVisitor
727727
{
728728
output.writeln("<powExpression>");
729729
output.writeln("<left>");
730-
visit(powExpression.left);
730+
dynamicDispatch(powExpression.left);
731731
output.writeln("</left>");
732732
if (powExpression.right !is null)
733733
{
734734
output.writeln("<right>");
735-
visit(powExpression.right);
735+
dynamicDispatch(powExpression.right);
736736
output.writeln("</right>");
737737
}
738738
output.writeln("</powExpression>");
@@ -743,10 +743,10 @@ class XMLPrinter : ASTVisitor
743743
output.writeln("<relExpression operator=\"",
744744
xmlAttributeEscape(str(relExpression.operator)), "\">");
745745
output.writeln("<left>");
746-
visit(relExpression.left);
746+
dynamicDispatch(relExpression.left);
747747
output.writeln("</left>");
748748
output.writeln("<right>");
749-
visit(relExpression.right);
749+
dynamicDispatch(relExpression.right);
750750
output.writeln("</right>");
751751
output.writeln("</relExpression>");
752752
}
@@ -768,10 +768,10 @@ class XMLPrinter : ASTVisitor
768768
output.writeln("<shiftExpression operator=\"",
769769
xmlAttributeEscape(str(shiftExpression.operator)), "\">");
770770
output.writeln("<left>");
771-
visit(shiftExpression.left);
771+
dynamicDispatch(shiftExpression.left);
772772
output.writeln("</left>");
773773
output.writeln("<right>");
774-
visit(shiftExpression.right);
774+
dynamicDispatch(shiftExpression.right);
775775
output.writeln("</right>");
776776
output.writeln("</shiftExpression>");
777777
}
@@ -804,7 +804,7 @@ class XMLPrinter : ASTVisitor
804804
if (templateAliasParameter.colonExpression !is null)
805805
{
806806
output.writeln("<specialization>");
807-
visit(templateAliasParameter.colonExpression);
807+
dynamicDispatch(templateAliasParameter.colonExpression);
808808
output.writeln("</specialization>");
809809
}
810810
else if (templateAliasParameter.colonType !is null)
@@ -817,7 +817,7 @@ class XMLPrinter : ASTVisitor
817817
if (templateAliasParameter.assignExpression !is null)
818818
{
819819
output.writeln("<default>");
820-
visit(templateAliasParameter.assignExpression);
820+
dynamicDispatch(templateAliasParameter.assignExpression);
821821
output.writeln("</default>");
822822
}
823823
else if (templateAliasParameter.assignType !is null)
@@ -962,14 +962,14 @@ class XMLPrinter : ASTVisitor
962962
if (typeSuffix.high !is null)
963963
{
964964
output.writeln("<low>");
965-
visit(typeSuffix.low);
965+
dynamicDispatch(typeSuffix.low);
966966
output.writeln("</low>");
967967
output.writeln("<high>");
968-
visit(typeSuffix.high);
968+
dynamicDispatch(typeSuffix.high);
969969
output.writeln("</high>");
970970
}
971971
else
972-
visit(typeSuffix.low);
972+
dynamicDispatch(typeSuffix.low);
973973
output.writeln("</typeSuffix>");
974974
}
975975
}
@@ -1041,12 +1041,12 @@ class XMLPrinter : ASTVisitor
10411041
{
10421042
output.writeln("<xorExpression>");
10431043
output.writeln("<left>");
1044-
visit(xorExpression.left);
1044+
dynamicDispatch(xorExpression.left);
10451045
output.writeln("</left>");
10461046
if (xorExpression.right !is null)
10471047
{
10481048
output.writeln("<right>");
1049-
visit(xorExpression.right);
1049+
dynamicDispatch(xorExpression.right);
10501050
output.writeln("</right>");
10511051
}
10521052
output.writeln("</xorExpression>");
@@ -1058,15 +1058,15 @@ class XMLPrinter : ASTVisitor
10581058
if (index.high)
10591059
{
10601060
output.writeln("<low>");
1061-
visit(index.low);
1061+
dynamicDispatch(index.low);
10621062
output.writeln("</low>");
10631063

10641064
output.writeln("<high>");
1065-
visit(index.high);
1065+
dynamicDispatch(index.high);
10661066
output.writeln("</high>");
10671067
}
10681068
else
1069-
visit(index.low);
1069+
dynamicDispatch(index.low);
10701070
output.writeln("</index>");
10711071
}
10721072

0 commit comments

Comments
 (0)