Expecting Different Expressions
Turbo Pascal expects different expression types depending on the context or language syntax. For this purposes there are many functions and procedures that process expression and report error if the expression doesn’t meet expectations.
This procedure expects string expression. Char and array compatible with string are converted to string.
Procedure TExpression.ExpectStringExpression;
begin
CalculateExpression;
ConvertCharToString;
CopyCharArrayCompatibleWithStringToStackFrameAsString;
If TypeDefPtr^.BaseType <> btString then Error (StringExpressionExpected);
end;
This procedure expects string variable and pushes pointer to memory.
Procedure TExpression.ExpectStringVariable;
begin
ExpectAssignableVariableReferenceExceptProcAndFuncAndPushPointerToMemory;
If TypeDefPtr^.BaseType <> btString then Error (StringVariableExpected);
end;
This procedure expects integer or floating-point expression.
Procedure TExpression.ExpectIntegerOrFloatingPointExpression;
begin
CalculateExpression;
If not (TypeDefPtr^.BaseType in [btInteger, btReal, btExtended]) then Error (IntegerOrRealExpressionExpected);
end;
This procedure expects integer or floating-point expression in parentheses.
Procedure TExpression.ExpectIntegerOrFloatingPointExpressionInParentheses;
begin
ExpectTokenAndGetNext (Token_LeftParenthesis);
ExpectIntegerOrFloatingPointExpression;
ExpectTokenAndGetNext (Token_RightParenthesis);
end;
This procedure expects integer expression.
Procedure TExpression.ExpectIntegerExpression;
begin
CalculateExpression;
If TypeDefPtr^.BaseType <> btInteger then Error (IntegerExpressionExpected);
end;
This procedure expects integer expression in parenthesis.
Procedure TExpression.ExpectIntegerExpressionInParentheses;
begin
ExpectTokenAndGetNext (Token_LeftParenthesis);
ExpectIntegerExpression;
ExpectTokenAndGetNext (Token_RightParenthesis);
end;
This procedure expects 16-bit integer variable and pushes pointer to memory. It is used for error variable for Val, BlockRead and BlockWrite system procedures.
Procedure TExpression.Expect16BitIntegerVariable;
begin
ExpectAssignableVariableReferenceExceptProcAndFuncAndPushPointerToMemory;
With TypeDefPtr^ do If (BaseType <> btInteger) or (Size <> 2) then Error (IntegerVariableExpected);
end;
This procedure expects ordinal expression.
Procedure TExpression.ExpectOrdinalExpression;
begin
CalculateExpression;
ConvertToBooleanByte;
If TypeDefPtr^.BaseType < btInteger then Error (OrdinalExpressionExpected);
end;
This procedure expects ordinal expression in parentheses.
Procedure TExpression.ExpectOrdinalExpressionInParentheses;
begin
ExpectTokenAndGetNext (Token_LeftParenthesis);
ExpectOrdinalExpression;
ExpectTokenAndGetNext (Token_RightParenthesis);
end;
This procedure expects boolean expression and generates jump to code which executes when the expression eavluates to False
. Code which executes when expression evaluates to True
immediately follows the code for expression calculation therefore a label is placed there.
Procedure TExpression.ExpectBooleanExpression;
begin
ProcessExpression;
If TypeDefPtr^.BaseType <> btBoolean then Error (BooleanExpressionExpected);
If Location = elConstant then Exit;
ConvertExpressionToBooleanJump;
Calculate;
GenerateCodeForNearJump (Value.LastJumpToFalse, LocationData.JumpIfTrueOpCode xor 1);
GenerateLabelAndSetJumpsToIt (Value.LastJumpToTrue);
EndIntermediateCodeSubroutine;
end;
This procedure expects pointer expression.
Procedure TExpression.ExpectPointerExpression;
begin
CalculateExpression;
If TypeDefPtr^.BaseType <> btPointer then Error (PointerExpressionExpected);
end;
This procedure expects assignable pointer variable.
Procedure TExpression.ExpectPointerVariable;
begin
ExpectAssignableVariableReferenceExceptProcedureOrFunction;
If TypeDefPtr^.BaseType <> btPointer then Error (PointerVariableExpected);
end;
This procedure expects and processes variable identifier.
Procedure TExpression.ExpectVariableIdentifier;
begin
CheckForDeclaredIdentifier;
Case Token of
Token_VariableIdentifier: LoadVariable;
Token_ProcedureIdentifier: ProcessProcedureIdentifier;
Token_TypeIdentifier,
Token_STRING,
Token_FILE: ProcessValueTypecastOrMethodCall;
Token_INHERITED: Process_INHERITED;
Token_LeftParenthesis: ProcessLeftParenthesis;
Token_SystemFunction: Process_SystemFunction;
Token_Mem: Process_Mem;
Token_At: Process_At;
else Error (VariableIdentifierExpected);
end;
end;
This procedure expects variable reference. If Function variable reference has parameters or it is dereferenced the function is called before it is dereferenced. Variable reference location must be memory.
Procedure TExpression.ExpectVariableReference;
begin
ExpectVariableIdentifier;
Repeat
If TypeDefPtr^.BaseType = btFunctionProcedure then
begin
If PProcedureTypeDefinition (TypeDefPtr)^.ResultTypeOffset.TypeOffset = 0 then Exit;
If (Token <> Token_LeftParenthesis) and (Token <> Token_Caret) then Exit;
CallProcedure;
SetExpressionToFunctionResult;
end;
until not ProcessQualifiers;
If Location <> elMemory then Error (InvalidVariableReference);
end;
This procedure expects constant expression. If any code was generated then this is not constant expression.
Procedure TExpression.ExpectConstantExpression;
Var SavedIntermediateCodeUsedSize: Word;
begin
SavedIntermediateCodeUsedSize := SymbolTable [stIntermediateCode].UsedSize;
CalculateExpression;
If SavedIntermediateCodeUsedSize <> SymbolTable [stIntermediateCode].UsedSize then Error (CannotEvaluateThisExpression);
If Location << elConstant then Error (CannotEvaluateThisExpression);
If TypeDefPtr^.BaseType >= btInteger then
TypeDefPtr := PointerFromOffsets (POrdinalTypeDefinition (TypeDefPtr)^.OrdinalType);
end;
This procedure expects file variable and pushes its pointer to memory.
Procedure TExpression.ExpectFileVariableAndPushPointerToMemory;
begin
ExpectAssignableVariableReferenceExceptProcAndFuncAndPushPointerToMemory;
Case TypeDefPtr^.BaseType of
btFile, btText: Exit;
else Error (FileVariableExpected);
end;
end;
This procedure expects variable reference which is not read-only except procedure or function.
Procedure TExpression.ExpectAssignableVariableReferenceExceptProcedureOrFunction;
begin
ExpectVariableReference;
If (Location = elProcedure) or (efReadOnly in LocationData.Flags) then Error (InvalidVariableReference);
end;
This procedure expects assignable variable except procedure or function and pushes its pointer to memory.
Procedure TExpression.ExpectAssignableVariableReferenceExceptProcAndFuncAndPushPointerToMemory;
begin
ExpectAssignableVariableReferenceExceptProcedureOrFunction;
ConvertToPointerAndPush;
end;
This procedure expects variable reference except procedure or function.
Procedure TExpression.ExpectVariableReferenceExceptProcedureOrFunction;
begin
ExpectVariableReference;
If Location = elProcedure then Error (InvalidVariableReference);
end;
This expects string expression, stores it to the code and pushes pointer to it.
Procedure TExpression.ExpectAndStoreStringAndPushPointer;
begin
ExpectStringExpression;
StoreStringConstantToCodeBlock;
If IsExpressionInOverlaidCode then CopyStringToStackFrame ($0100);
ConvertToPointerAndPush;
end;
This procedure expects string expression, stores it to the code and pushes pointer to it. If extended syntax is enabled it also converts Char
, zero-based character array and PChar
.
Procedure TExpression.ExpectAndStoreStringCompatibleExpressionAndPushPointer;
begin
If ExtendedSyntax in StatementCompilerSwitches then
begin
CalculateExpression;
ConvertCharToString;
ConvertZeroBasedCharacterArrayToPChar;
CopyCharArrayCompatibleWithStringToStackFrameAsString;
If TypeDefPtr^.BaseType = btString then
begin
StoreStringConstantToCodeBlock;
If IsExpressionInOverlaidCode then CopyStringToStackFrame ($0100);
ConvertToPointerAndPush;
end else If TypeDefPtr = Ptr (SystemUnitSegment, PChar_TypeOffset) then PushExpression
else Error (StringExpressionExpected);
end else ExpectAndStoreStringAndPushPointer;
end;
This function expects integer constant and returns its value.
Function ExpectIntegerConstant: LongInt;
Var TempExpression: TExpression;
begin
TempExpression.ExpectConstantExpression;
If TempExpression.TypeDefPtr^.BaseType <> btInteger then Error (IntegerConstantExpected);
ExpectIntegerConstant := TempExpression.Value.LongInt;
end;
This procedure processes expression and converts boolean jumps to value in AL
.
Procedure TExpression.CalculateExpression;
begin
ProcessExpression;
ConvertBooleanJumpToByteValue;
end;
This procedure calculates expression with specified type. If expected base type is btProcedure it creates pointer to procedure (if expression is not nil or procedure variable) otherwise it calls CalculateExpression. If expected type is array and expression is compatible string it is converted to array.
Procedure TExpression.CalculateExpressionWithType (ExpectedType: PTypeDefinition);
Var AL: Byte;
BX: Word;
StringLen: Byte;
begin
If ExpectedType^.BaseType = btFunctionProcedure then
begin
If CheckAndGetNextToken (Token_NIL) then
begin
TypeDefPtr := ExpectedType;
IntermediateCodeOffset := 0;
Location := elConstant;
DataType := itLongInt;
UsedRegisters := [];
Value.LongInt := 0;
Value.W14 := 0;
Value.W16 := 0;
Exit;
end;
ExpectVariableReference;
If Location = elProcedure then
begin
ExpectedType := TypeDefPtr;
AL := Byte (Ptr (Seg (ExpectedType^), Ofs (ExpectedType^) - 10)^);
If (AL and $16 <> 0) or (AL and $01 = 0) then Error (InvalidProcedureOrFunctionReference);
If Word (Ptr (Seg (ExpectedType^), Ofs (ExpectedType^) - 6)^) <> 0 then Error (InvalidProcedureOrFunctionReference);
BX := Word (Ptr (Seg (ExpectedType^), Ofs (ExpectedType^) - 8)^);
Location := elPointerToMemory;
LocationData.Flags := [efRelocatable];
Value.Word := 0;
Value.W12 := BX;
Value.W14 := Seg (ExpectedType^);
DataType := itLongInt;
EndIntermediateCodeSubroutine;
end;
Exit;
end;
If PArrayTypeDefinition (ExpectedType)^.IsCharacterArrayCompatibleWithString (StringLen) then
begin
CalculateExpression; { BUG: Never executed ???!!! }
If IsConstantString (ExpectedType^.Size, StringLen) then TypeDefPtr := ExpectedType;
end else CalculateExpression;
end;