Turbo Pascal generates code for all mathemathical operations with two operands by the following procedure. The input of this procedure are left and right expression and the operation. ``` TCalcOperation = ( Calc_Add, { 00 } Calc_Subtract, { 01 } Calc_Multiply, { 02 } Calc_DIV, { 03 } Calc_MOD, { 04 } Calc_SHL, { 05 } Calc_SHR, { 06 } Calc_AND, { 07 } Calc_OR, { 08 } Calc_XOR, { 09 } Calc_IsEqual, { 0A } Calc_IsNotEqual, { 0B } Calc_IsGreater, { 0C } Calc_IsLower, { 0D } Calc_IsGreaterOrEqual, { 0E } Calc_IsLowerOrEqual, { 0F } Calc_Divide, { 10 } Calc_IN); { 11 } ``` Table AllowedOperations defines which operations are allowed. Conditional jump opcodes define which jump code will be generated for comparison operations. The procedure first checks for PChar operations, then it copies string-compatible character arrays to stack frame, next some type adjustments are made, type compatibility is checked and finally the methematical operation is performed. If both operands are constant then no code needs to be generated and special procedures are used. Finally, left expression holds the result (including code) of the mathematical operation.```Procedure CalculateOperation (Operation: TCalcOperation; Var LeftExpression, RightExpression: TExpression); Const AllowedOperations: Array [Calc_Add..Calc_Divide] of TBaseTypeSet = ( { + } [ btChar, btInteger, btReal, btExtended, btString, btSet], { - } [ btInteger, btReal, btExtended, btPointer, btSet], { * } [ btInteger, btReal, btExtended, btSet], { DIV } [ btInteger], { MOD } [ btInteger], { SHL } [ btInteger], { SHR } [ btInteger], { AND } [ btBoolean, btInteger], { OR } [ btBoolean, btInteger], { XOR } [ btBoolean, btInteger], { = } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet], { <> } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet], { > } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer], { < } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer], { >= } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet], { <= } [btEnumeration, btChar, btBoolean, btInteger, btReal, btExtended, btString, btPointer, btSet], { / } [ btInteger, btReal, btExtended]); UnsignedConditionalJumpOpCode: Array [Calc_IsEqual..Calc_IsLowerOrEqual] of Byte = ( JE, JNE, JA, JB, JNB, JBE); SignedConditionalJumpOpCode: Array [Calc_IsEqual..Calc_IsLowerOrEqual] of Byte = ( JE, JNE, JG, JL, JNL, JLE); begin If ExtendedSyntax in ModuleCompilerSwitches then If CharacterPointerOperations then Exit; LeftExpression.CopyCharArrayCompatibleWithStringToStackFrameAsString; RightExpression.CopyCharArrayCompatibleWithStringToStackFrameAsString; If LeftExpression.TypeDefPtr^.BaseType = RightExpression.TypeDefPtr^.BaseType then begin If (LeftExpression.TypeDefPtr^.BaseType = btInteger) and (Operation = Calc_Divide) then ConvertToRealOrExtended else If (LeftExpression.TypeDefPtr^.BaseType = btChar) and (Operation = Calc_Add) then begin LeftExpression.ConvertCharToString; RightExpression.ConvertCharToString; end; end else begin LeftExpression.ConvertCharToString; RightExpression.ConvertCharToString; ConvertToRealOrExtended; end; LeftExpression.CheckTypeCompatibility (RightExpression.TypeDefPtr); If not (RightExpression.TypeDefPtr^.BaseType in AllowedOperations [Operation]) then Error (OperandTypesDoNotMatchOperator); If (LeftExpression.Location = elConstant) and (RightExpression.Location = elConstant) then Case LeftExpression.TypeDefPtr^.BaseType of btSet: ConstantSetOperations; btPointer: ConstantPointerOperations; btString: ConstantStringOperations; btExtended: ConstantExtendedOperations; btReal: GenerateCodeForRealOperations; btInteger: ConstantIntegerOperations; btBoolean: ConstantBooleanOperations; btChar: ConstantIntegerOperations; btEnumeration: ConstantIntegerOperations; end else Case LeftExpression.TypeDefPtr^.BaseType of btSet: GenerateCodeForSetOperations; btPointer: GenerateCodeForPointerOperations; btString: GenerateCodeForStringOperations; btExtended: GenerateCodeForExtendedOperations; btReal: GenerateCodeForRealOperations; btInteger: GenerateCodeForIntegerOperations; btBoolean: GenerateCodeForBooleanOperations; btChar: GenerateCodeForIntegerOperations; btEnumeration: GenerateCodeForIntegerOperations; end; end; ```If both expressions are constant or 80x87 instructions are enabled then both expressions are converted to Extended, otherwise they are converted to Real.``` Function ConvertToRealOrExtended: Boolean; begin If (LeftExpression.Location = elConstant) and (RightExpression.Location = elConstant) then ConvertIntegerOrRealToExtended else If Instructions80x87 in StatementCompilerSwitches then ConvertIntegerOrRealToExtended else ConvertIntegerOrExtendedToReal; end; `````` Procedure ConvertIntegerOrRealToExtended; begin LeftExpression.ConvertIntegerToExtended; LeftExpression.ConvertRealToExtended; RightExpression.ConvertIntegerToExtended; RightExpression.ConvertRealToExtended; end; `````` Procedure ConvertIntegerOrExtendedToReal; begin LeftExpression.ConvertIntegerToReal; LeftExpression.ConvertExtendedToReal; RightExpression.ConvertIntegerToReal; RightExpression.ConvertExtendedToReal; end; ```