View Javadoc

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 }