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 java.util.Objects; 015import org.eclipse.golo.compiler.parser.GoloASTNode; 016 017import static java.util.Collections.unmodifiableList; 018 019public final class ForEachLoopStatement extends GoloStatement implements Scope, BlockContainer { 020 private Block block = Block.emptyBlock(); 021 private ExpressionStatement iterable; 022 private final List<LocalReference> valueRefs = new LinkedList<>(); 023 private ExpressionStatement whenClause; 024 private boolean isVarargs = false; 025 026 ForEachLoopStatement() { 027 super(); 028 } 029 030 public ForEachLoopStatement block(Object block) { 031 this.block = Builders.toBlock(block); 032 return this; 033 } 034 035 @Override 036 public ForEachLoopStatement ofAST(GoloASTNode node) { 037 node.setIrElement(this); 038 return this; 039 } 040 041 public ForEachLoopStatement on(Object iterable) { 042 this.iterable = ExpressionStatement.of(iterable); 043 return this; 044 } 045 046 public ForEachLoopStatement varargs(boolean b) { 047 this.isVarargs = b; 048 return this; 049 } 050 051 public ForEachLoopStatement var(Object varRef) { 052 LocalReference ref; 053 if (varRef instanceof String) { 054 ref = Builders.localRef(varRef).variable(); 055 } else if (varRef instanceof LocalReference) { 056 ref = (LocalReference) varRef; 057 } else { 058 throw new IllegalArgumentException("not a ref, a string or a builder"); 059 } 060 this.valueRefs.add(ref); 061 return this; 062 } 063 064 public ForEachLoopStatement when(Object clause) { 065 this.whenClause = ExpressionStatement.of(clause); 066 return this; 067 } 068 069 public ExpressionStatement getIterable() { 070 return iterable; 071 } 072 073 public Block getBlock() { 074 return block; 075 } 076 077 public boolean isDestructuring() { 078 return valueRefs.size() > 1; 079 } 080 081 public boolean isVarargs() { 082 return this.isVarargs; 083 } 084 085 public LocalReference getReference() { 086 return valueRefs.get(0); 087 } 088 089 public List<LocalReference> getReferences() { 090 return unmodifiableList(valueRefs); 091 } 092 093 public boolean hasWhenClause() { 094 return whenClause != null; 095 } 096 097 public ExpressionStatement getWhenClause() { 098 return whenClause; 099 } 100 101 @Override 102 public void relink(ReferenceTable table) { 103 block.relink(table); 104 } 105 106 @Override 107 public void relinkTopLevel(ReferenceTable table) { 108 block.relinkTopLevel(table); 109 } 110 111 @Override 112 public void accept(GoloIrVisitor visitor) { 113 visitor.visitForEachLoopStatement(this); 114 } 115 116 @Override 117 public void walk(GoloIrVisitor visitor) { 118 for (LocalReference ref : valueRefs) { 119 ref.accept(visitor); 120 } 121 iterable.accept(visitor); 122 if (whenClause != null) { 123 whenClause.accept(visitor); 124 } 125 block.accept(visitor); 126 } 127 128 @Override 129 protected void replaceElement(GoloElement original, GoloElement newElement) { 130 if (Objects.equals(iterable, original)) { 131 on(newElement); 132 } else if (Objects.equals(whenClause, original)) { 133 when(newElement); 134 } else if (Objects.equals(block, original)) { 135 block(newElement); 136 } else { 137 throw cantReplace(original, newElement); 138 } 139 } 140}