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; 013 014public final class ConditionalBranching extends GoloStatement implements Scope { 015 016 private ExpressionStatement condition; 017 private Block trueBlock; 018 private ConditionalBranching elseConditionalBranching; 019 private Block falseBlock; 020 021 ConditionalBranching() { 022 super(); 023 } 024 025 public ConditionalBranching condition(Object cond) { 026 if (cond == null) { 027 setCondition(Builders.constant(false)); 028 } else { 029 setCondition((ExpressionStatement) cond); 030 } 031 return this; 032 } 033 034 public ConditionalBranching whenTrue(Object block) { 035 setTrueBlock(Builders.toBlock(block)); 036 return this; 037 } 038 039 public ConditionalBranching whenFalse(Object block) { 040 setFalseBlock(block == null ? null : Builders.toBlock(block)); 041 return this; 042 } 043 044 public ConditionalBranching elseBranch(Object elseBranch) { 045 this.elseConditionalBranching = (ConditionalBranching) elseBranch; 046 makeParentOf(elseConditionalBranching); 047 return this; 048 } 049 050 public ConditionalBranching otherwise(Object alternative) { 051 if (alternative instanceof ConditionalBranching) { 052 return elseBranch((ConditionalBranching) alternative); 053 } 054 return whenFalse(alternative); 055 } 056 057 @Override 058 public ConditionalBranching ofAST(GoloASTNode node) { 059 super.ofAST(node); 060 return this; 061 } 062 063 @Override 064 public void relink(ReferenceTable table) { 065 trueBlock.relink(table); 066 if (falseBlock != null) { 067 falseBlock.relink(table); 068 } 069 if (elseConditionalBranching != null) { 070 elseConditionalBranching.relink(table); 071 } 072 } 073 074 @Override 075 public void relinkTopLevel(ReferenceTable table) { 076 trueBlock.relinkTopLevel(table); 077 if (falseBlock != null) { 078 falseBlock.relinkTopLevel(table); 079 } 080 if (elseConditionalBranching != null) { 081 elseConditionalBranching.relinkTopLevel(table); 082 } 083 } 084 085 public ExpressionStatement getCondition() { 086 return condition; 087 } 088 089 public void setCondition(ExpressionStatement condition) { 090 this.condition = condition; 091 makeParentOf(condition); 092 } 093 094 public Block getTrueBlock() { 095 return trueBlock; 096 } 097 098 public void setTrueBlock(Block block) { 099 this.trueBlock = block; 100 makeParentOf(block); 101 } 102 103 public Block getFalseBlock() { 104 return falseBlock; 105 } 106 107 public void setFalseBlock(Block block) { 108 this.falseBlock = block; 109 if (block != null) { 110 makeParentOf(block); 111 } 112 } 113 114 public boolean hasFalseBlock() { 115 return falseBlock != null; 116 } 117 118 public ConditionalBranching getElseConditionalBranching() { 119 return elseConditionalBranching; 120 } 121 122 public void setElseConditionalBranching(ConditionalBranching elseBranch) { 123 this.elseConditionalBranching = elseBranch; 124 makeParentOf(elseBranch); 125 } 126 127 public boolean hasElseConditionalBranching() { 128 return elseConditionalBranching != null; 129 } 130 131 public boolean returnsFromBothBranches() { 132 if (hasFalseBlock()) { 133 return trueBlock.hasReturn() && falseBlock.hasReturn(); 134 } else if (hasElseConditionalBranching()) { 135 return trueBlock.hasReturn() && elseConditionalBranching.returnsFromBothBranches(); 136 } else { 137 return false; 138 } 139 } 140 141 @Override 142 public String toString() { 143 return String.format("if %s %s%s", condition, trueBlock, 144 hasFalseBlock() ? " else " + falseBlock.toString() 145 : hasElseConditionalBranching() ? " else " + elseConditionalBranching.toString() 146 : ""); 147 } 148 149 @Override 150 public void accept(GoloIrVisitor visitor) { 151 visitor.visitConditionalBranching(this); 152 } 153 154 @Override 155 public void walk(GoloIrVisitor visitor) { 156 condition.accept(visitor); 157 trueBlock.accept(visitor); 158 if (falseBlock != null) { 159 falseBlock.accept(visitor); 160 } 161 if (elseConditionalBranching != null) { 162 elseConditionalBranching.accept(visitor); 163 } 164 } 165 166 @Override 167 protected void replaceElement(GoloElement original, GoloElement newElement) { 168 if (condition == original && newElement instanceof ExpressionStatement) { 169 condition(newElement); 170 } else if (elseConditionalBranching == original && newElement instanceof ConditionalBranching) { 171 elseBranch(newElement); 172 } else if (trueBlock == original) { 173 whenTrue(newElement); 174 } else if (falseBlock == original) { 175 whenFalse(newElement); 176 } else { 177 throw cantReplace(original, newElement); 178 } 179 } 180 181}