Press enter to see results or esc to cancel.

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;