Press enter to see results or esc to cancel.

Processing Constant Declarations

Turbo Pascal constants can be of two types: ordinary constants which are only stored to the symbol table and typed constants which are also embedded into the program. Therefore, typed constant values are stored into a separate symbol table.

Procedure ProcessConstantDeclarations;
Var TypePtr: PTypeDefinition;
    Variable: PVariableIdentifierData;
    Constant: PConstantIdentifierData absolute Variable;
    ConstantIdentifier: PIdentifier;
    Expression: TExpression;
    DataPtr, AddData: Pointer;
    Size: Word;
    UnitTypeOffsets: TUnitOffsets;

  Procedure GetTypedConstantInitialValue;
  Var VarData: Pointer;
      Size: Word;
  begin
    Size := TypePtr^.Size;
    VarData := IncreaseSymbolTable (stTypedConstants, Size);
    CurrentTypedConstantValueOffset := Ofs (VarData^);
    FillChar (VarData^, Size, 0);
    TypedConstantsOffsetBeforeConstantValueProcessing := Ofs (VarData^) + Size;
    ProcessTypedConstant (TypePtr);
    TypedConstantsOffsetBeforeConstantValueProcessing := LastTypedConstantsSize;
  end;

begin
  GetNextToken;
  Repeat
    ConstantIdentifier := ExpectAndStoreIdentifier (0, AddData);
    If CheckAndGetNextToken (Token_Colon) then
      begin                                            { Typed constant }
        Variable := IncreaseSymbolTable (stMain, SizeOf (TVariableIdentifierData));
        TokenForEqual := Token_EqualAsSeparator;
        TypePtr := GetVariableType;
        TokenForEqual := Token_Equal;
        If (WordAlignment in ModuleCompilerSwitches) and (TypePtr^.Size <> 1) then WordAlignAddressForTypedConstants;
        ForceCreationOfTypedConstantsBlockRecord := True;
        VariableData_Flags := TypedConstant;
        RecordTypeDefinitionOffset.TypedConstantOffset :=
          SymbolTable [stTypedConstants].NextRecordOffset - LastTypedConstantsSize;
        RecordTypeDefinitionOffset.TypedConstantsBlockRecordOffset := SymbolTable [stTypedConstantsBlocks].NextRecordOffset;
        ExpectTokenAndGetNext (Token_EqualAsSeparator);
        GetTypedConstantInitialValue;
        ConstantIdentifier^.Token := Token_VariableIdentifier;
        With Variable^ do
          begin
            Flags := VariableData_Flags;
            W1.Ofs := RecordTypeDefinitionOffset.TypedConstantOffset;
            W1.Seg := RecordTypeDefinitionOffset.TypedConstantsBlockRecordOffset;
            W5 := VariableData_NextMemberOffset;
            UnitTypeOffsets := CurrentVarUnitTypeOffsets;
          end;
      end else
        begin
          ExpectTokenAndGetNext (Token_Equal);
          Expression.ExpectConstantExpression;
          ConstantIdentifier^.Token := Token_ConstantIdentifier;
          DataPtr := @Expression.Value;
          TypePtr := Expression.TypeDefPtr;
          Size := 4;
          If TypePtr^.BaseType < btInteger then
            Case TypePtr^.BaseType of
              btPointer: Size := 4;
              btExtended: Size := 10;
              else begin
                    DataPtr := Ptr (DSeg, Expression.Value.Word);
                    If TypePtr^.BaseType = btSet then Size := 32
                      else Size := Byte (DataPtr^) + 1;
                 end;
            end;
          GetTypeAndUnitIdentifierOffsets (TypePtr, UnitTypeOffsets);
          Constant := IncreaseSymbolTable (stMain, SizeOf (TUnitOffsets) + Size);
          Constant^.UnitTypeOffsets := UnitTypeOffsets;
          Move (DataPtr^, Constant^.Value, Size);
        end;
    ExpectTokenAndGetNext (TOKEN_Semicolon);
  until Token <> Token_Identifier;
  CreateTypedConstantsBlockRecord;
end;

For each Const declaration Turbo Pascal creates a record in symbol table for typed constants (if they are declared).

Procedure CreateTypedConstantsBlockRecord;
begin
  WordAlignAddressForTypedConstants;
  If (SymbolTable [stTypedConstants].UsedSize <> LastTypedConstantsSize) or ForceCreationOfTypedConstantsBlockRecord then
    begin
      ForceCreationOfTypedConstantsBlockRecord := False;
      With PTypedConstantsBlockRecord (IncreaseSymbolTable (stTypedConstantsBlocks, SizeOf (TTypedConstantsBlockRecord)))^ do
        begin
          Offset := 0;
          ConstantsSize := SymbolTable [stTypedConstants].UsedSize - LastTypedConstantsSize;
          ReferencesSize := SymbolTable [stTypedConstantsReferences].UsedSize - LastTypedConstantsReferencesSize;
          tcrW6 := CurrentRecordOrObjectTypeDefinitionOffset;
        end;
      LastTypedConstantsSize := SymbolTable [stTypedConstants].UsedSize;
      TypedConstantsOffsetBeforeConstantValueProcessing := SymbolTable [stTypedConstants].NextRecordOffset;
      LastTypedConstantsReferencesSize := SymbolTable [stTypedConstantsReferences].UsedSize;
    end;
end;