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 org.overturetool.vdmj.definitions.MultiBindListDefinition;
27  import org.overturetool.vdmj.expressions.Expression;
28  import org.overturetool.vdmj.lex.LexLocation;
29  import org.overturetool.vdmj.patterns.MultipleBind;
30  import org.overturetool.vdmj.patterns.Pattern;
31  import org.overturetool.vdmj.pog.LetBeExistsObligation;
32  import org.overturetool.vdmj.pog.POContextStack;
33  import org.overturetool.vdmj.pog.ProofObligationList;
34  import org.overturetool.vdmj.runtime.Context;
35  import org.overturetool.vdmj.runtime.ValueException;
36  import org.overturetool.vdmj.typechecker.Environment;
37  import org.overturetool.vdmj.typechecker.FlatCheckedEnvironment;
38  import org.overturetool.vdmj.typechecker.NameScope;
39  import org.overturetool.vdmj.types.BooleanType;
40  import org.overturetool.vdmj.types.Type;
41  import org.overturetool.vdmj.types.TypeSet;
42  import org.overturetool.vdmj.values.NameValuePair;
43  import org.overturetool.vdmj.values.NameValuePairList;
44  import org.overturetool.vdmj.values.Quantifier;
45  import org.overturetool.vdmj.values.QuantifierList;
46  import org.overturetool.vdmj.values.Value;
47  import org.overturetool.vdmj.values.ValueList;
48  
49  public class LetBeStStatement extends Statement
50  {
51  	private static final long serialVersionUID = 1L;
52  	public final MultipleBind bind;
53  	public final Expression suchThat;
54  	public final Statement statement;
55  	private MultiBindListDefinition def = null;
56  
57  	public LetBeStStatement(LexLocation location,
58  		MultipleBind bind, Expression suchThat, Statement statement)
59  	{
60  		super(location);
61  		this.bind = bind;
62  		this.suchThat = suchThat;
63  		this.statement = statement;
64  	}
65  
66  	@Override
67  	public String toString()
68  	{
69  		return "let " + bind +
70  			(suchThat == null ? "" : " be st " + suchThat) + " in " + statement;
71  	}
72  
73  	@Override
74  	public String kind()
75  	{
76  		return "let be st";
77  	}
78  
79  	@Override
80  	public Type typeCheck(Environment base, NameScope scope)
81  	{
82  		def = new MultiBindListDefinition(location, bind.getMultipleBindList());
83  		def.typeCheck(base, scope);
84  		Environment local = new FlatCheckedEnvironment(def, base);
85  
86  		if (suchThat != null && !suchThat.typeCheck(local, null, scope).isType(BooleanType.class))
87  		{
88  			report(3225, "Such that clause is not boolean");
89  		}
90  
91  		Type r = statement.typeCheck(local, scope);
92  		local.unusedCheck();
93  		return r;
94  	}
95  
96  	@Override
97  	public TypeSet exitCheck()
98  	{
99  		return statement.exitCheck();
100 	}
101 
102 	@Override
103 	public Statement findStatement(int lineno)
104 	{
105 		Statement found = super.findStatement(lineno);
106 		if (found != null) return found;
107 		return statement.findStatement(lineno);
108 	}
109 
110 	@Override
111 	public Expression findExpression(int lineno)
112 	{
113 		Expression found = suchThat.findExpression(lineno);
114 		if (found != null) return found;
115 		return statement.findExpression(lineno);
116 	}
117 
118 	@Override
119 	public Value eval(Context ctxt)
120 	{
121 		breakpoint.check(location, ctxt);
122 		QuantifierList quantifiers = new QuantifierList();
123 
124 		for (MultipleBind mb: def.bindings)
125 		{
126 			ValueList bvals = mb.getBindValues(ctxt);
127 
128 			for (Pattern p: mb.plist)
129 			{
130 				Quantifier q = new Quantifier(p, bvals);
131 				quantifiers.add(q);
132 			}
133 		}
134 
135 		quantifiers.init();
136 
137 		try
138 		{
139 			while (quantifiers.hasNext(ctxt))
140 			{
141 				Context evalContext = new Context(location, "let be st statement", ctxt);
142 				NameValuePairList nvpl = quantifiers.next();
143 				boolean matches = true;
144 
145 				for (NameValuePair nvp: nvpl)
146 				{
147 					Value v = evalContext.get(nvp.name);
148 
149 					if (v == null)
150 					{
151 						evalContext.put(nvp.name, nvp.value);
152 					}
153 					else
154 					{
155 						if (!v.equals(nvp.value))
156 						{
157 							matches = false;
158 							break;	// This quantifier set does not match
159 						}
160 					}
161 				}
162 
163 				if (matches &&
164 					(suchThat == null || suchThat.eval(evalContext).boolValue(ctxt)))
165 				{
166 					return statement.eval(evalContext);
167 				}
168 			}
169 		}
170         catch (ValueException e)
171         {
172         	abort(e);
173         }
174 
175 		return abort(4040, "Let be st found no applicable bindings", ctxt);
176 	}
177 
178 	@Override
179 	public ProofObligationList getProofObligations(POContextStack ctxt)
180 	{
181 		ProofObligationList obligations = new ProofObligationList();
182 		obligations.add(new LetBeExistsObligation(this, ctxt));
183 		obligations.addAll(bind.getProofObligations(ctxt));
184 
185 		if (suchThat != null)
186 		{
187 			obligations.addAll(suchThat.getProofObligations(ctxt));
188 		}
189 
190 		obligations.addAll(statement.getProofObligations(ctxt));
191 
192 		return obligations;
193 	}
194 }