@@ -368,6 +368,33 @@ void MCKeywordsExecuteRepeatStatements(MCExecContext& ctxt, MCStatement *stateme
368368 }
369369}
370370
371+ void MCKeywordsExecRepeatCount (MCExecContext& ctxt, MCStatement *statements, MCExpression *endcond, uint2 line, uint2 pos)
372+ {
373+ MCAutoValueRef t_condition;
374+
375+ if (!ctxt . TryToEvaluateExpression (endcond, line, pos, EE_REPEAT_BADFORCOND, &t_condition))
376+ return ;
377+
378+ // SN-2015-01-14: [[ Bug 14377 ]] Throw an error as it used to be done
379+ integer_t t_count;
380+ if (!ctxt . ConvertToInteger (*t_condition, t_count) && (MCtrace || MCnbreakpoints)
381+ && !MCtrylock && !MClockerrors)
382+ {
383+ MCB_error (ctxt, line, pos, EE_REPEAT_BADFORCOND);
384+ return ;
385+ }
386+
387+ while (t_count > 0 )
388+ {
389+ bool t_done;
390+ MCKeywordsExecuteRepeatStatements (ctxt, statements, line, pos, t_done);
391+ if (t_done)
392+ break ;
393+
394+ t_count -= 1 ;
395+ }
396+ }
397+
371398void MCKeywordsExecRepeatFor (MCExecContext& ctxt, MCStatement *statements, MCExpression *endcond, MCVarref *loopvar, File_unit each, uint2 line, uint2 pos)
372399{
373400 MCAutoArrayRef t_array;
@@ -382,10 +409,7 @@ void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExp
382409 uintptr_t t_iterator;
383410 // SN2015-06-15: [[ Bug 15457 ]] The index can be a negative index.
384411 index_t t_sequenced_iterator;
385- const byte_t *t_data_ptr, *t_data_end;
386- Parse_stat ps;
387- MCScriptPoint *sp = nil;
388- int4 count = 0 ;
412+ const byte_t *t_data_ptr;
389413
390414 MCTextChunkIterator *tci = nil;
391415
@@ -394,88 +418,74 @@ void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExp
394418
395419 bool t_sequence_array;
396420 t_sequence_array = false ;
397-
398- if (loopvar != NULL )
421+
422+ if (each == FU_ELEMENT || each == FU_KEY )
399423 {
400- if (each == FU_ELEMENT || each == FU_KEY)
401- {
402- if (!ctxt . ConvertToArray (*t_condition, &t_array))
403- return ;
404-
405- // SN-2015-06-15: [[ Bug 15457 ]] If this is a numerical array, do
406- // it in order - even if it does not start at 1
407- if (each == FU_ELEMENT && MCArrayIsNumericSequence (*t_array, t_sequenced_iterator))
408- {
409- t_sequence_array = true ;
410- if (!MCArrayFetchValueAtIndex (*t_array, t_sequenced_iterator, t_value))
411- return ;
412- }
413- else
414- {
415- t_iterator = 0 ;
416- if (!MCArrayIterate (*t_array, t_iterator, t_key, t_value))
417- return ;
418- }
419- }
420- else if (each == FU_BYTE)
424+ if (!ctxt . ConvertToArray (*t_condition, &t_array))
425+ return ;
426+
427+ // SN-2015-06-15: [[ Bug 15457 ]] If this is a numerical array, do
428+ // it in order - even if it does not start at 1
429+ if (each == FU_ELEMENT && MCArrayIsNumericSequence (*t_array, t_sequenced_iterator))
421430 {
422- if (!ctxt . ConvertToData (*t_condition, &t_data))
431+ t_sequence_array = true ;
432+ if (!MCArrayFetchValueAtIndex (*t_array, t_sequenced_iterator, t_value))
423433 return ;
424-
425- t_length = MCDataGetLength (*t_data);
426- t_data_ptr = MCDataGetBytePtr (*t_data);
427434 }
428435 else
429436 {
430- if (!ctxt . ConvertToString (*t_condition, &t_string))
437+ t_iterator = 0 ;
438+ if (!MCArrayIterate (*t_array, t_iterator, t_key, t_value))
431439 return ;
432-
433- switch (each)
434- {
435- case FU_LINE:
436- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_LINE);
437- break ;
438- case FU_PARAGRAPH:
439- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_PARAGRAPH);
440- break ;
441- case FU_SENTENCE:
442- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_SENTENCE);
443- break ;
444- case FU_ITEM:
445- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_ITEM);
446- break ;
447- case FU_WORD:
448- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_WORD);
449- break ;
450- case FU_TRUEWORD:
451- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_TRUEWORD);
452- break ;
453- case FU_TOKEN:
454- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_TOKEN);
455- break ;
456- case FU_CODEPOINT:
457- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_CODEPOINT);
458- break ;
459- case FU_CODEUNIT:
460- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_CODEUNIT);
461- break ;
462- case FU_CHARACTER:
463- default :
464- tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_CHARACTER);
465- break ;
466- }
467440 }
468441 }
442+ else if (each == FU_BYTE)
443+ {
444+ if (!ctxt . ConvertToData (*t_condition, &t_data))
445+ return ;
446+
447+ t_length = MCDataGetLength (*t_data);
448+ t_data_ptr = MCDataGetBytePtr (*t_data);
449+ }
469450 else
470451 {
471- // SN-2015-01-14: [[ Bug 14377 ]] Throw an error as it used to be done
472- if (!ctxt . ConvertToInteger (*t_condition, count) && (MCtrace || MCnbreakpoints)
473- && !MCtrylock && !MClockerrors)
474- {
475- MCB_error (ctxt, line, pos, EE_REPEAT_BADFORCOND);
452+ if (!ctxt . ConvertToString (*t_condition, &t_string))
476453 return ;
477- }
478- count = MCU_max (count, 0 );
454+
455+ switch (each)
456+ {
457+ case FU_LINE:
458+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_LINE);
459+ break ;
460+ case FU_PARAGRAPH:
461+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_PARAGRAPH);
462+ break ;
463+ case FU_SENTENCE:
464+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_SENTENCE);
465+ break ;
466+ case FU_ITEM:
467+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_ITEM);
468+ break ;
469+ case FU_WORD:
470+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_WORD);
471+ break ;
472+ case FU_TRUEWORD:
473+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_TRUEWORD);
474+ break ;
475+ case FU_TOKEN:
476+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_TOKEN);
477+ break ;
478+ case FU_CODEPOINT:
479+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_CODEPOINT);
480+ break ;
481+ case FU_CODEUNIT:
482+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_CODEUNIT);
483+ break ;
484+ case FU_CHARACTER:
485+ default :
486+ tci = MCStringsTextChunkIteratorCreate (ctxt, *t_string, CT_CHARACTER);
487+ break ;
488+ }
479489 }
480490
481491 bool done;
@@ -491,83 +501,76 @@ void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExp
491501 {
492502 MCAutoStringRef t_unit;
493503 MCAutoDataRef t_byte;
494- if (loopvar != NULL )
504+ switch (each )
495505 {
496- switch (each)
506+ case FU_KEY:
507+ {
508+ loopvar -> set (ctxt, t_key);
509+ if (!MCArrayIterate (*t_array, t_iterator, t_key, t_value))
510+ endnext = true ;
511+ }
512+ break ;
513+
514+ case FU_ELEMENT:
497515 {
498- case FU_KEY:
516+ loopvar -> set (ctxt, t_value);
517+ // SN-2015-06-15: [[ Bug 15457 ]] Sequenced, numeric arrays
518+ // have their own iterator
519+ if (t_sequence_array)
499520 {
500- // MW-2010-12-15: [[ Bug 9218 ]] Make a copy of the key so that it can't be mutated
501- // accidentally.
502- MCNewAutoNameRef t_key_copy;
503- MCNameClone (t_key, &t_key_copy);
504- loopvar -> set (ctxt, *t_key_copy);
505- if (!MCArrayIterate (*t_array, t_iterator, t_key, t_value))
521+ if (!MCArrayFetchValueAtIndex (*t_array, ++t_sequenced_iterator, t_value))
506522 endnext = true ;
507523 }
508- break ;
509- case FU_ELEMENT:
510- {
511- loopvar -> set (ctxt, t_value);
512- // SN-2015-06-15: [[ Bug 15457 ]] Sequenced, numeric arrays
513- // have their own iterator
514- if (t_sequence_array)
515- {
516- if (!MCArrayFetchValueAtIndex (*t_array, ++t_sequenced_iterator, t_value))
517- endnext = true ;
518- }
519- else
520- {
521- if (!MCArrayIterate (*t_array, t_iterator, t_key, t_value))
522- endnext = true ;
523- }
524- }
525- break ;
526-
527- case FU_BYTE:
524+ else
528525 {
529- // SN-2014-04-14 [[ Bug 12184 ]] If we have no data at all, we don't want to start the loop
530- if (t_length)
531- {
532- MCDataCreateWithBytes (t_data_ptr++, 1 , &t_byte);
533-
534- endnext = (--t_length) == 0 ;
535- }
536- else
537- done = true ;
526+ if (!MCArrayIterate (*t_array, t_iterator, t_key, t_value))
527+ endnext = true ;
538528 }
539- break ;
540-
541- default :
529+ }
530+ break ;
531+
532+ case FU_BYTE:
533+ {
534+ // SN-2014-04-14 [[ Bug 12184 ]] If we have no data at all, we don't want to start the loop
535+ if (t_length)
542536 {
543- t_found = MCStringsTextChunkIteratorNext (ctxt, tci);
544- endnext = tci -> IsExhausted ();
537+ MCDataCreateWithBytes (t_data_ptr++, 1 , &t_byte);
545538
546- if (!t_found)
547- {
548- t_unit = kMCEmptyString ;
549- done = true ;
550- }
551- else
552- tci -> CopyString (&t_unit);
539+ endnext = (--t_length) == 0 ;
553540 }
541+ else
542+ done = true ;
554543 }
555- // MW-2010-12-15: [[ Bug 9218 ]] Added KEY to the type of repeat that already
556- // copies the value.
557- // MW-2011-02-08: [[ Bug ]] Make sure we don't use 't_unit' if the repeat type is 'key' or
558- // 'element'.
559- // Set the loop variable to whatever the value was in the last iteration.
560- if (each == FU_BYTE)
544+ break ;
545+
546+ default :
561547 {
562- // SN-2014-04-14 [[ Bug 12184 ]] We don't need to set anything since we are not going in the loop
563- if (!done)
564- loopvar -> set (ctxt, *t_byte);
548+ t_found = MCStringsTextChunkIteratorNext (ctxt, tci);
549+ endnext = tci -> IsExhausted ();
550+
551+ if (!t_found)
552+ {
553+ t_unit = kMCEmptyString ;
554+ done = true ;
555+ }
556+ else
557+ tci -> CopyString (&t_unit);
565558 }
566- else if (each != FU_ELEMENT && each != FU_KEY)
567- loopvar -> set (ctxt, *t_unit);
559+ break ;
568560 }
569- else
570- done = count-- == 0 ;
561+ // MW-2010-12-15: [[ Bug 9218 ]] Added KEY to the type of repeat that already
562+ // copies the value.
563+ // MW-2011-02-08: [[ Bug ]] Make sure we don't use 't_unit' if the repeat type is 'key' or
564+ // 'element'.
565+ // Set the loop variable to whatever the value was in the last iteration.
566+ if (each == FU_BYTE)
567+ {
568+ // SN-2014-04-14 [[ Bug 12184 ]] We don't need to set anything since we are not going in the loop
569+ if (!done)
570+ loopvar -> set (ctxt, *t_byte);
571+ }
572+ else if (each != FU_ELEMENT && each != FU_KEY)
573+ loopvar -> set (ctxt, *t_unit);
571574
572575 if (!done)
573576 MCKeywordsExecuteRepeatStatements (ctxt, statements, line, pos, done);
@@ -593,7 +596,6 @@ void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExp
593596void MCKeywordsExecRepeatWith (MCExecContext& ctxt, MCStatement *statements, MCExpression *step, MCExpression *startcond, MCExpression *endcond, MCVarref *loopvar, real8 stepval, uint2 line, uint2 pos)
594597{
595598 real8 endn = 0.0 ;
596- MCExecValue t_condition;
597599
598600 if (step != NULL )
599601 {
0 commit comments