001/*
002 * Copyright (c) 2012-2017 Institut National des Sciences Appliquées de Lyon (INSA-Lyon)
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 */
009
010package org.eclipse.golo.compiler.ir;
011
012import java.util.List;
013import java.util.LinkedList;
014import org.eclipse.golo.compiler.parser.GoloASTNode;
015
016import static java.util.Collections.unmodifiableList;
017
018public class CollectionComprehension extends ExpressionStatement {
019
020  private final CollectionLiteral.Type type;
021  private ExpressionStatement expression;
022  private final List<Block> loopBlocks = new LinkedList<>();
023
024  CollectionComprehension(CollectionLiteral.Type type) {
025    super();
026    this.type = type;
027  }
028
029  @Override
030  public CollectionComprehension ofAST(GoloASTNode n) {
031    super.ofAST(n);
032    return this;
033  }
034
035  public CollectionComprehension expression(Object expression) {
036    this.expression = (ExpressionStatement) expression;
037    makeParentOf(this.expression);
038    return this;
039  }
040
041  public CollectionComprehension loop(Object b) {
042    Block theBlock = Block.of(b);
043    this.loopBlocks.add(theBlock);
044    makeParentOf(theBlock);
045    return this;
046  }
047
048  public ExpressionStatement getExpression() {
049    return this.expression;
050  }
051
052  public List<Block> getLoopBlocks() {
053    return unmodifiableList(loopBlocks);
054  }
055
056  public CollectionLiteral.Type getType() {
057    return this.type;
058  }
059
060  public CollectionLiteral.Type getMutableType() {
061    return (CollectionLiteral.Type.tuple.equals(type)
062       || CollectionLiteral.Type.array.equals(type))
063      ? CollectionLiteral.Type.list
064      : type;
065  }
066
067  @Override
068  public void accept(GoloIrVisitor visitor) {
069    visitor.visitCollectionComprehension(this);
070  }
071
072  @Override
073  public void walk(GoloIrVisitor visitor) {
074    expression.accept(visitor);
075    for (Block block: loopBlocks) {
076      block.accept(visitor);
077    }
078  }
079
080  @Override
081  protected void replaceElement(GoloElement original, GoloElement newElement) {
082    if (expression == original && newElement instanceof ExpressionStatement) {
083      expression(newElement);
084    } else if (newElement instanceof Block && loopBlocks.contains(original)) {
085      loopBlocks.set(loopBlocks.indexOf(original), (Block) newElement);
086    } else {
087      throw cantReplace(original, newElement);
088    }
089  }
090}