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;