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;
014
015import static java.util.Collections.unmodifiableList;
016import org.eclipse.golo.compiler.parser.GoloASTNode;
017
018public final class CaseStatement extends GoloStatement implements Scope, Alternatives<Block> {
019
020  private Block otherwise;
021  private final LinkedList<WhenClause<Block>> clauses = new LinkedList<>();
022
023  CaseStatement() {
024    super();
025  }
026
027  public CaseStatement when(Object cond) {
028    WhenClause<Block> clause = new WhenClause<Block>((ExpressionStatement) cond, null);
029    this.clauses.add(clause);
030    makeParentOf(clause);
031    return this;
032  }
033
034  public CaseStatement then(Object action) {
035    this.clauses.getLast().setAction((Block) action);
036    return this;
037  }
038
039  public CaseStatement otherwise(Object action) {
040    otherwise = (Block) action;
041    makeParentOf(otherwise);
042    return this;
043  }
044
045  public List<WhenClause<Block>> getClauses() {
046    return unmodifiableList(this.clauses);
047  }
048
049  public Block getOtherwise() {
050    return this.otherwise;
051  }
052
053  @Override
054  public CaseStatement ofAST(GoloASTNode n) {
055    super.ofAST(n);
056    return this;
057  }
058
059  @Override
060  public void relink(ReferenceTable table) {
061    this.getOtherwise().relink(table);
062    for (WhenClause<Block> c : getClauses()) {
063      c.action().relink(table);
064    }
065  }
066
067  @Override
068  public void relinkTopLevel(ReferenceTable table) {
069    this.getOtherwise().relinkTopLevel(table);
070    for (WhenClause<Block> c : getClauses()) {
071      c.action().relinkTopLevel(table);
072    }
073  }
074
075  @Override
076  public void accept(GoloIrVisitor visitor) {
077    visitor.visitCaseStatement(this);
078  }
079
080  @Override
081  public void walk(GoloIrVisitor visitor) {
082    for (WhenClause<Block> clause : clauses) {
083      clause.accept(visitor);
084    }
085    otherwise.accept(visitor);
086  }
087
088  @Override
089  public void replaceElement(GoloElement original, GoloElement newElement) {
090    if (!(newElement instanceof Block || newElement instanceof WhenClause)) {
091      throw cantConvert("Block or WhenClause", newElement);
092    }
093    if (otherwise.equals(original)) {
094      otherwise(newElement);
095      return;
096    }
097    if (clauses.contains(original)) {
098      @SuppressWarnings("unchecked")
099      WhenClause<Block> when = (WhenClause<Block>) newElement;
100      clauses.set(clauses.indexOf(original), when);
101      makeParentOf(when);
102      return;
103    }
104    throw doesNotContain(original);
105  }
106}