Press enter to see results or esc to cancel.

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;