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}