/* Compiler implementation of the D programming language * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved * written by Walter Bright * http://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. * http://www.boost.org/LICENSE_1_0.txt * https://github.com/D-Programming-Language/dmd/blob/master/src/apply.c */ #include "root/dsystem.h" #include "mars.h" #include "expression.h" #include "template.h" #include "visitor.h" /************************************** * An Expression tree walker that will visit each Expression e in the tree, * in depth-first evaluation order, and call fp(e,param) on it. * fp() signals whether the walking continues with its return value: * Returns: * 0 continue * 1 done * It's a bit slower than using virtual functions, but more encapsulated and less brittle. * Creating an iterator for this would be much more complex. */ class PostorderExpressionVisitor : public StoppableVisitor { public: StoppableVisitor *v; PostorderExpressionVisitor(StoppableVisitor *v) : v(v) {} bool doCond(Expression *e) { if (!stop && e) e->accept(this); return stop; } bool doCond(Expressions *e) { if (!e) return false; for (size_t i = 0; i < e->dim && !stop; i++) doCond((*e)[i]); return stop; } bool applyTo(Expression *e) { e->accept(v); stop = v->stop; return true; } void visit(Expression *e) { applyTo(e); } void visit(NewExp *e) { //printf("NewExp::apply(): %s\n", toChars()); doCond(e->thisexp) || doCond(e->newargs) || doCond(e->arguments) || applyTo(e); } void visit(NewAnonClassExp *e) { //printf("NewAnonClassExp::apply(): %s\n", toChars()); doCond(e->thisexp) || doCond(e->newargs) || doCond(e->arguments) || applyTo(e); } void visit(TypeidExp *e) { doCond(isExpression(e->obj)) || applyTo(e); } void visit(UnaExp *e) { doCond(e->e1) || applyTo(e); } void visit(BinExp *e) { doCond(e->e1) || doCond(e->e2) || applyTo(e); } void visit(AssertExp *e) { //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars()); doCond(e->e1) || doCond(e->msg) || applyTo(e); } void visit(CallExp *e) { //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars()); doCond(e->e1) || doCond(e->arguments) || applyTo(e); } void visit(ArrayExp *e) { //printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars()); doCond(e->e1) || doCond(e->arguments) || applyTo(e); } void visit(SliceExp *e) { doCond(e->e1) || doCond(e->lwr) || doCond(e->upr) || applyTo(e); } void visit(ArrayLiteralExp *e) { doCond(e->basis) || doCond(e->elements) || applyTo(e); } void visit(AssocArrayLiteralExp *e) { doCond(e->keys) || doCond(e->values) || applyTo(e); } void visit(StructLiteralExp *e) { if (e->stageflags & stageApply) return; int old = e->stageflags; e->stageflags |= stageApply; doCond(e->elements) || applyTo(e); e->stageflags = old; } void visit(TupleExp *e) { doCond(e->e0) || doCond(e->exps) || applyTo(e); } void visit(CondExp *e) { doCond(e->econd) || doCond(e->e1) || doCond(e->e2) || applyTo(e); } }; bool walkPostorder(Expression *e, StoppableVisitor *v) { PostorderExpressionVisitor pv(v); e->accept(&pv); return v->stop; }