Generating code for Boolean expression is no different from code for integer expressions with the exception of short-circuit evaluations. Boolean operations AND and OR can be decided after only one operant is calculated. If the first operand in boolean operation OR evaluates to True then there is no need to evaluate the second one. Similarly, if the first operand in boolean operation AND evaluates to False then there is no need to evaluate the second one. This procedure takes care for this. Short-circuit evaluation is a great example of the elegance of Turbo Pascal and boolean expressions using jump lists. Procedure GenerateCodeForBooleanOperations;
Var LastJumpToTrue, LastJumpToFalse, TempWord: PWord;
JumpIfTrueOpCode: Byte;
begin
If (FullBooleanEval in StatementCompilerSwitches) or not (Operation in [Calc_AND, Calc_OR]) then
begin
LeftExpression.ConvertToBooleanByte;
RightExpression.ConvertToBooleanByte;
GenerateCodeForIntegerOperations;
Exit;
end;
LeftExpression.ConvertExpressionToBooleanJump;
RightExpression.ConvertExpressionToBooleanJump;
LeftExpression.Calculate;
LastJumpToTrue := @LeftExpression.Value.LastJumpToTrue;
LastJumpToFalse := @LeftExpression.Value.LastJumpToFalse;
JumpIfTrueOpCode := LeftExpression.LocationData.JumpIfTrueOpCode;
If Operation <> Calc_OR then
begin
JumpIfTrueOpCode := JumpIfTrueOpCode xor $01;
TempWord := LastJumpToTrue;
LastJumpToTrue := LastJumpToFalse;
LastJumpToFalse := TempWord;
end;
GenerateCodeForNearJump (LastJumpToTrue^, JumpIfTrueOpCode);
GenerateLabelAndSetJumpsToIt (LastJumpToFalse^);
RightExpression.Calculate;
LeftExpression.EndIntermediateCodeSubroutine;
With LeftExpression do UsedRegisters := UsedRegisters + RightExpression.UsedRegisters;
JoinJumpsOfBothExpressions (LeftExpression.Value.LastJumpToTrue, RightExpression.Value.LastJumpToTrue);
JoinJumpsOfBothExpressions (LeftExpression.Value.LastJumpToFalse, RightExpression.Value.LastJumpToFalse);
LeftExpression.LocationData.JumpIfTrueOpCode := RightExpression.LocationData.JumpIfTrueOpCode;
end;
|