PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/FScriptFramework/ArrayRepId.m

https://github.com/DottedGecko/F-Script
Objective C | 765 lines | 576 code | 146 blank | 43 comment | 187 complexity | c0c8bdc730d66665af7b40bc7f3e2ecb MD5 | raw file
  1. /* ArrayRepId.m Copyright (c) 1998-2009 Philippe Mougin. */
  2. /* This software is open source. See the license. */
  3. #import "build_config.h"
  4. #import "ArrayRepId.h"
  5. #import "FSArray.h"
  6. #import "FScriptFunctions.h"
  7. #import <Foundation/Foundation.h>
  8. #import "FSBooleanPrivate.h"
  9. #import "FSCompiler.h"
  10. #import "FSVoid.h"
  11. #import <objc/objc-runtime.h>
  12. #import <objc/objc-auto.h>
  13. #import "FSBlock.h"
  14. #import "BlockRep.h"
  15. #import "BlockPrivate.h"
  16. #import "BlockInspector.h"
  17. #import "FSExecEngine.h"
  18. #import "FSPattern.h"
  19. #import "FSExecEngine.h" // sendMsg
  20. #import "FSNumber.h"
  21. #import "NumberPrivate.h"
  22. #import <string.h>
  23. #import "ArrayPrivate.h"
  24. #import "ArrayRepDouble.h"
  25. #import "ArrayRepBoolean.h"
  26. #import "FSMiscTools.h"
  27. #ifndef MAX
  28. #define MAX(a, b) \
  29. ({typeof(a) _a = (a); typeof(b) _b = (b); \
  30. _a > _b ? _a : _b; })
  31. #endif
  32. #ifndef MIN
  33. #define MIN(a, b) \
  34. ({typeof(a) _a = (a); typeof(b) _b = (b); \
  35. _a < _b ? _a : _b; })
  36. #endif
  37. @interface ArrayRepId(ArrayRepIdPrivate)
  38. - (void) addObjectsFromFSArray:(FSArray *)otherArray;
  39. @end
  40. @implementation ArrayRepId
  41. /*typedef struct {
  42. unsigned long state;
  43. id *itemsPtr;
  44. unsigned long *mutationsPtr;
  45. unsigned long extra[5];
  46. } NSFastEnumerationState;*/
  47. - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)statep objects:(id *)stackbuf count:(NSUInteger)len
  48. {
  49. if (statep->state == 0)
  50. {
  51. statep->state = 1;
  52. statep->itemsPtr = t;
  53. statep->mutationsPtr = (unsigned long *)self;
  54. return count;
  55. }
  56. else return 0;
  57. }
  58. ///////////////////////////////////// USER METHODS
  59. - (id)at:(id)index put:(id)elem
  60. {
  61. double ind;
  62. id oldElem;
  63. if (!index) FSExecError(@"index of an array must not be nil");
  64. if ([index isKindOfClass:[NSIndexSet class]])
  65. {
  66. NSMutableArray *newIndex = [FSArray array];
  67. NSUInteger currentIndex = [index firstIndex];
  68. while (currentIndex != NSNotFound)
  69. {
  70. [newIndex addObject:[NSNumber numberWithDouble:currentIndex]];
  71. currentIndex = [index indexGreaterThanIndex:currentIndex];
  72. }
  73. index = newIndex;
  74. }
  75. if ([index isKindOfClass:[NSNumber class]])
  76. {
  77. ind = [index doubleValue];
  78. if (ind < 0) FSExecError(@"index of an array must be a number greater or equal to 0");
  79. if (ind >= count) FSExecError(@"index of an array must be a number less than the size of the array");
  80. oldElem = t[(NSUInteger)ind];
  81. t[(NSUInteger)ind] = [elem retain];
  82. [oldElem release];
  83. }
  84. else if ([index isKindOfClass:[NSArray class]])
  85. {
  86. id elem_index;
  87. NSUInteger i = 0;
  88. NSUInteger j = 0;
  89. NSUInteger nb = [index count];
  90. NSUInteger elem_count = 0; // elem_count is initialized in order to avoid a false warning "might be used uninitialized"
  91. BOOL elemIsArray = [elem isKindOfClass:[NSArray class]];
  92. //if (![elem isKindOfClass:[NSArray class]])
  93. // FSExecError(@"method \"at:put:\", argument 1 is an array, argument 2 must be an array too");
  94. if (elemIsArray) elem_count = [elem count];
  95. while (i < nb && ![index objectAtIndex:i]) i++; // ignore the nil value
  96. if (i == nb)
  97. {
  98. if ((nb == count || nb == 0) && (!elemIsArray || elem_count == 0)) return elem;
  99. else FSExecError(@"invalid index");
  100. }
  101. elem_index = [index objectAtIndex:i];
  102. if ([elem_index isKindOfClass:[FSBoolean class]])
  103. {
  104. NSUInteger k,trueCount;
  105. if (nb != count) FSExecError(@"indexing with an array of boolean of bad size");
  106. if (elemIsArray)
  107. {
  108. for (k=i, trueCount=0; k<nb; k++)
  109. {
  110. elem_index = [index objectAtIndex:k];
  111. if (elem_index == fsTrue || (elem_index != fsFalse && [elem_index isKindOfClass:[FSBoolean class]] && [elem_index isTrue]))
  112. trueCount++;
  113. }
  114. if (elem_count < trueCount) FSExecError(@"method \"at:put:\", not enough elements in argument 2");
  115. else if (elem_count > trueCount) FSExecError(@"method \"at:put:\", too many elements in argument 2");
  116. }
  117. while (i < nb)
  118. {
  119. elem_index = [index objectAtIndex:i];
  120. if (elem_index == fsTrue || (elem_index != fsFalse && [elem_index isKindOfClass:[FSBoolean class]] && [elem_index isTrue]) )
  121. {
  122. oldElem = t[i];
  123. t[i] = [(elemIsArray ? [elem objectAtIndex:j] : elem) retain];
  124. [oldElem release];
  125. j++;
  126. }
  127. else if (elem_index != fsFalse && ![elem_index isKindOfClass:[FSBoolean class]]) FSExecError(@"indexing with a mixed array");
  128. i++;
  129. while (i < nb && ![index objectAtIndex:i]) i++; // ignore the nil value
  130. }
  131. return elem;
  132. }
  133. else if ([elem_index isKindOfClass:[NSNumber class]])
  134. {
  135. NSUInteger k;
  136. if (elemIsArray && nb != elem_count) FSExecError(@"method \"at:put:\", argument 1 and argument 2 must be arrays of same size");
  137. for (k=i; k<nb; k++)
  138. {
  139. elem_index = [index objectAtIndex:k];
  140. if (![elem_index isKindOfClass:[NSNumber class]]) FSExecError(@"array indexing by a mixed array");
  141. ind = [elem_index doubleValue];
  142. if (ind < 0) FSExecError(@"index of an array must be a number greater or equal to 0");
  143. else if (ind >= count) FSExecError(@"index of an array must be a number less than the size of the array");
  144. }
  145. while (i < nb)
  146. {
  147. elem_index = [index objectAtIndex:i];
  148. ind = [elem_index doubleValue];
  149. oldElem = t[(NSUInteger)ind];
  150. t[(NSUInteger)ind] = [(elemIsArray ? [elem objectAtIndex:i] : elem) retain];
  151. [oldElem release];
  152. i++;
  153. while (i < nb && ![index objectAtIndex:i]) i++; // ignore the nil values
  154. }
  155. }
  156. else // elem_index is neither an NSNumber nor a FSBoolean
  157. FSExecError([NSString stringWithFormat:@"array indexing by an array containing %@", descriptionForFSMessage(elem_index)]);
  158. }
  159. else
  160. FSExecError([NSString stringWithFormat:@"array indexing by %@, number, array or index set expected", descriptionForFSMessage(index)]);
  161. return elem;
  162. }
  163. - (id)operator_backslash:(FSBlock*)bl // may raise
  164. {
  165. NSUInteger i;
  166. id args[3];
  167. args[0] = t[0];
  168. if ([bl isCompact])
  169. {
  170. SEL selector = [bl selector];
  171. NSString *selectorStr = [bl selectorStr];
  172. FSMsgContext *msgContext = [bl msgContext];
  173. args[1] = (id)(selector ? selector : [FSCompiler selectorFromString:selectorStr]);
  174. for (i = 1; i < count; i++)
  175. {
  176. args[2] = t[i];
  177. args[0] = sendMsg(args[0], selector, 3, args, nil, msgContext, nil);
  178. }
  179. }
  180. else
  181. {
  182. BlockRep *blRep = [bl blockRep];
  183. for (i = 1; i < count; i++)
  184. {
  185. args[2] = t[i];
  186. args[0] = [blRep body_notCompact_valueArgs:args count:3 block:bl];
  187. }
  188. }
  189. return args[0];
  190. }
  191. - (FSArray *)replicateWithArray:(FSArray *)operand
  192. {
  193. FSArray *r;
  194. NSUInteger i,j;
  195. FSArray *index = operand;
  196. assert(![operand isProxy]);
  197. r = [FSArray array];
  198. switch ([index type])
  199. {
  200. case FS_ID:
  201. {
  202. id *indexData = [operand dataPtr];
  203. for (i=0; i < count; i++)
  204. {
  205. double opElemDouble;
  206. if (![indexData[i] isKindOfClass:NSNumberClass]) FSExecError(@"argument 1 of method \"replicate:\" must be an array of numbers");
  207. opElemDouble = [(NSNumber *)(indexData[i]) doubleValue];
  208. if (opElemDouble < 0) FSExecError(@"argument 1 of method \"replicate:\" must not contain negative numbers");
  209. if (opElemDouble > NSUIntegerMax) FSExecError([NSString stringWithFormat:@"argument of method \"replicate:\" must contain numbers less or equal to %lu", (unsigned long)NSUIntegerMax]);
  210. for (j=0; j < opElemDouble; j++) [r addObject:t[i]];
  211. }
  212. break;
  213. }
  214. case DOUBLE:
  215. {
  216. double *indexData = [(ArrayRepDouble *)[operand arrayRep] doublesPtr];
  217. for (i=0; i < count; i++)
  218. {
  219. double opElemDouble = indexData[i];
  220. if (opElemDouble < 0) FSExecError(@"argument 1 of method \"replicate:\" must not contain negative numbers");
  221. if (opElemDouble > NSUIntegerMax)
  222. FSExecError([NSString stringWithFormat:@"argument of method \"replicate:\" must contain numbers less or equal to %lu", (unsigned long)NSUIntegerMax]);
  223. for (j=0; j < opElemDouble; j++) [r addObject:t[i]];
  224. }
  225. break;
  226. }
  227. case BOOLEAN:
  228. if ([operand count] != 0) FSExecError(@"argument 1 of method \"replicate:\" is an array of Booleans. An array of numbers was expected");
  229. break;
  230. case EMPTY: break;
  231. case FETCH_REQUEST:
  232. [operand becomeArrayOfId];
  233. return [self indexWithArray:operand];
  234. } // end switch
  235. return r;
  236. }
  237. - (FSArray *)rotatedBy:(NSNumber *)operand
  238. {
  239. FSArray *r;
  240. NSUInteger i;
  241. NSInteger op;
  242. VERIF_OP_NSNUMBER(@"rotatedBy:");
  243. if (count == 0) return [FSArray array];
  244. op = [operand doubleValue];
  245. r = [FSArray arrayWithCapacity:count];
  246. if (op >= 0)
  247. {
  248. for(i = op % count ; i < count; i++)
  249. [r addObject:t[i]];
  250. for (i = 0; i < op % count; i++)
  251. [r addObject:t[i]];
  252. }
  253. else
  254. {
  255. op = -op;
  256. for(i = count-(op % count) ; i < count; i++)
  257. [r addObject:t[i]];
  258. for (i = 0; i < count-(op % count); i++)
  259. [r addObject:t[i]];
  260. }
  261. return r;
  262. }
  263. ///////////////////////////////////////////////////////////////////////////
  264. //////////////////////////////////// OTHER METHOD /////////////////////////
  265. ///////////////////////////////////////////////////////////////////////////
  266. - (void)addObject:(id)anObject
  267. {
  268. count++;
  269. if (count > capacity)
  270. {
  271. capacity = (capacity+1)*2;
  272. t = (id *)NSReallocateCollectable(t, capacity * sizeof(id), NSScannedOption);
  273. }
  274. t[count-1] = [anObject retain];
  275. }
  276. - (void)addObjectsFromFSArray:(FSArray *)otherArray
  277. {
  278. NSUInteger i;
  279. NSUInteger oldCount = count;
  280. id *otherArrayData = [otherArray dataPtr];
  281. NSUInteger otherArrayCount = [otherArray count];
  282. count += otherArrayCount;
  283. if (count > capacity)
  284. {
  285. capacity = count;
  286. t = (id *)NSReallocateCollectable(t, capacity * sizeof(id), NSScannedOption);
  287. }
  288. for (i = 0; i < otherArrayCount; i++)
  289. t[oldCount+i] = [otherArrayData[i] retain];
  290. }
  291. - (ArrayRepId *) asArrayRepId
  292. { return self;}
  293. - (id)copyWithZone:(NSZone *)zone
  294. {
  295. return [[[self class] allocWithZone:zone] initWithObjects:t count:count];
  296. }
  297. - (NSUInteger)count
  298. { return count; }
  299. - (void *)dataPtr
  300. {return t;}
  301. - (void)dealloc
  302. {
  303. NSUInteger i;
  304. //printf("\n arrayRep : dealloc\n");
  305. for (i = 0; i < count; i++) [t[i] release];
  306. free(t);
  307. [super dealloc];
  308. }
  309. - (NSString *)descriptionLimited:(NSUInteger)nbElem
  310. {
  311. NSMutableString *str = [[@"{" mutableCopy] autorelease];
  312. NSString *elemStr = @""; // W
  313. NSUInteger i;
  314. NSUInteger lim = MIN(count,nbElem);
  315. if (lim > 0)
  316. {
  317. elemStr = printString(t[0]);
  318. [str appendString:elemStr];
  319. }
  320. for (i = 1; i < lim; i++)
  321. {
  322. [str appendString:@", "];
  323. if ([elemStr length] > 20) [str appendString:@"\n"];
  324. elemStr = printString(t[i]);
  325. [str appendString:elemStr];
  326. }
  327. if (count > nbElem) [str appendFormat:@", ... (%lu more elements)",(unsigned long)(count-nbElem)];
  328. [str appendString:@"}"];
  329. return str;
  330. }
  331. - (NSUInteger)indexOfObject:(id)anObject inRange:(NSRange)range identical:(BOOL)identical
  332. {
  333. if (range.length == 0) return NSNotFound;
  334. else
  335. {
  336. NSUInteger i = range.location;
  337. NSUInteger end = (range.location + range.length -1);
  338. while ( i <= end && !( identical ? t[i] == anObject : ([t[i] isEqual:anObject] || (t[i] == nil && anObject == nil)) ) )
  339. {
  340. i++;
  341. }
  342. return (i > end) ? NSNotFound : i;
  343. }
  344. }
  345. - (id)indexWithArray:(FSArray *)index
  346. {
  347. switch ([index type])
  348. {
  349. case FS_ID:
  350. {
  351. FSArray *r;
  352. id *indexData;
  353. NSUInteger i = 0;
  354. NSUInteger nb = [index count];
  355. indexData = [index dataPtr];
  356. while (i < nb && !indexData[i]) i++; // ignore the nil value
  357. if (i == nb)
  358. {
  359. if (nb == count || nb == 0) return [FSArray array];
  360. else FSExecError(@"invalid index");
  361. }
  362. if (indexData[i] == fsTrue || indexData[i] == fsFalse || [indexData[i] isKindOfClass:[FSBoolean class]])
  363. {
  364. if (nb != count) FSExecError(@"indexing with an array of booleans of bad size");
  365. r = [FSArray array];
  366. while (i < nb)
  367. {
  368. if (indexData[i] == fsTrue) [r addObject:t[i]];
  369. else if (indexData[i] != fsFalse)
  370. {
  371. if (![indexData[i] isKindOfClass:[FSBoolean class]]) FSExecError(@"indexing with a mixed array");
  372. else if ([indexData[i] isTrue]) [r addObject:t[i]];
  373. }
  374. i++;
  375. while (i < nb && !indexData[i]) i++; // ignore the nil value
  376. }
  377. }
  378. else if ([indexData[i] isKindOfClass:NSNumberClass])
  379. {
  380. r = [FSArray arrayWithCapacity:nb];
  381. while (i < nb)
  382. {
  383. double ind;
  384. if (![indexData[i] isKindOfClass:NSNumberClass]) FSExecError(@"indexing with a mixed array");
  385. ind = [indexData[i] doubleValue];
  386. /*
  387. if (ind != (int)ind)
  388. FSExecError(@"l'indice d'un tableau doit etre un nombre sans "
  389. @"partie fractionnaire");
  390. */
  391. if (ind < 0) FSExecError(@"index of an array must be a number greater or equal to 0");
  392. if (ind >= count) FSExecError(@"index of an array must be a number less than the size of the array");
  393. [r addObject:t[(NSUInteger)ind]];
  394. i++;
  395. while (i < nb && !indexData[i]) i++; // ignore the nil value
  396. }
  397. }
  398. else // indexData[i] is neither an NSNumber nor a FSBoolean
  399. {
  400. FSExecError([NSString stringWithFormat:@"array indexing by an array containing %@", descriptionForFSMessage(indexData[i])]);
  401. return nil; // W
  402. }
  403. return r;
  404. }
  405. case BOOLEAN:
  406. {
  407. NSUInteger i;
  408. FSArray *r;
  409. char *indexData;
  410. if ([index count] == 0) return [FSArray array];
  411. if ([index count] != count) FSExecError(@"indexing with an array of booleans of bad size");
  412. r = [FSArray array];
  413. indexData = [(ArrayRepBoolean *)[index arrayRep] booleansPtr];
  414. for (i = 0; i < count; i++) if (indexData[i]) [r addObject:t[i]];
  415. return r;
  416. }
  417. case DOUBLE:
  418. {
  419. FSArray *r;
  420. double *indexData;
  421. NSUInteger i = 0;
  422. NSUInteger nb = [index count];
  423. if (i == nb) return [FSArray array];
  424. indexData = [(ArrayRepDouble *)[index arrayRep] doublesPtr];
  425. r = [FSArray arrayWithCapacity:nb];
  426. while (i < nb)
  427. {
  428. double ind = indexData[i];
  429. /*
  430. if (ind != (int)ind)
  431. FSExecError(@"l'indice d'un tableau doit etre un nombre sans "
  432. @"partie fractionnaire");
  433. */
  434. if (ind < 0) FSExecError(@"index of an array must be a number greater or equal to 0");
  435. if (ind >= count) FSExecError(@"index of an array must be a number less than the size of the array");
  436. [r addObject:t[(NSUInteger)ind]];
  437. i++;
  438. }
  439. return r;
  440. }
  441. case EMPTY: return [FSArray array];
  442. case FETCH_REQUEST:
  443. [index becomeArrayOfId];
  444. return [self indexWithArray:index];
  445. } // end switch
  446. return nil; // W
  447. }
  448. - (id)init
  449. {
  450. return [self initWithCapacity:0];
  451. }
  452. /*- initFrom:(unsigned)from to:(unsigned)to step:(unsigned)step
  453. {
  454. if (to < from) return [self init];
  455. if ([self initWithCapacity:1+((to-from)/step)])
  456. {
  457. double valcou = from;
  458. do
  459. {
  460. t[count++] = [[[Number alloc] initWithDouble:valcou] retain];
  461. valcou += step;
  462. }
  463. while (valcou <= to);
  464. return self;
  465. }
  466. return nil;
  467. } */
  468. - (id)initFilledWith:(id)elem count:(NSUInteger)nb
  469. {
  470. if (self = [self initWithCapacity:nb])
  471. {
  472. for(count = 0; count < nb; count++) t[count] = [elem retain];
  473. return self;
  474. }
  475. return nil;
  476. }
  477. - (id)initWithCapacity:(NSUInteger)aNumItems
  478. {
  479. if ((self = [super init]))
  480. {
  481. t = NSAllocateCollectable(aNumItems*sizeof(id), NSScannedOption);
  482. if (!t)
  483. {
  484. [super dealloc];
  485. return nil;
  486. }
  487. retainCount = 1;
  488. capacity = aNumItems;
  489. count = 0;
  490. return self;
  491. }
  492. return nil;
  493. }
  494. - (id)initWithObjectsNoCopy:(id *)tab count:(NSUInteger)nb
  495. {
  496. if ((self = [super init]))
  497. {
  498. retainCount = 1;
  499. t = tab;
  500. capacity = nb;
  501. count = nb;
  502. return self;
  503. }
  504. return nil;
  505. }
  506. - (id)initWithObjects:(id *)objects count:(NSUInteger)nb
  507. {
  508. NSUInteger i;
  509. if (self = [self initWithCapacity:nb])
  510. {
  511. for (i = 0; i < nb; i++)
  512. {
  513. t[i] = [objects[i] retain];
  514. }
  515. count = nb;
  516. return self;
  517. }
  518. return nil;
  519. }
  520. - (void)insertObject:anObject atIndex:(NSUInteger)index
  521. {
  522. if (index > count) [NSException raise:NSRangeException format:@"index beyond the end of the array in method -insertObject:atIndex"];
  523. count++ ;
  524. if (count > capacity)
  525. {
  526. capacity = (capacity+1)*2;
  527. t = (id*)NSReallocateCollectable(t, capacity * sizeof(id), NSScannedOption);
  528. }
  529. objc_memmove_collectable( &(t[index+1]), &(t[index]), ((count-1)-index) * sizeof(id));
  530. t[index] = [anObject retain];
  531. }
  532. - (id)objectAtIndex:(NSUInteger)index
  533. {
  534. if (index >= count) [NSException raise:NSRangeException format:@"index beyond the end of the array in method -ObjectAtIndex:"];
  535. return t[index];
  536. }
  537. - (void)removeLastElem
  538. {
  539. [self removeLastObject];
  540. }
  541. - (void)removeLastObject
  542. {
  543. if (count == 0) [NSException raise:NSRangeException format:@"-removeLastObject called on an empty array"];
  544. [t[count-1] release];
  545. count--;
  546. if (capacity/2 >= count+100)
  547. {
  548. capacity = capacity/2;
  549. t = (id*)NSReallocateCollectable(t, capacity * sizeof(id), NSScannedOption);
  550. }
  551. }
  552. - (void)removeElemAtIndex:(NSUInteger)index
  553. {
  554. [self removeObjectAtIndex:index];
  555. }
  556. - (void)removeObjectAtIndex:(NSUInteger)index
  557. {
  558. if (index >= count) [NSException raise:NSRangeException format:@"index beyond the end of the array in method -removeObjectAtIndex:"];
  559. [t[index] release];
  560. count--;
  561. objc_memmove_collectable( &(t[index]), &(t[index+1]), (count-index) * sizeof(id) );
  562. if (capacity/2 >= count+100)
  563. {
  564. capacity = capacity/2;
  565. t = (id*)NSReallocateCollectable(t, capacity * sizeof(id), NSScannedOption);
  566. }
  567. }
  568. - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject
  569. {
  570. if (index >= count) [NSException raise:NSRangeException format:@"index beyond the end of the array in method -replaceObjectAtIndex:withObject:"];
  571. [anObject retain];
  572. [t[index] release];
  573. t[index] = anObject;
  574. }
  575. - (id)retain { retainCount++; return self;}
  576. - (NSUInteger)retainCount { return retainCount;}
  577. - (oneway void)release { if (--retainCount == 0) [self dealloc];}
  578. - (NSArray *)subarrayWithRange:(NSRange)range
  579. {
  580. ArrayRepId *resRep;
  581. FSArray *r;
  582. resRep = [[ArrayRepId alloc] initWithObjects:t+range.location count:range.length];
  583. r = [FSArray arrayWithRep:resRep];
  584. [resRep release];
  585. return r;
  586. }
  587. - (enum ArrayRepType)repType { return FS_ID;}
  588. - (FSArray *)where:(NSArray *)booleans // precondition: booleans is actualy an array and is of same size as the receiver
  589. {
  590. FSArray *result = [FSArray array];
  591. if ([booleans isKindOfClass:[FSArray class]] && [(FSArray *)booleans type] == BOOLEAN)
  592. {
  593. char *rawBooleans = [(ArrayRepBoolean *)[(FSArray *)booleans arrayRep] booleansPtr];
  594. for (NSUInteger i = 0; i < count; i++) if (rawBooleans[i]) [result addObject:t[i]];
  595. }
  596. else
  597. {
  598. id boolean;
  599. for (NSUInteger i = 0; i < count; i++)
  600. {
  601. boolean = [booleans objectAtIndex:i];
  602. if (boolean == fsFalse || boolean == nil)
  603. continue;
  604. else if (boolean == fsTrue)
  605. [result addObject:t[i]];
  606. else if ([boolean isKindOfClass:[FSBoolean class]])
  607. {
  608. if ([boolean isTrue])
  609. [result addObject:t[i]];
  610. }
  611. else
  612. FSExecError(@"argument of method \"where:\" must be an array of booleans");
  613. }
  614. }
  615. return result;
  616. }
  617. @end