Introducing short-circuiting logic

Fixes #1863

Thanks to @Tokeiburu
This commit is contained in:
Lemongrass3110 2020-02-17 22:46:05 +01:00
parent 390eb9772a
commit 59184b9e79

View File

@ -3922,24 +3922,50 @@ void op_2(struct script_state *st, int op)
}
get_val(st, left);
get_val(st, right);
bool right_is_int;
bool right_is_string;
// Delay the access for short-circuiting
if( op == C_LAND ){
// If it is a reference
if( data_isreference( right ) ){
// Check the type by using the variable name
right_is_string = is_string_variable( reference_getname( right ) );
right_is_int = !right_is_string;
}else{
// Otherwise just check the type of the data
right_is_int = data_isint( right );
right_is_string = data_isstring( right );
}
}else{
// Convert to a value instantly
get_val( st, right );
right_is_int = data_isint( right );
right_is_string = data_isstring( right );
}
// automatic conversions
switch( op )
{
case C_ADD:
if( data_isint(left) && data_isstring(right) )
if( data_isint(left) && right_is_string )
{// convert int-string to string-string
conv_str(st, left);
right_is_string = false;
right_is_int = true;
}
else if( data_isstring(left) && data_isint(right) )
else if( data_isstring(left) && right_is_int )
{// convert string-int to string-string
conv_str(st, right);
right_is_int = false;
right_is_string = true;
}
break;
}
if( data_isstring(left) && data_isstring(right) )
if( data_isstring(left) && right_is_string )
{// ss => op_2str
op_2str(st, op, left->u.str, right->u.str);
script_removetop(st, leftref.type == C_NOP ? -3 : -2, -1);// pop the two values before the top one
@ -3951,10 +3977,26 @@ void op_2(struct script_state *st, int op)
*left = leftref;
}
}
else if( data_isint(left) && data_isint(right) )
else if( data_isint(left) && right_is_int )
{// ii => op_2num
int64 i1 = left->u.num;
int64 i2 = right->u.num;
int64 i2;
// Special checks for short-circuiting
if( op == C_LAND ){
// Only access the second parameter of the logical and, if the first is not zero
if( i1 != 0 ){
// Convert to a value now
get_val( st, right );
i2 = right->u.num;
}else{
// Still run the operator, but make it fail for sure
i2 = 0;
}
}else{
// Store the value, so that it can be used inside the operator logic
i2 = right->u.num;
}
script_removetop(st, leftref.type == C_NOP ? -2 : -1, 0);
op_2num(st, op, i1, i2);