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;
39 namespace Microsoft.VisualBasic.CompilerServices
41 [Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute]
42 [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
43 sealed public class FlowControl {
44 private sealed /*static (final)in mainsoft java code*/ class ObjectFor {
45 public object Counter;
49 public object StepValue;
51 public bool PositiveStep;
57 * This method check if the loop can continued.
58 * if the StepValue is positive it check that count is smaller than the limit.
59 * if the StepValue is negative it check that count is bigger than the limit.
63 * @return boolean True of the for next loop can continue and false otherwise.
65 public static bool ForNextCheckR4(float count, float limit, float StepValue) {
66 bool positiveStep = StepValue > 0.0F;
67 bool isCountSmallThenLimit = count <= limit;
68 return positiveStep? isCountSmallThenLimit : !isCountSmallThenLimit;
72 * This method check if the loop can continued.
73 * if the StepValue is positive it check that count is smaller than the limit.
74 * if the StepValue is negative it check that count is bigger than the limit.
78 * @return boolean True of the for next loop can continue and false otherwise.
80 public static bool ForNextCheckR8(double count, double limit, double StepValue) {
81 bool positiveStep = StepValue > 0.0;
82 bool isCountSmallThenLimit = count <= limit;
83 return positiveStep? isCountSmallThenLimit : !isCountSmallThenLimit;
87 * This method check if the loop can continued.
88 * if the StepValue is positive it check that count is smaller than the limit.
89 * if the StepValue is negative it check that count is bigger than the limit.
93 * @return boolean True of the for next loop can continue and false otherwise.
95 public static bool ForNextCheckDec(Decimal count, Decimal limit, Decimal StepValue) {
96 bool positiveStep = StepValue.CompareTo(Decimal.Zero) < 0;
97 bool isCountSmallThenLimit = count.CompareTo(limit) >= 0;
98 return positiveStep? isCountSmallThenLimit : !isCountSmallThenLimit;
102 * This method method updates the LoopFor reference and the Counter reference
103 * object according to the given params and returns if this loop can continue.
104 * @param Counter this loop counter value
105 * @param Start this loop start value
106 * @param Limit this loop limitation value
107 * @param StepValue this loop step value
108 * @param lfr the LoopFor reference object
109 * @param cr the Counter object reference
110 * @return boolean is the returned LoopFor object can continue.
112 public static bool ForLoopInitObj(
117 ref System.Object lfr,
118 ref System.Object cr) {
120 object CounterResult = cr;
123 throw new ArgumentException("Argument_InvalidNullValue1 " + " Start");
126 throw new ArgumentException("Argument_InvalidNullValue1 " + " Limit");
128 if (StepValue == null) {
129 throw new ArgumentException("Argument_InvalidNullValue1 " + " Step");
131 //gets the type of all the given parameters
132 Type startType = Start.GetType();
133 Type limitType = Limit.GetType();
134 Type stepType = StepValue.GetType();
136 //gets the widest common type code
138 TypeCode commonTypeCode = ObjectType.GetWidestType(Start, Limit, false);
139 commonTypeCode = ObjectType.GetWidestType(StepValue, commonTypeCode);
140 if (commonTypeCode == TypeCode.String) {
141 commonTypeCode = TypeCode.Double;
143 if (commonTypeCode == TypeCode.Object) {
145 //throw new ArgumentException(
146 // Utils.GetResourceString(
147 // "ForLoop_CommonType3",
148 // Utils.VBFriendlyName(startType),
149 // Utils.VBFriendlyName(limitType),
150 // Utils.VBFriendlyName(StepValue)));
151 throw new ArgumentException("ForLoop_CommonType3 startType limitType StepValue");
154 ObjectFor objectFor = new ObjectFor();
155 TypeCode startTypeCode = Type.GetTypeCode(startType);
156 TypeCode limitTypeCode = Type.GetTypeCode(limitType);
157 TypeCode stepTypeCode = Type.GetTypeCode(stepType);
158 Type enumType = null;
160 bool isStartTypeValidEnum = (startTypeCode == commonTypeCode) && (startType.IsEnum);
161 bool isLimitTypeValidEnum = (limitTypeCode == commonTypeCode) && (limitType.IsEnum);
162 bool isStepTypeValidEnum = (stepTypeCode == commonTypeCode) && (stepType.IsEnum);
164 bool isStartAndStepTypeEqual = (startType == stepType);
165 bool isStartAndLimitTypeEqual = (startType == limitType);
166 bool isStepAndLimitTypeEqual = (stepType == limitType);
168 //the For loop has enum type in the following case
169 //1. step is enum and it's type code equal to commonTypeCode and start and
170 // limit don't meet this condition.
171 //2. step and start are enum and their type code equal to commonTypeCode and
172 // their types are equal. limit doesn't meet this condition about been enum
173 // or about been equal to commonTypeCode.
174 //3. step and limit are enum and their type code equal to commonTypeCode and
175 // their types are equal. start doesn't meet this condition about been enum
176 // or about been equal to commonTypeCode.
177 //4. step and limit and start are enum and their type code equal to commonTypeCode and
178 // their types are equal.
179 //5. start is enum and it's type code equal to commonTypeCode .step and
180 // limit don't meet this condition.
181 //6. limit is enum and it's type code equal to commonTypeCode .step and
182 // start don't meet this condition.
183 //7.start and limit are enum and their type code equal to commonTypeCode and
184 // their types are equal. step doesn't meet this condition about been enum
185 // or about been equal to commonTypeCode.
188 if (isStartTypeValidEnum && isLimitTypeValidEnum && isStepTypeValidEnum
189 && isStartAndStepTypeEqual && isStartAndLimitTypeEqual)
190 enumType = startType;
191 else if (isStartTypeValidEnum && isStepTypeValidEnum && isStartAndStepTypeEqual)
192 enumType = startType;
193 else if (isStartTypeValidEnum && isStepTypeValidEnum && isStartAndStepTypeEqual)
194 enumType = startType;
195 else if (isStartTypeValidEnum && isLimitTypeValidEnum && isStartAndLimitTypeEqual)
196 enumType = startType;
197 else if (isStartTypeValidEnum && !isLimitTypeValidEnum && !isStepTypeValidEnum)
198 enumType = startType;
199 else if (!isStartTypeValidEnum && isLimitTypeValidEnum && !isStepTypeValidEnum)
200 enumType = limitType;
201 else if (!isStartTypeValidEnum && !isLimitTypeValidEnum && isStepTypeValidEnum)
204 objectFor.EnumType = enumType;
206 //set the counter field of objectFor with Start value transleted to
207 // the widest common type code
208 objectFor.Counter = convertType(Start, commonTypeCode,"Start");
209 //set the Limit field of objectFor with Limit value transleted to
210 // the widest common type code
211 objectFor.Limit = convertType(Limit, commonTypeCode,"Limit");
212 //set the StepValue field of objectFor with StepValue value transleted to
213 // the widest common type code
214 objectFor.StepValue = convertType(StepValue, commonTypeCode,"Step");
215 //local is the value of zero in the widest common type code
217 object local = ObjectType.CTypeHelper(0, commonTypeCode);
219 IComparable iComparable = (IComparable)objectFor.StepValue;
220 objectFor.PositiveStep = iComparable.CompareTo(local) >= 0;
222 // sets the loop for reference
225 //sets the counter reference
226 if (objectFor.EnumType != null) {
227 cr = Enum.ToObject(objectFor.EnumType, objectFor.Counter);
230 cr = objectFor.Counter;
232 return CheckContinueLoop(objectFor);
235 private static object convertType(object original, TypeCode typeCode, string fieldName) {
237 return ObjectType.CTypeHelper(original, typeCode);
239 catch /*(Exception e)*/ {
240 throw new ArgumentException("ForLoop_ConvertToType3 " + fieldName);
244 public static bool ForNextCheckObj(object Counter, object LoopObj,
245 ref System.Object CounterResult) {// throws java.lang.Exception
246 TypeCode generalTypeCode = 0;
248 if (LoopObj == null) {
249 //TODO: use resource for the correct execption.
250 throw new Exception("VB error message #92 ForNextCheckObj LoopObj cannot be null");
251 //throw ExceptionUtils.VbMakeException(92);//correct java version
253 if (Counter == null) {
254 throw new NullReferenceException("Argument_InvalidNullValue1 " + " Counter");
256 //throw new NullReferenceException(
257 // Utils.GetResourceString(
258 // "Argument_InvalidNullValue1",
261 ObjectFor objectFor = (ObjectFor) LoopObj;
263 IConvertible iConvertible_counter = (IConvertible)Counter;
264 IConvertible iConvertible_step = (IConvertible) objectFor.StepValue;
266 TypeCode counterTypeCode = iConvertible_counter.GetTypeCode();
267 TypeCode stepTypeCode = iConvertible_step.GetTypeCode();
269 if (counterTypeCode == stepTypeCode && counterTypeCode != TypeCode.String) {
270 generalTypeCode = counterTypeCode;
273 generalTypeCode = ObjectType.GetWidestType(counterTypeCode, stepTypeCode);
274 if (generalTypeCode == TypeCode.String) {
275 generalTypeCode = TypeCode.Double;
277 Counter = convertType(Counter, generalTypeCode,"Start");
278 objectFor.Limit = convertType(objectFor.Limit, generalTypeCode,"Limit");
279 objectFor.StepValue = convertType(objectFor.StepValue, generalTypeCode,"Step");
281 //changes the counter field to be the sum of step and counter
282 objectFor.Counter = ObjectType.AddObj(Counter, objectFor.StepValue);
283 IConvertible iConvertible_objectCounter = (IConvertible)objectFor.Counter;
284 TypeCode objectCounterTypeCode = iConvertible_objectCounter.GetTypeCode();
286 //setting the counter in counter reference.
287 //if the for is enum type change counter to enum.
288 if (objectFor.EnumType != null) {
289 CounterResult = Enum.ToObject(objectFor.EnumType, objectFor.Counter);
292 CounterResult = objectFor.Counter;
295 //if the counter after the change didn't change it's type return true if
296 // the for object can continue loop and false otherwise.
297 //if the counter changed it's type change all for object fields to counter
298 //current type and return false.
299 if (objectCounterTypeCode == generalTypeCode) {
300 return CheckContinueLoop(objectFor);
303 objectFor.Limit = ObjectType.CTypeHelper(objectFor.Limit, objectCounterTypeCode);
305 objectFor.StepValue =
306 ObjectType.CTypeHelper(objectFor.StepValue, objectCounterTypeCode);
312 * This method returns IEnumertator for a given array
313 * @param ary the given array
314 * @return IEnumerator the array's Enumerator
316 public static IEnumerator ForEachInArr(Array ary) {// throws java.lang.Exception
317 IEnumerator iEnumerator = (IEnumerator)ary;//is ArrayStaticWrapper.GetEnumerator(ary); in java code.
318 if (iEnumerator != null)
320 throw ExceptionUtils.VbMakeException(92);
324 * This method gets IEnumerator for a given object that implements IEnumerable
325 * @param obj the object that implements IEnumerable
326 * @return IEnumerator the object's IEnumerator.
328 public static IEnumerator ForEachInObj(object obj) {// throws java.lang.Exception
330 throw ExceptionUtils.VbMakeException(91);
332 IEnumerable iEnumerable = (IEnumerable)obj;
333 if (iEnumerable != null) {
334 IEnumerator iEnumerator = iEnumerable.GetEnumerator();
335 if (iEnumerator != null)
338 string s = obj.GetType().ToString();
339 ExceptionUtils.ThrowException1(100, s);
344 * This method set the next value of teh Enumerator in the reference.
345 * if there isn't next value , null is been set in the referece.
348 * @return boolean returns the value of enumerator.MoveNext().
350 public static bool ForEachNextObj(ref System.Object obj, IEnumerator enumerator) {
351 if (enumerator.MoveNext()) {
352 obj = enumerator.Current;
360 * This method check if the loop can continued.
361 * if the step is positive it check that the counter is smaller than the limit.
362 * if the step is negative it check that the counter is bigger than the limit.
366 private static bool CheckContinueLoop(ObjectFor LoopFor) {
368 //throw new NotImplementedException("MSVB.Compilerservices.flowcontrol needs help");
369 IComparable iComparable = (IComparable)LoopFor.Counter;
371 if (iComparable != null) {
372 int i = iComparable.CompareTo(LoopFor.Limit);
373 bool isCountSmallThenLimit = i<=0;
374 return LoopFor.PositiveStep ? isCountSmallThenLimit : !isCountSmallThenLimit;
376 throw new ArgumentException("Argument_IComparable2 loop control variable"); // + Utils.VBFriendlyName(LoopFor.Counter)));
377 //TODO: verify this and the above are the same and remove.
378 //throw new ArgumentException(Utils.GetResourceString(
379 // "Argument_IComparable2", "loop control variable",
380 // Utils.VBFriendlyName(LoopFor.Counter)));
384 * This method throws exception if the input is Valuetype
385 * @param obj the object that need to be checked
387 public static void CheckForSyncLockOnValueType(object obj) {
389 //throw new NotImplementedException("MSVB.Compilerservices.flowcontrol needs help");
390 if (obj != null && obj.GetType().IsValueType)
391 throw new ArgumentException(Utils.GetResourceString("SyncLockRequiresReferenceType1 "));
392 //TODO: verify this and the above are the same and remove.
393 //if (obj != null && ObjectStaticWrapper.GetType(obj).get_IsValueType())
394 // throw new ArgumentException(Utils.GetResourceString(
395 // "SyncLockRequiresReferenceType1",Utils.VBFriendlyName(obj)));