Processing Set Constants
This procedure processes set constants. This can be an empty set, or a collection of set elements and ranges. If the elements are not constant the code is generated to include them into the set. Individual elements as well as range limits are treated as expressions.
Procedure ProcessSetConstant;
Var TempSet: Set of Byte;
LowerLimitExpression, UpperLimitExpression: TExpression;
Element, LowerLimit, UpperLimit: Byte;
NonConstantElementCode: TIntermediateCodeOffsets;
TypePtr: PtrRec;
N: Byte;
DataOffset: Word;
Procedure ExpectSetElement (Var Expression: TExpression);
begin
Expression.ExpectOrdinalExpression;
If TypePtr.Ptr = nil then
begin
TypePtr.Ofs := POrdinalTypeDefinition (Expression.TypeDefPtr)^.OrdinalType.TypeOffset + 20;
TypePtr.Seg := PUnitIdentifierData (Ptr (Seg (Expression.TypeDefPtr^),
POrdinalTypeDefinition (Expression.TypeDefPtr)^.OrdinalType.UnitIdentifierData))^.UnitSegment;
end;
If (TypePtr.Seg <> PUnitIdentifierData (Ptr (Seg (Expression.TypeDefPtr^),
POrdinalTypeDefinition (Expression.TypeDefPtr)^.OrdinalType.UnitIdentifierData))^.UnitSegment) or
(TypePtr.Ofs <> POrdinalTypeDefinition (Expression.TypeDefPtr)^.OrdinalType.TypeOffset + 20) then Error (TypeMismatch);
Expression.CheckOrdinalRange (Ptr (SystemUnitSegment, Byte_TypeOffset));
end;
begin
GetNextToken;
TempSet := [];
TypePtr.Ptr := nil;
NonConstantElementCode.NumberOfStatements := 0;
If not CheckAndGetNextToken (Token_RightBracket) then
begin
Repeat
ExpectSetElement (LowerLimitExpression);
If CheckAndGetNextToken (Token_PeriodPeriod) then
begin { Range }
ExpectSetElement (UpperLimitExpression);
If (LowerLimitExpression.Location = elConstant) and (UpperLimitExpression.Location = elConstant) then
begin
LowerLimit := LowerLimitExpression.Value.Byte;
UpperLimit := UpperLimitExpression.Value.Byte;
end else begin
LowerLimitExpression.Calculate;
LowerLimitExpression.Push;
UpperLimitExpression.Calculate;
UpperLimitExpression.Push;
GenerateInstruction_CALL_FAR (SysProc_ZAddRange);
AddCallToIntermediateCodeSubroutine (NonConstantElementCode, EndSubroutine);
Continue;
end;
end else begin { Single set element }
If LowerLimitExpression.Location = elConstant then
begin
LowerLimit := LowerLimitExpression.Value.Byte;
UpperLimit := LowerLimit;
end else begin
LowerLimitExpression.Calculate;
LowerLimitExpression.Push;
GenerateInstruction_CALL_FAR (SysProc_ZAddComp);
AddCallToIntermediateCodeSubroutine (NonConstantElementCode, EndSubroutine);
Continue;
end;
end;
If LowerLimit <= UpperLimit then
For Element := LowerLimit to UpperLimit do Include (TempSet, Element);
until not CheckAndGetNextToken (Token_Comma);
ExpectTokenAndGetNext (TOKEN_RightBracket);
end else begin { Empty set }
TypePtr.Ofs := EmptySet_TypeOffset;
TypePtr.Seg := SystemUnitSegment;
end;
DataOffset := GetTempBufferOffset (32);
Move (TempSet, Ptr (DSeg, DataOffset)^, 32);
TypeDefPtr := TypePtr.Ptr;
IntermediateCodeOffset := 0;
Location := elConstant;
UsedRegisters := [];
Value.Word := DataOffset;
SetDataTypeOfSet;
If NonConstantElementCode.NumberOfStatements <> 0 then
begin
ExpandSetToStackFrameAndPushPointer (0);
Calculate;
Generate_icGoSub_ForEachSubroutine (NonConstantElementCode);
EndIntermediateCodeSubroutine;
end;
end;