5 // Chris J Breisch (cjbreisch@altavista.net)
6 // Dennis Hayes (dennish@raytek.com)
8 // (C) 2002 Chris J Breisch
11 * Copyright (c) 2002-2003 Mainsoft Corporation.
12 * Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 * DEALINGS IN THE SOFTWARE.
33 * This class allows to execute loop statement of VisualBasic .NET
37 using System.Collections;
38 using System.ComponentModel;
40 namespace Microsoft.VisualBasic.CompilerServices
42 [StandardModule, EditorBrowsable(EditorBrowsableState.Never)]
43 sealed public class FlowControl {
44 private FlowControl () {}
46 private sealed /*static (final)in mainsoft java code*/ class ObjectFor {
47 public object Counter;
51 public object StepValue;
53 public bool PositiveStep;
59 * This method check if the loop can continued.
60 * if the StepValue is positive it check that count is smaller than the limit.
61 * if the StepValue is negative it check that count is bigger than the limit.
65 * @return boolean True of the for next loop can continue and false otherwise.
67 public static bool ForNextCheckR4(float count, float limit, float StepValue) {
68 bool positiveStep = StepValue > 0.0F;
70 return count <= limit;
72 return count >= limit;
76 * This method check if the loop can continued.
77 * if the StepValue is positive it check that count is smaller than the limit.
78 * if the StepValue is negative it check that count is bigger than the limit.
82 * @return boolean True of the for next loop can continue and false otherwise.
84 public static bool ForNextCheckR8(double count, double limit, double StepValue) {
85 bool positiveStep = StepValue > 0.0;
87 return count <= limit;
89 return count >= limit;
93 * This method check if the loop can continued.
94 * if the StepValue is positive it check that count is smaller than the limit.
95 * if the StepValue is negative it check that count is bigger than the limit.
99 * @return boolean True of the for next loop can continue and false otherwise.
101 public static bool ForNextCheckDec(Decimal count, Decimal limit, Decimal StepValue) {
102 bool positiveStep = StepValue.CompareTo(Decimal.Zero) > 0;
104 return (count.CompareTo(limit) <= 0);
106 return (limit.CompareTo(count) <= 0);
110 * This method method updates the LoopFor reference and the Counter reference
111 * object according to the given params and returns if this loop can continue.
112 * @param Counter this loop counter value
113 * @param Start this loop start value
114 * @param Limit this loop limitation value
115 * @param StepValue this loop step value
116 * @param lfr the LoopFor reference object
117 * @param cr the Counter object reference
118 * @return boolean is the returned LoopFor object can continue.
120 public static bool ForLoopInitObj(
125 ref System.Object lfr,
126 ref System.Object cr) {
129 throw new ArgumentException("Argument_InvalidNullValue1 " + " Start");
132 throw new ArgumentException("Argument_InvalidNullValue1 " + " Limit");
134 if (StepValue == null) {
135 throw new ArgumentException("Argument_InvalidNullValue1 " + " Step");
137 //gets the type of all the given parameters
138 Type startType = Start.GetType();
139 Type limitType = Limit.GetType();
140 Type stepType = StepValue.GetType();
142 //gets the widest common type code
144 TypeCode commonTypeCode = ObjectType.GetWidestType(Start, Limit, false);
145 commonTypeCode = ObjectType.GetWidestType(StepValue, commonTypeCode);
146 if (commonTypeCode == TypeCode.String) {
147 commonTypeCode = TypeCode.Double;
149 if (commonTypeCode == TypeCode.Object) {
151 //throw new ArgumentException(
152 // Utils.GetResourceString(
153 // "ForLoop_CommonType3",
154 // Utils.VBFriendlyName(startType),
155 // Utils.VBFriendlyName(limitType),
156 // Utils.VBFriendlyName(StepValue)));
157 throw new ArgumentException("ForLoop_CommonType3 startType limitType StepValue");
160 ObjectFor objectFor = new ObjectFor();
161 TypeCode startTypeCode = Type.GetTypeCode(startType);
162 TypeCode limitTypeCode = Type.GetTypeCode(limitType);
163 TypeCode stepTypeCode = Type.GetTypeCode(stepType);
164 Type enumType = null;
166 bool isStartTypeValidEnum = (startTypeCode == commonTypeCode) && (startType.IsEnum);
167 bool isLimitTypeValidEnum = (limitTypeCode == commonTypeCode) && (limitType.IsEnum);
168 bool isStepTypeValidEnum = (stepTypeCode == commonTypeCode) && (stepType.IsEnum);
170 bool isStartAndStepTypeEqual = (startType == stepType);
171 bool isStartAndLimitTypeEqual = (startType == limitType);
172 // bool isStepAndLimitTypeEqual = (stepType == limitType);
174 //the For loop has enum type in the following case
175 //1. step is enum and it's type code equal to commonTypeCode and start and
176 // limit don't meet this condition.
177 //2. step and start are enum and their type code equal to commonTypeCode and
178 // their types are equal. limit doesn't meet this condition about been enum
179 // or about been equal to commonTypeCode.
180 //3. step and limit are enum and their type code equal to commonTypeCode and
181 // their types are equal. start doesn't meet this condition about been enum
182 // or about been equal to commonTypeCode.
183 //4. step and limit and start are enum and their type code equal to commonTypeCode and
184 // their types are equal.
185 //5. start is enum and it's type code equal to commonTypeCode .step and
186 // limit don't meet this condition.
187 //6. limit is enum and it's type code equal to commonTypeCode .step and
188 // start don't meet this condition.
189 //7.start and limit are enum and their type code equal to commonTypeCode and
190 // their types are equal. step doesn't meet this condition about been enum
191 // or about been equal to commonTypeCode.
194 if (isStartTypeValidEnum && isLimitTypeValidEnum && isStepTypeValidEnum
195 && isStartAndStepTypeEqual && isStartAndLimitTypeEqual)
196 enumType = startType;
197 else if (isStartTypeValidEnum && isStepTypeValidEnum && isStartAndStepTypeEqual)
198 enumType = startType;
199 else if (isStartTypeValidEnum && isStepTypeValidEnum && isStartAndStepTypeEqual)
200 enumType = startType;
201 else if (isStartTypeValidEnum && isLimitTypeValidEnum && isStartAndLimitTypeEqual)
202 enumType = startType;
203 else if (isStartTypeValidEnum && !isLimitTypeValidEnum && !isStepTypeValidEnum)
204 enumType = startType;
205 else if (!isStartTypeValidEnum && isLimitTypeValidEnum && !isStepTypeValidEnum)
206 enumType = limitType;
207 else if (!isStartTypeValidEnum && !isLimitTypeValidEnum && isStepTypeValidEnum)
210 objectFor.EnumType = enumType;
212 //set the counter field of objectFor with Start value transleted to
213 // the widest common type code
214 objectFor.Counter = convertType(Start, commonTypeCode,"Start");
215 //set the Limit field of objectFor with Limit value transleted to
216 // the widest common type code
217 objectFor.Limit = convertType(Limit, commonTypeCode,"Limit");
218 //set the StepValue field of objectFor with StepValue value transleted to
219 // the widest common type code
220 objectFor.StepValue = convertType(StepValue, commonTypeCode,"Step");
221 //local is the value of zero in the widest common type code
223 object local = ObjectType.CTypeHelper(0, commonTypeCode);
225 IComparable iComparable = (IComparable)objectFor.StepValue;
226 objectFor.PositiveStep = iComparable.CompareTo(local) >= 0;
228 // sets the loop for reference
231 //sets the counter reference
232 if (objectFor.EnumType != null) {
233 cr = Enum.ToObject(objectFor.EnumType, objectFor.Counter);
236 cr = objectFor.Counter;
238 return CheckContinueLoop(objectFor);
241 private static object convertType(object original, TypeCode typeCode, string fieldName) {
243 return ObjectType.CTypeHelper(original, typeCode);
245 catch /*(Exception e)*/ {
246 throw new ArgumentException("ForLoop_ConvertToType3 " + fieldName);
250 public static bool ForNextCheckObj(object Counter, object LoopObj,
251 ref System.Object CounterResult) {// throws java.lang.Exception
252 TypeCode generalTypeCode = 0;
254 if (LoopObj == null) {
255 //TODO: use resource for the correct execption.
256 throw new Exception("VB error message #92 ForNextCheckObj LoopObj cannot be null");
257 //throw ExceptionUtils.VbMakeException(92);//correct java version
259 if (Counter == null) {
260 throw new NullReferenceException("Argument_InvalidNullValue1 " + " Counter");
262 //throw new NullReferenceException(
263 // Utils.GetResourceString(
264 // "Argument_InvalidNullValue1",
267 ObjectFor objectFor = (ObjectFor) LoopObj;
269 IConvertible iConvertible_counter = (IConvertible)Counter;
270 IConvertible iConvertible_step = (IConvertible) objectFor.StepValue;
272 TypeCode counterTypeCode = iConvertible_counter.GetTypeCode();
273 TypeCode stepTypeCode = iConvertible_step.GetTypeCode();
275 if (counterTypeCode == stepTypeCode && counterTypeCode != TypeCode.String) {
276 generalTypeCode = counterTypeCode;
279 generalTypeCode = ObjectType.GetWidestType(counterTypeCode, stepTypeCode);
280 if (generalTypeCode == TypeCode.String) {
281 generalTypeCode = TypeCode.Double;
283 Counter = convertType(Counter, generalTypeCode,"Start");
284 objectFor.Limit = convertType(objectFor.Limit, generalTypeCode,"Limit");
285 objectFor.StepValue = convertType(objectFor.StepValue, generalTypeCode,"Step");
287 //changes the counter field to be the sum of step and counter
288 objectFor.Counter = ObjectType.AddObj(Counter, objectFor.StepValue);
289 IConvertible iConvertible_objectCounter = (IConvertible)objectFor.Counter;
290 TypeCode objectCounterTypeCode = iConvertible_objectCounter.GetTypeCode();
292 //setting the counter in counter reference.
293 //if the for is enum type change counter to enum.
294 if (objectFor.EnumType != null) {
295 CounterResult = Enum.ToObject(objectFor.EnumType, objectFor.Counter);
298 CounterResult = objectFor.Counter;
301 //if the counter after the change didn't change it's type return true if
302 // the for object can continue loop and false otherwise.
303 //if the counter changed it's type change all for object fields to counter
304 //current type and return false.
305 if (objectCounterTypeCode == generalTypeCode) {
306 return CheckContinueLoop(objectFor);
309 objectFor.Limit = ObjectType.CTypeHelper(objectFor.Limit, objectCounterTypeCode);
311 objectFor.StepValue =
312 ObjectType.CTypeHelper(objectFor.StepValue, objectCounterTypeCode);
318 * This method returns IEnumertator for a given array
319 * @param ary the given array
320 * @return IEnumerator the array's Enumerator
322 public static IEnumerator ForEachInArr(Array ary) {// throws java.lang.Exception
323 IEnumerator iEnumerator = (IEnumerator)ary;//is ArrayStaticWrapper.GetEnumerator(ary); in java code.
324 if (iEnumerator != null)
326 throw ExceptionUtils.VbMakeException(92);
330 * This method gets IEnumerator for a given object that implements IEnumerable
331 * @param obj the object that implements IEnumerable
332 * @return IEnumerator the object's IEnumerator.
334 public static IEnumerator ForEachInObj(object obj) {// throws java.lang.Exception
336 throw ExceptionUtils.VbMakeException(91);
338 IEnumerable iEnumerable = (IEnumerable)obj;
339 if (iEnumerable != null) {
340 IEnumerator iEnumerator = iEnumerable.GetEnumerator();
341 if (iEnumerator != null)
344 string s = obj.GetType().ToString();
345 ExceptionUtils.ThrowException1(100, s);
350 * This method set the next value of teh Enumerator in the reference.
351 * if there isn't next value , null is been set in the referece.
354 * @return boolean returns the value of enumerator.MoveNext().
356 public static bool ForEachNextObj(ref System.Object obj, IEnumerator enumerator) {
357 if (enumerator.MoveNext()) {
358 obj = enumerator.Current;
366 * This method check if the loop can continued.
367 * if the step is positive it check that the counter is smaller than the limit.
368 * if the step is negative it check that the counter is bigger than the limit.
372 private static bool CheckContinueLoop(ObjectFor LoopFor) {
374 //throw new NotImplementedException("MSVB.Compilerservices.flowcontrol needs help");
375 IComparable iComparable = (IComparable)LoopFor.Counter;
377 if (iComparable != null) {
378 int i = iComparable.CompareTo(LoopFor.Limit);
379 if (LoopFor.PositiveStep)
384 throw new ArgumentException("Argument_IComparable2 loop control variable"); // + Utils.VBFriendlyName(LoopFor.Counter)));
385 //TODO: verify this and the above are the same and remove.
386 //throw new ArgumentException(Utils.GetResourceString(
387 // "Argument_IComparable2", "loop control variable",
388 // Utils.VBFriendlyName(LoopFor.Counter)));
392 * This method throws exception if the input is Valuetype
393 * @param obj the object that need to be checked
395 public static void CheckForSyncLockOnValueType(object obj) {
397 //throw new NotImplementedException("MSVB.Compilerservices.flowcontrol needs help");
398 if (obj != null && obj.GetType().IsValueType)
399 throw new ArgumentException(Utils.GetResourceString("SyncLockRequiresReferenceType1 "));
400 //TODO: verify this and the above are the same and remove.
401 //if (obj != null && ObjectStaticWrapper.GetType(obj).get_IsValueType())
402 // throw new ArgumentException(Utils.GetResourceString(
403 // "SyncLockRequiresReferenceType1",Utils.VBFriendlyName(obj)));