Skip to content

Commit 2559185

Browse files
Merge pull request livecode#2396 from livecodesebastien/bugfix-15457
[[ Bug 15457 ]] <repeat for each element> should use numeric order fo…
2 parents 4536fe5 + 53ec37f commit 2559185

4 files changed

Lines changed: 45 additions & 11 deletions

File tree

docs/notes/bugfix-15457.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Repeat for each element subtly different in 7.0

engine/src/exec-keywords.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExp
385385
MCNameRef t_key;
386386
MCValueRef t_value;
387387
uintptr_t t_iterator;
388+
// SN2015-06-15: [[ Bug 15457 ]] The index can be a negative index.
389+
index_t t_sequenced_iterator;
388390
const byte_t *t_data_ptr, *t_data_end;
389391
Parse_stat ps;
390392
MCScriptPoint *sp = nil;
@@ -405,12 +407,12 @@ void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExp
405407
if (!ctxt . ConvertToArray(*t_condition, &t_array))
406408
return;
407409

408-
// If this is a numerical array, do it in order
409-
if (each == FU_ELEMENT && MCArrayIsSequence(*t_array))
410+
// SN-2015-06-15: [[ Bug 15457 ]] If this is a numerical array, do
411+
// it in order - even if it does not start at 1
412+
if (each == FU_ELEMENT && MCArrayIsNumericSequence(*t_array, t_sequenced_iterator))
410413
{
411414
t_sequence_array = true;
412-
t_iterator = 1;
413-
if (!MCArrayFetchValueAtIndex(*t_array, t_iterator, t_value))
415+
if (!MCArrayFetchValueAtIndex(*t_array, t_sequenced_iterator, t_value))
414416
return;
415417
}
416418
else
@@ -513,9 +515,11 @@ void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExp
513515
case FU_ELEMENT:
514516
{
515517
loopvar -> set(ctxt, t_value);
518+
// SN-2015-06-15: [[ Bug 15457 ]] Sequenced, numeric arrays
519+
// have their own iterator
516520
if (t_sequence_array)
517521
{
518-
if (!MCArrayFetchValueAtIndex(*t_array, ++t_iterator, t_value))
522+
if (!MCArrayFetchValueAtIndex(*t_array, ++t_sequenced_iterator, t_value))
519523
endnext = true;
520524
}
521525
else

engine/src/foundation-legacy.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,14 @@ bool MCNameGetAsIndex(MCNameRef p_name, index_t& r_index)
11781178
if (MCStringGetLength(t_key) != 1 && MCStringGetCodepointAtIndex(t_key, 0) == '0')
11791179
return false;
11801180

1181+
// SN-2015-05-15: [[ Bug 15457 ]] Store the string-to-number conversion.
1182+
double t_double_index;
1183+
if (MCStringGetNumericValue(t_key, t_double_index))
1184+
{
1185+
r_index = (index_t)t_double_index;
1186+
return true;
1187+
}
1188+
11811189
char *t_end;
11821190
index_t t_index;
11831191

@@ -1189,6 +1197,9 @@ bool MCNameGetAsIndex(MCNameRef p_name, index_t& r_index)
11891197
t_index = strtol(*t_cstring, &t_end, 10);
11901198
if (*t_end == '\0')
11911199
{
1200+
// SN-2015-06-15: [[ Bug 15457 ]] Store the converted value - improve
1201+
// speed if repeating several times over the elements of a array.
1202+
MCStringSetNumericValue(t_key, t_index);
11921203
r_index = t_index;
11931204
return true;
11941205
}
@@ -1272,12 +1283,26 @@ static bool get_array_extent(void *context, MCArrayRef p_array, MCNameRef p_key,
12721283

12731284
bool MCArrayIsSequence(MCArrayRef self)
12741285
{
1275-
get_array_extent_context_t ctxt;
1276-
ctxt . minimum = INDEX_MAX;
1277-
ctxt . maximum = INDEX_MIN;
1278-
return MCArrayApply(self, get_array_extent, &ctxt) &&
1279-
ctxt . minimum == 1 &&
1280-
(ctxt . maximum - ctxt . minimum + 1) == MCArrayGetCount(self);
1286+
int32_t t_start_index;
1287+
1288+
// IsSequence returns true if the sequence starts with 1 only
1289+
return MCArrayIsNumericSequence(self, t_start_index) && t_start_index == 1;
1290+
}
1291+
1292+
bool MCArrayIsNumericSequence(MCArrayRef self, int32_t &r_start_index)
1293+
{
1294+
get_array_extent_context_t ctxt;
1295+
ctxt . minimum = INDEX_MAX;
1296+
ctxt . maximum = INDEX_MIN;
1297+
1298+
if (MCArrayApply(self, get_array_extent, &ctxt) &&
1299+
(ctxt . maximum - ctxt . minimum + 1) == MCArrayGetCount(self))
1300+
{
1301+
r_start_index = ctxt . minimum;
1302+
return true;
1303+
}
1304+
1305+
return false;
12811306
}
12821307

12831308
static bool list_keys(void *p_context, MCArrayRef p_array, MCNameRef p_key, MCValueRef p_value)

engine/src/foundation-legacy.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ class MCObjectOutputStream;
115115
// with no holes).
116116
bool MCArrayIsSequence(MCArrayRef array);
117117

118+
// SN-2015-06-15: [[ Bug 15457 ]] Returns true if the array a dense, numeric
119+
// sequence - but does not have to start with 1.
120+
bool MCArrayIsNumericSequence(MCArrayRef self, index_t &r_start_index);
121+
118122
// Constructs a string containing the list of all keys in the array separated by
119123
// the given delimiter.
120124
bool MCArrayListKeys(MCArrayRef array, char delimiter, MCStringRef& r_list);

0 commit comments

Comments
 (0)