/*
* Copyright 2008 CoreMedia AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package net.jangaroo.jooc.ast;
import net.jangaroo.jooc.JooSymbol;
import net.jangaroo.jooc.Jooc;
import net.jangaroo.jooc.Scope;
import net.jangaroo.jooc.SyntacticKeywords;
import java.io.IOException;
import java.util.List;
/**
* @author Andreas Gawecki
* @author Frank Wienberg
*/
public class ForInStatement extends LoopStatement {
private JooSymbol symEach;
private JooSymbol lParen;
private VariableDeclaration decl;
private Expr lValue; // only as alternative to decl
private JooSymbol symIn;
private Expr expr;
private JooSymbol rParen;
private Ide auxIde; // generated for each loop auxiliary loop variable
private Ide exprAuxIde; // generated for each loop auxiliary expression value variable
public ForInStatement(JooSymbol symFor, JooSymbol symEach, JooSymbol lParen, VariableDeclaration decl, JooSymbol symIn, Expr expr, JooSymbol rParen, Statement body) {
this(symFor, symEach, lParen, decl, null, symIn, expr, rParen, body);
}
public ForInStatement(JooSymbol symFor, JooSymbol symEach, JooSymbol lParen, Expr lValue, JooSymbol symIn, Expr expr, JooSymbol rParen, Statement body) {
this(symFor, symEach, lParen, null, lValue, symIn, expr, rParen, body);
}
private ForInStatement(JooSymbol symFor, JooSymbol symEach, JooSymbol lParen, VariableDeclaration decl, Expr lValue, JooSymbol symIn, Expr expr, JooSymbol rParen, Statement body) {
super(symFor, body);
if (!(symEach == null || SyntacticKeywords.EACH.equals(symEach.getText()))) {
throw Jooc.error(symEach, "'for' must be followed by '(' or 'each'.");
}
this.symEach = symEach;
this.lParen = lParen;
this.decl = decl;
this.lValue = lValue;
this.symIn = symIn;
this.expr = expr;
this.rParen = rParen;
}
@Override
public List<? extends AstNode> getChildren() {
return makeChildren(super.getChildren(), decl, lValue, expr);
}
public JooSymbol getSymEach() {
return symEach;
}
public JooSymbol getLParen() {
return lParen;
}
public VariableDeclaration getDecl() {
return decl;
}
public Expr getLValue() {
return lValue;
}
public JooSymbol getSymIn() {
return symIn;
}
public Expr getExpr() {
return expr;
}
public JooSymbol getRParen() {
return rParen;
}
public Ide getAuxIde() {
return auxIde;
}
public Ide getExprAuxIde() {
return exprAuxIde;
}
@Override
public void visit(AstVisitor visitor) throws IOException {
visitor.visitForInStatement(this);
}
@Override
public void scope(final Scope scope) {
super.scope(scope);
// always create aux var, as looping over an Array needs it even without "each":
auxIde = scope.createAuxVar(scope);
auxIde.scope(scope);
if (symEach != null) {
if (!(getExpr() instanceof IdeExpr)) {
exprAuxIde = scope.createAuxVar(scope);
exprAuxIde.scope(scope);
}
}
if (decl != null) {
decl.scope(scope);
} else {
lValue.scope(scope);
}
expr.scope(scope);
}
protected void analyzeLoopHeader() {
if (decl != null) {
decl.analyze(this);
} else {
lValue.analyze(this);
}
expr.analyze(this);
}
}