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 org.eclipse.golo.compiler.parser.GoloASTNode;
013import java.util.Objects;
014
015import static org.eclipse.golo.compiler.ir.Builders.*;
016
017public final class LoopStatement extends GoloStatement implements Scope, BlockContainer {
018
019  private AssignmentStatement initStatement = null;
020  private ExpressionStatement conditionStatement = constant(false);
021  private GoloStatement postStatement = null;
022  private Block block = Block.emptyBlock();;
023
024  LoopStatement() {
025    super();
026  }
027
028  @Override
029  public LoopStatement ofAST(GoloASTNode node) {
030    super.ofAST(node);
031    return this;
032  }
033
034  public LoopStatement init(Object assignment) {
035    if (assignment instanceof AssignmentStatement) {
036      setInitStatement((AssignmentStatement) assignment);
037      return this;
038    }
039    throw cantConvert("assignment", assignment);
040  }
041
042  public LoopStatement condition(Object expression) {
043    if (expression instanceof ExpressionStatement) {
044      setConditionStatement((ExpressionStatement) expression);
045      return this;
046    }
047    throw cantConvert("expression", expression);
048  }
049
050  public LoopStatement post(Object statement) {
051    if (statement instanceof GoloStatement) {
052      setPostStatement((GoloStatement) statement);
053      return this;
054    }
055    throw cantConvert("statement", statement);
056  }
057
058  public LoopStatement block(Block innerBlock) {
059    setBlock(innerBlock);
060    return this;
061  }
062
063  public LoopStatement block(Object... statements) {
064    return this.block(Builders.block(statements));
065  }
066
067  public boolean hasInitStatement() {
068    return initStatement != null;
069  }
070
071  public AssignmentStatement getInitStatement() {
072    return initStatement;
073  }
074
075  public void setInitStatement(AssignmentStatement init) {
076    this.initStatement = init;
077    makeParentOf(init);
078  }
079
080  public ExpressionStatement getConditionStatement() {
081    return conditionStatement;
082  }
083
084  public void setConditionStatement(ExpressionStatement cond) {
085    conditionStatement = (cond == null ? constant(false) : cond);
086    makeParentOf(conditionStatement);
087  }
088
089  public Block getBlock() {
090    return block;
091  }
092
093  public void setBlock(Block block) {
094    this.block = (block == null ? Block.emptyBlock() : block);
095    makeParentOf(this.block);
096  }
097
098  public GoloStatement getPostStatement() {
099    return postStatement;
100  }
101
102  public void setPostStatement(GoloStatement stat) {
103    postStatement = stat;
104    makeParentOf(postStatement);
105  }
106
107  public boolean hasPostStatement() {
108    return postStatement != null;
109  }
110
111  @Override
112  public void relink(ReferenceTable table) {
113    block.relink(table);
114  }
115
116  @Override
117  public void relinkTopLevel(ReferenceTable table) {
118    block.relinkTopLevel(table);
119  }
120
121  @Override
122  public void accept(GoloIrVisitor visitor) {
123    visitor.visitLoopStatement(this);
124  }
125
126  @Override
127  public void walk(GoloIrVisitor visitor) {
128    if (initStatement != null) {
129      initStatement.accept(visitor);
130    }
131    conditionStatement.accept(visitor);
132    if (postStatement != null) {
133      postStatement.accept(visitor);
134    }
135    block.accept(visitor);
136  }
137
138  @Override
139  protected void replaceElement(GoloElement original, GoloElement newElement) {
140    if (Objects.equals(initStatement, original)) {
141      init(newElement);
142    } else if (Objects.equals(conditionStatement, original)) {
143      condition(newElement);
144    } else if (Objects.equals(postStatement, original)) {
145      post(newElement);
146    } else if (Objects.equals(block, original)) {
147      block((Block) newElement);
148    } else {
149      throw cantReplace(original, newElement);
150    }
151  }
152}