1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _apply.d) 9 */ 10 11 module ddmd.apply; 12 13 import ddmd.arraytypes; 14 import ddmd.dtemplate; 15 import ddmd.expression; 16 import ddmd.visitor; 17 18 /************************************** 19 * An Expression tree walker that will visit each Expression e in the tree, 20 * in depth-first evaluation order, and call fp(e,param) on it. 21 * fp() signals whether the walking continues with its return value: 22 * Returns: 23 * 0 continue 24 * 1 done 25 * It's a bit slower than using virtual functions, but more encapsulated and less brittle. 26 * Creating an iterator for this would be much more complex. 27 */ 28 extern (C++) final class PostorderExpressionVisitor : StoppableVisitor 29 { 30 alias visit = super.visit; 31 public: 32 StoppableVisitor v; 33 34 extern (D) this(StoppableVisitor v) 35 { 36 this.v = v; 37 } 38 39 bool doCond(Expression e) 40 { 41 if (!stop && e) 42 e.accept(this); 43 return stop; 44 } 45 46 bool doCond(Expressions* e) 47 { 48 if (!e) 49 return false; 50 for (size_t i = 0; i < e.dim && !stop; i++) 51 doCond((*e)[i]); 52 return stop; 53 } 54 55 bool applyTo(Expression e) 56 { 57 e.accept(v); 58 stop = v.stop; 59 return true; 60 } 61 62 override void visit(Expression e) 63 { 64 applyTo(e); 65 } 66 67 override void visit(NewExp e) 68 { 69 //printf("NewExp::apply(): %s\n", toChars()); 70 doCond(e.thisexp) || doCond(e.newargs) || doCond(e.arguments) || applyTo(e); 71 } 72 73 override void visit(NewAnonClassExp e) 74 { 75 //printf("NewAnonClassExp::apply(): %s\n", toChars()); 76 doCond(e.thisexp) || doCond(e.newargs) || doCond(e.arguments) || applyTo(e); 77 } 78 79 override void visit(TypeidExp e) 80 { 81 doCond(isExpression(e.obj)) || applyTo(e); 82 } 83 84 override void visit(UnaExp e) 85 { 86 doCond(e.e1) || applyTo(e); 87 } 88 89 override void visit(BinExp e) 90 { 91 doCond(e.e1) || doCond(e.e2) || applyTo(e); 92 } 93 94 override void visit(AssertExp e) 95 { 96 //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars()); 97 doCond(e.e1) || doCond(e.msg) || applyTo(e); 98 } 99 100 override void visit(CallExp e) 101 { 102 //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars()); 103 doCond(e.e1) || doCond(e.arguments) || applyTo(e); 104 } 105 106 override void visit(ArrayExp e) 107 { 108 //printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars()); 109 doCond(e.e1) || doCond(e.arguments) || applyTo(e); 110 } 111 112 override void visit(SliceExp e) 113 { 114 doCond(e.e1) || doCond(e.lwr) || doCond(e.upr) || applyTo(e); 115 } 116 117 override void visit(ArrayLiteralExp e) 118 { 119 doCond(e.basis) || doCond(e.elements) || applyTo(e); 120 } 121 122 override void visit(AssocArrayLiteralExp e) 123 { 124 doCond(e.keys) || doCond(e.values) || applyTo(e); 125 } 126 127 override void visit(StructLiteralExp e) 128 { 129 if (e.stageflags & stageApply) 130 return; 131 int old = e.stageflags; 132 e.stageflags |= stageApply; 133 doCond(e.elements) || applyTo(e); 134 e.stageflags = old; 135 } 136 137 override void visit(TupleExp e) 138 { 139 doCond(e.e0) || doCond(e.exps) || applyTo(e); 140 } 141 142 override void visit(CondExp e) 143 { 144 doCond(e.econd) || doCond(e.e1) || doCond(e.e2) || applyTo(e); 145 } 146 } 147 148 extern (C++) bool walkPostorder(Expression e, StoppableVisitor v) 149 { 150 scope PostorderExpressionVisitor pv = new PostorderExpressionVisitor(v); 151 e.accept(pv); 152 return v.stop; 153 }