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