Skip to content

Commit 14a9e64

Browse files
[[ NumberExpectation ]] Added new property to ExecContext, in order to specify when we want to get a number
This avoids a useless number -> ValueRef -> number conversion
1 parent b994f24 commit 14a9e64

File tree

7 files changed

+215
-10
lines changed

7 files changed

+215
-10
lines changed

engine/src/cmdsm.cpp

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,18 @@ void MCAdd::exec_ctxt(MCExecContext &ctxt)
186186
#endif /* MCAdd */
187187

188188
MCExecValue t_src;
189+
Boolean t_old_expectation;
190+
191+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
192+
t_old_expectation = ctxt . GetNumberExpected();
193+
ctxt . SetNumberExpected(True);
194+
189195
if (!ctxt . EvaluateExpression(source, EE_ADD_BADSOURCE, t_src)
190196
|| !ctxt . ConvertToNumberOrArray(t_src))
197+
{
198+
ctxt . SetNumberExpected(t_old_expectation);
191199
return;
200+
}
192201

193202
MCExecValue t_dst;
194203
MCAutoPointer<MCContainer> t_dst_container;
@@ -198,12 +207,14 @@ void MCAdd::exec_ctxt(MCExecContext &ctxt)
198207
{
199208
ctxt . LegacyThrow(EE_ADD_BADDEST);
200209
MCExecTypeRelease(t_src);
210+
ctxt . SetNumberExpected(t_old_expectation);
201211
return;
202212
}
203213

204214
if (!t_dst_container -> eval_ctxt(ctxt, t_dst))
205215
{
206216
MCExecTypeRelease(t_src);
217+
ctxt . SetNumberExpected(t_old_expectation);
207218
return;
208219
}
209220
}
@@ -212,9 +223,13 @@ void MCAdd::exec_ctxt(MCExecContext &ctxt)
212223
if (!ctxt . EvaluateExpression(dest, EE_ADD_BADDEST, t_dst))
213224
{
214225
MCExecTypeRelease(t_src);
226+
ctxt . SetNumberExpected(t_old_expectation);
215227
return;
216228
}
217-
}
229+
}
230+
231+
// Set the number expectation back to its previous state
232+
ctxt . SetNumberExpected(t_old_expectation);
218233

219234
if (!ctxt . ConvertToNumberOrArray(t_dst))
220235
{
@@ -231,7 +246,7 @@ void MCAdd::exec_ctxt(MCExecContext &ctxt)
231246
MCMathExecAddArrayToArray(ctxt, t_src . arrayref_value, t_dst . arrayref_value, t_result . arrayref_value);
232247
else
233248
{
234-
ctxt . LegacyThrow(EE_ADD_MISMATCH);
249+
ctxt . LegacyThrow(EE_ADD_MISMATCH);
235250
return;
236251
}
237252
}
@@ -429,9 +444,18 @@ void MCDivide::exec_ctxt(MCExecContext &ctxt)
429444
#endif /* MCDivide */
430445

431446
MCExecValue t_src;
447+
Boolean t_old_expectation;
448+
449+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
450+
t_old_expectation = ctxt . GetNumberExpected();
451+
ctxt . SetNumberExpected(True);
452+
432453
if (!ctxt . EvaluateExpression(source, EE_DIVIDE_BADSOURCE, t_src)
433454
|| !ctxt . ConvertToNumberOrArray(t_src))
455+
{
456+
ctxt . SetNumberExpected(t_old_expectation);
434457
return;
458+
}
435459

436460
MCExecValue t_dst;
437461
MCAutoPointer<MCContainer> t_dst_container;
@@ -441,12 +465,14 @@ void MCDivide::exec_ctxt(MCExecContext &ctxt)
441465
{
442466
ctxt . LegacyThrow(EE_DIVIDE_BADDEST);
443467
MCExecTypeRelease(t_src);
468+
ctxt . SetNumberExpected(t_old_expectation);
444469
return;
445470
}
446471

447472
if (!t_dst_container -> eval_ctxt(ctxt, t_dst))
448473
{
449474
MCExecTypeRelease(t_src);
475+
ctxt . SetNumberExpected(t_old_expectation);
450476
return;
451477
}
452478
}
@@ -455,9 +481,13 @@ void MCDivide::exec_ctxt(MCExecContext &ctxt)
455481
if (!ctxt . EvaluateExpression(dest, EE_DIVIDE_BADDEST, t_dst))
456482
{
457483
MCExecTypeRelease(t_src);
484+
ctxt . SetNumberExpected(t_old_expectation);
458485
return;
459486
}
460487
}
488+
489+
// Set the number expectation back to its previous state
490+
ctxt . SetNumberExpected(t_old_expectation);
461491

462492
if (!ctxt . ConvertToNumberOrArray(t_dst))
463493
{
@@ -670,10 +700,18 @@ void MCMultiply::exec_ctxt(MCExecContext &ctxt)
670700
#endif /* MCMultiply */
671701

672702
MCExecValue t_src;
703+
Boolean t_old_expectation;
704+
705+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
706+
t_old_expectation = ctxt . GetNumberExpected();
707+
ctxt . SetNumberExpected(True);
673708

674709
if(!ctxt . EvaluateExpression(source, EE_MULTIPLY_BADSOURCE, t_src)
675710
|| !ctxt . ConvertToNumberOrArray(t_src))
711+
{
712+
ctxt . SetNumberExpected(t_old_expectation);
676713
return;
714+
}
677715

678716
MCExecValue t_dst;
679717
MCAutoPointer<MCContainer> t_dst_container;
@@ -683,12 +721,14 @@ void MCMultiply::exec_ctxt(MCExecContext &ctxt)
683721
{
684722
ctxt . LegacyThrow(EE_MULTIPLY_BADDEST);
685723
MCExecTypeRelease(t_src);
724+
ctxt . SetNumberExpected(t_old_expectation);
686725
return;
687726
}
688727

689728
if (!t_dst_container -> eval_ctxt(ctxt, t_dst))
690729
{
691730
MCExecTypeRelease(t_src);
731+
ctxt . SetNumberExpected(t_old_expectation);
692732
return;
693733
}
694734
}
@@ -697,9 +737,13 @@ void MCMultiply::exec_ctxt(MCExecContext &ctxt)
697737
if (!ctxt . EvaluateExpression(dest, EE_MULTIPLY_BADDEST, t_dst))
698738
{
699739
MCExecTypeRelease(t_src);
740+
ctxt . SetNumberExpected(t_old_expectation);
700741
return;
701742
}
702743
}
744+
745+
// Set the number expectation back to the previous state
746+
ctxt . SetNumberExpected(t_old_expectation);
703747

704748
if (!ctxt . ConvertToNumberOrArray(t_dst))
705749
{
@@ -895,10 +939,18 @@ void MCSubtract::exec_ctxt(MCExecContext &ctxt)
895939
#endif /* MCSubtract */
896940

897941
MCExecValue t_src;
942+
Boolean t_old_expectation;
943+
944+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
945+
t_old_expectation = ctxt . GetNumberExpected();
946+
ctxt . SetNumberExpected(True);
898947

899948
if (!ctxt . EvaluateExpression(source, EE_SUBTRACT_BADSOURCE, t_src)
900949
|| !ctxt . ConvertToNumberOrArray(t_src))
950+
{
951+
ctxt . SetNumberExpected(t_old_expectation);
901952
return;
953+
}
902954

903955
MCExecValue t_dst;
904956
MCAutoPointer<MCContainer> t_dst_container;
@@ -908,12 +960,14 @@ void MCSubtract::exec_ctxt(MCExecContext &ctxt)
908960
{
909961
ctxt . LegacyThrow(EE_SUBTRACT_BADDEST);
910962
MCExecTypeRelease(t_src);
963+
ctxt . SetNumberExpected(t_old_expectation);
911964
return;
912965
}
913966

914967
if (!t_dst_container -> eval_ctxt(ctxt, t_dst))
915968
{
916969
MCExecTypeRelease(t_src);
970+
ctxt . SetNumberExpected(t_old_expectation);
917971
return;
918972
}
919973
}
@@ -922,9 +976,13 @@ void MCSubtract::exec_ctxt(MCExecContext &ctxt)
922976
if (!ctxt . EvaluateExpression(dest, EE_SUBTRACT_BADDEST, t_dst))
923977
{
924978
MCExecTypeRelease(t_src);
979+
ctxt . SetNumberExpected(t_old_expectation);
925980
return;
926981
}
927982
}
983+
984+
// Set the number expectation back to its previous state
985+
ctxt . SetNumberExpected(t_old_expectation);
928986

929987
if (!ctxt . ConvertToNumberOrArray(t_dst))
930988
{

engine/src/exec.cpp

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -737,9 +737,12 @@ bool MCExecContext::TryToEvaluateExpressionAsDouble(MCExpression *p_expr, uint2
737737
bool t_success, t_can_debug;
738738
t_success = false;
739739

740+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
741+
Boolean t_old_expectation = m_numberexpected;
742+
m_numberexpected = True;
740743
do
741744
{
742-
MCExecValue t_value;
745+
MCExecValue t_value;
743746
p_expr -> eval_ctxt(*this, t_value);
744747

745748
if (!MCExecTypeIsNumber(t_value))
@@ -761,6 +764,7 @@ bool MCExecContext::TryToEvaluateExpressionAsDouble(MCExpression *p_expr, uint2
761764
}
762765
while (!t_success && t_can_debug && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors);
763766

767+
m_numberexpected = t_old_expectation;
764768
if (t_success)
765769
return true;
766770

@@ -1075,7 +1079,29 @@ bool MCExecContext::EvalExprAsUInt(MCExpression *p_expr, Exec_errors p_error, ui
10751079
{
10761080
MCAssert(p_expr != nil);
10771081

1078-
p_expr -> eval_uint(*this, r_value);
1082+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
1083+
MCExecValue t_value;
1084+
Boolean t_number_expected = m_numberexpected;
1085+
m_numberexpected = True;
1086+
1087+
p_expr -> eval_ctxt(*this, t_value);
1088+
1089+
m_numberexpected = t_number_expected;
1090+
1091+
if (!HasError())
1092+
{
1093+
// Convert the exec value to an unsigned integer, avoiding to go through a valueref pivot if possible
1094+
if (!MCExecTypeIsNumber(t_value))
1095+
MCExecTypeConvertAndReleaseAlways(*this, t_value . type, &t_value, kMCExecValueTypeUInt, &r_value);
1096+
else if (t_value . type == kMCExecValueTypeDouble)
1097+
r_value = (uinteger_t) t_value . double_value;
1098+
else if (t_value . type == kMCExecValueTypeInt)
1099+
r_value = (uinteger_t) t_value . int_value;
1100+
else if (t_value . type == kMCExecValueTypeFloat)
1101+
r_value = (uinteger_t) t_value . float_value;
1102+
else // uint
1103+
r_value = t_value . uint_value;
1104+
}
10791105

10801106
if (!HasError())
10811107
return true;
@@ -1100,7 +1126,29 @@ bool MCExecContext::EvalExprAsInt(MCExpression *p_expr, Exec_errors p_error, int
11001126
{
11011127
MCAssert(p_expr != nil);
11021128

1103-
p_expr -> eval_int(*this, r_value);
1129+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
1130+
MCExecValue t_value;
1131+
Boolean t_number_expected = m_numberexpected;
1132+
m_numberexpected = True;
1133+
1134+
p_expr -> eval_ctxt(*this, t_value);
1135+
1136+
m_numberexpected = t_number_expected;
1137+
1138+
if (!HasError())
1139+
{
1140+
// Convert the exec value to an unsigned integer, avoiding to go through a valueref pivot if possible
1141+
if (!MCExecTypeIsNumber(t_value))
1142+
MCExecTypeConvertAndReleaseAlways(*this, t_value . type, &t_value, kMCExecValueTypeInt, &r_value);
1143+
else if (t_value . type == kMCExecValueTypeDouble)
1144+
r_value = (integer_t) t_value . double_value;
1145+
else if (t_value . type == kMCExecValueTypeUInt)
1146+
r_value = (integer_t) t_value . uint_value;
1147+
else if (t_value . type == kMCExecValueTypeFloat)
1148+
r_value = (integer_t) t_value . float_value;
1149+
else // int
1150+
r_value = t_value . int_value;
1151+
}
11041152

11051153
if (!HasError())
11061154
return true;
@@ -1168,7 +1216,29 @@ bool MCExecContext::EvalExprAsDouble(MCExpression *p_expr, Exec_errors p_error,
11681216
{
11691217
MCAssert(p_expr != nil);
11701218

1171-
p_expr -> eval_double(*this, r_value);
1219+
// SN-2014-04-08 [[ NumberExpectation ]] Ensure we get a number when it's possible instead of a ValueRef
1220+
Boolean t_number_expected = m_numberexpected;
1221+
MCExecValue t_value;
1222+
m_numberexpected = True;
1223+
1224+
p_expr -> eval_ctxt(*this, t_value);
1225+
1226+
m_numberexpected = t_number_expected;
1227+
1228+
if (!HasError())
1229+
{
1230+
// Convert the exec value to an unsigned integer, avoiding to go through a valueref pivot if possible
1231+
if (!MCExecTypeIsNumber(t_value))
1232+
MCExecTypeConvertAndReleaseAlways(*this, t_value . type, &t_value, kMCExecValueTypeDouble, &r_value);
1233+
else if (t_value . type == kMCExecValueTypeUInt)
1234+
r_value = (double) t_value . uint_value;
1235+
else if (t_value . type == kMCExecValueTypeInt)
1236+
r_value = (double) t_value . int_value;
1237+
else if (t_value . type == kMCExecValueTypeFloat)
1238+
r_value = (double) t_value . float_value;
1239+
else // double
1240+
r_value = t_value . double_value;
1241+
}
11721242

11731243
if (!HasError())
11741244
return true;

engine/src/exec.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,7 @@ class MCExecContext
12301230
m_nftrailing = 6;
12311231
m_cutoff = 35;
12321232
m_stat = ES_NORMAL;
1233+
m_numberexpected = False;
12331234
}
12341235

12351236
//////////
@@ -1367,6 +1368,11 @@ class MCExecContext
13671368
{
13681369
return m_nfforce;
13691370
}
1371+
1372+
Boolean GetNumberExpected() const
1373+
{
1374+
return m_numberexpected;
1375+
}
13701376

13711377
//////////
13721378

@@ -1431,6 +1437,11 @@ class MCExecContext
14311437
{
14321438
m_rowdel = p_value;
14331439
}
1440+
1441+
void SetNumberExpected(Boolean p_value)
1442+
{
1443+
m_numberexpected = p_value;
1444+
}
14341445

14351446
//////////
14361447

@@ -1714,6 +1725,10 @@ class MCExecContext
17141725
Boolean m_usesystemdate;
17151726
Boolean m_useunicode;
17161727
Boolean m_deletearray;
1728+
// SN-2014-04-08 [[ NumberExpectation ]]
1729+
// New property allowing to specify, when evaluating a literal number,
1730+
// that we expect a number over a valueref
1731+
Boolean m_numberexpected;
17171732
char m_itemdel;
17181733
char m_columndel;
17191734
char m_linedel;

engine/src/funcsm.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,34 @@ bool MCParamFunction::params_to_doubles(MCExecContext& ctxt, real64_t *&r_double
108108
else
109109
{
110110
MCParameter *t_param = params;
111+
bool t_success;
112+
t_success = true;
111113
while (t_param != NULL)
112114
{
113-
MCAutoValueRef t_value;
115+
MCExecValue t_value;
114116
real64_t t_double;
115-
if (!t_param->eval(ctxt, &t_value) || !ctxt . ConvertToReal(*t_value, t_double))
117+
118+
// SN-2014-04-08 [[ NumberExpectation ]]
119+
// Lookup for an exec value, and does the conversion - might save up boxing / unboxing throught ValueRef
120+
t_success = t_param->eval_ctxt(ctxt, t_value);
121+
122+
if (t_success)
123+
{
124+
if (!MCExecTypeIsNumber(t_value))
125+
MCExecTypeConvertAndReleaseAlways(ctxt, t_value . type, &t_value, kMCExecValueTypeDouble, &t_double);
126+
else if (t_value . type == kMCExecValueTypeFloat)
127+
t_double = (double) t_value . float_value;
128+
else if (t_value . type == kMCExecValueTypeInt)
129+
t_double = (double) t_value . int_value;
130+
else if (t_value . type == kMCExecValueTypeUInt)
131+
t_double = (double) t_value . uint_value;
132+
else // double
133+
t_double = t_value . double_value;
134+
135+
t_success = !ctxt . HasError();
136+
}
137+
138+
if (!t_success)
116139
{
117140
ctxt . LegacyThrow(EE_FUNCTION_BADSOURCE);
118141
return false;

0 commit comments

Comments
 (0)