001    // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
002    // for details. All rights reserved. Use of this source code is governed by a
003    // BSD-style license that can be found in the LICENSE file.
004    
005    package com.google.dart.compiler.backend.js.ast;
006    
007    import com.google.dart.compiler.util.AstUtil;
008    import org.jetbrains.annotations.NotNull;
009    
010    /**
011     * A <code>for</code> statement. If specified at all, the initializer part is
012     * either a declaration of one or more variables, in which case
013     * {@link #getInitVars()} is used, or an expression, in which case
014     * {@link #getInitExpression()} is used. In the latter case, the comma operator is
015     * often used to create a compound expression.
016     * <p/>
017     * <p/>
018     * Note that any of the parts of the <code>for</code> loop header can be
019     * <code>null</code>, although the body will never be null.
020     */
021    public class JsFor extends SourceInfoAwareJsNode implements JsStatement {
022        private JsStatement body;
023        private JsExpression condition;
024        private JsExpression incrementExpression;
025        private JsExpression initExpression;
026        private JsVars initVars;
027    
028        public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression) {
029            this(initVars, condition, incrementExpression, null);
030        }
031    
032        public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
033            this.initVars = initVars;
034            this.incrementExpression = incrementExpression;
035            this.condition = condition;
036            this.body = body;
037            initExpression = null;
038        }
039    
040        public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression) {
041            this(initExpression, condition, incrementExpression, null);
042        }
043    
044        public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
045            this.initExpression = initExpression;
046            this.incrementExpression = incrementExpression;
047            this.condition = condition;
048            this.body = body;
049            initVars = null;
050        }
051    
052        public JsStatement getBody() {
053            return body;
054        }
055    
056        public JsExpression getCondition() {
057            return condition;
058        }
059    
060        public JsExpression getIncrementExpression() {
061            return incrementExpression;
062        }
063    
064        public JsExpression getInitExpression() {
065            return initExpression;
066        }
067    
068        public JsVars getInitVars() {
069            return initVars;
070        }
071    
072        public void setBody(JsStatement body) {
073            this.body = body;
074        }
075    
076        @Override
077        public void accept(JsVisitor v) {
078            v.visitFor(this);
079        }
080    
081        @Override
082        public void acceptChildren(JsVisitor visitor) {
083            assert (!(initExpression != null && initVars != null));
084    
085            if (initExpression != null) {
086                visitor.accept(initExpression);
087            }
088            else if (initVars != null) {
089                visitor.accept(initVars);
090            }
091    
092            if (condition != null) {
093                visitor.accept(condition);
094            }
095    
096            if (incrementExpression != null) {
097                visitor.accept(incrementExpression);
098            }
099            visitor.accept(body);
100        }
101    
102        @Override
103        public void traverse(JsVisitorWithContext v, JsContext ctx) {
104            if (v.visit(this, ctx)) {
105                assert (!(initExpression != null && initVars != null));
106    
107                if (initExpression != null) {
108                    initExpression = v.accept(initExpression);
109                } else if (initVars != null) {
110                    initVars = v.acceptStatement(initVars);
111                }
112    
113                if (condition != null) {
114                    condition = v.accept(condition);
115                }
116    
117                if (incrementExpression != null) {
118                    incrementExpression = v.accept(incrementExpression);
119                }
120                body = v.acceptStatement(body);
121            }
122            v.endVisit(this, ctx);
123        }
124    
125        @NotNull
126        @Override
127        public JsFor deepCopy() {
128            JsStatement bodyCopy = AstUtil.deepCopy(body);
129            JsExpression conditionCopy = AstUtil.deepCopy(condition);
130            JsExpression incrementalExprCopy = AstUtil.deepCopy(incrementExpression);
131    
132            JsFor result;
133            if (initVars != null) {
134                result = new JsFor(initVars.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy);
135            } else {
136                result = new JsFor(initExpression.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy);
137            }
138    
139            return result.withMetadataFrom(this);
140        }
141    }