Bladeren bron

Introducing short-circuiting logic

Fixes #1863

Thanks to @Tokeiburu
Lemongrass3110 5 jaren geleden
bovenliggende
commit
59184b9e79
1 gewijzigde bestanden met toevoegingen van 48 en 6 verwijderingen
  1. 48 6
      src/map/script.cpp

+ 48 - 6
src/map/script.cpp

@@ -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);