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 }