1 /******************************************************************************** 2 * 3 * Copyright (c) 2008 Fujitsu Services Ltd. 4 * 5 * Author: Nick Battle 6 * 7 * This file is part of VDMJ. 8 * 9 * VDMJ is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation, either version 3 of the License, or 12 * (at your option) any later version. 13 * 14 * VDMJ is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with VDMJ. If not, see <http://www.gnu.org/licenses/>. 21 * 22 ******************************************************************************/ 23 24 package org.overturetool.vdmj.statements; 25 26 import java.util.List; 27 28 import org.overturetool.vdmj.expressions.Expression; 29 import org.overturetool.vdmj.lex.LexLocation; 30 import org.overturetool.vdmj.pog.POContextStack; 31 import org.overturetool.vdmj.pog.ProofObligationList; 32 import org.overturetool.vdmj.runtime.Context; 33 import org.overturetool.vdmj.runtime.ValueException; 34 import org.overturetool.vdmj.typechecker.Environment; 35 import org.overturetool.vdmj.typechecker.NameScope; 36 import org.overturetool.vdmj.types.BooleanType; 37 import org.overturetool.vdmj.types.Type; 38 import org.overturetool.vdmj.types.TypeSet; 39 import org.overturetool.vdmj.types.VoidType; 40 import org.overturetool.vdmj.values.Value; 41 import org.overturetool.vdmj.values.VoidValue; 42 43 44 public class IfStatement extends Statement 45 { 46 private static final long serialVersionUID = 1L; 47 public final Expression ifExp; 48 public final Statement thenStmt; 49 public final List<ElseIfStatement> elseList; 50 public final Statement elseStmt; 51 52 public IfStatement(LexLocation location, 53 Expression ifExp, Statement thenStmt, 54 List<ElseIfStatement> elseList, Statement elseStmt) 55 { 56 super(location); 57 this.ifExp = ifExp; 58 this.thenStmt = thenStmt; 59 this.elseList = elseList; 60 this.elseStmt = elseStmt; 61 } 62 63 @Override 64 public String toString() 65 { 66 StringBuilder sb = new StringBuilder(); 67 sb.append("if " + ifExp + "\nthen\n" + thenStmt); 68 69 for (ElseIfStatement s: elseList) 70 { 71 sb.append(s.toString()); 72 } 73 74 if (elseStmt != null) 75 { 76 sb.append("else\n"); 77 sb.append(elseStmt.toString()); 78 } 79 80 return sb.toString(); 81 } 82 83 @Override 84 public String kind() 85 { 86 return "if"; 87 } 88 89 @Override 90 public Type typeCheck(Environment env, NameScope scope) 91 { 92 Type test = ifExp.typeCheck(env, null, scope); 93 94 if (!test.isType(BooleanType.class)) 95 { 96 ifExp.report(3224, "If expression is not boolean"); 97 } 98 99 TypeSet rtypes = new TypeSet(); 100 rtypes.add(thenStmt.typeCheck(env, scope)); 101 102 if (elseList != null) 103 { 104 for (ElseIfStatement stmt: elseList) 105 { 106 rtypes.add(stmt.typeCheck(env, scope)); 107 } 108 } 109 110 if (elseStmt != null) 111 { 112 rtypes.add(elseStmt.typeCheck(env, scope)); 113 } 114 else 115 { 116 rtypes.add(new VoidType(location)); 117 } 118 119 return rtypes.getType(location); 120 } 121 122 @Override 123 public TypeSet exitCheck() 124 { 125 TypeSet types = new TypeSet(); 126 types.addAll(thenStmt.exitCheck()); 127 128 for (ElseIfStatement stmt: elseList) 129 { 130 types.addAll(stmt.exitCheck()); 131 } 132 133 if (elseStmt != null) 134 { 135 types.addAll(elseStmt.exitCheck()); 136 } 137 138 return types; 139 } 140 141 @Override 142 public Statement findStatement(int lineno) 143 { 144 Statement found = super.findStatement(lineno); 145 if (found != null) return found; 146 found = thenStmt.findStatement(lineno); 147 if (found != null) return found; 148 149 for (ElseIfStatement stmt: elseList) 150 { 151 found = stmt.findStatement(lineno); 152 if (found != null) return found; 153 } 154 155 if (elseStmt != null) 156 { 157 found = elseStmt.findStatement(lineno); 158 } 159 160 return found; 161 } 162 163 @Override 164 public Expression findExpression(int lineno) 165 { 166 Expression found = thenStmt.findExpression(lineno); 167 if (found != null) return found; 168 169 for (ElseIfStatement stmt: elseList) 170 { 171 found = stmt.findExpression(lineno); 172 if (found != null) return found; 173 } 174 175 if (elseStmt != null) 176 { 177 found = elseStmt.findExpression(lineno); 178 } 179 180 return found; 181 } 182 183 @Override 184 public Value eval(Context ctxt) 185 { 186 breakpoint.check(location, ctxt); 187 188 try 189 { 190 if (ifExp.eval(ctxt).boolValue(ctxt)) 191 { 192 return thenStmt.eval(ctxt); 193 } 194 else 195 { 196 for (ElseIfStatement elseif: elseList) 197 { 198 Value r = elseif.eval(ctxt); 199 if (r != null) return r; 200 } 201 202 if (elseStmt != null) 203 { 204 return elseStmt.eval(ctxt); 205 } 206 207 return new VoidValue(); 208 } 209 } 210 catch (ValueException e) 211 { 212 return abort(e); 213 } 214 } 215 216 @Override 217 public ProofObligationList getProofObligations(POContextStack ctxt) 218 { 219 ProofObligationList obligations = ifExp.getProofObligations(ctxt); 220 obligations.addAll(thenStmt.getProofObligations(ctxt)); 221 222 for (ElseIfStatement stmt: elseList) 223 { 224 obligations.addAll(stmt.getProofObligations(ctxt)); 225 } 226 227 if (elseStmt != null) 228 { 229 obligations.addAll(elseStmt.getProofObligations(ctxt)); 230 } 231 232 return obligations; 233 } 234 }