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