A subrange type represents a subset of the values in another ordinal type (called the base type). Any construction of the form Low..High, where Low and High are constant expressions of the same ordinal type and Low is less than High, identifies a subrange type that includes all values between Low and High. For example, if you declare the enumerated type
type TColors = (Red, Blue, Green, Yellow, Orange, Purple, White, Black);
you can then define a subrange type like
type TMyColors = Green..White;
Here TMyColors includes the values Green, Yellow, Orange, Purple, and White.
You can use numeric constants and characters (string constants of length 1) to define subrange types:
type
SomeNumbers = -128..127;
Caps = 'A'..'Z';
When you use numeric or character constants to define a subrange, the base type is the smallest integer or character type that contains the specified range.
The LowerBound..UpperBound construction itself functions as a type name, so you can use it directly in variable declarations. For example,
var SomeNum: 1..500;
declares an integer variable whose value can be anywhere in the range from 1 to 500.
The ordinality of each value in a subrange is preserved from the base type. (In the first example, if Color is a variable that holds the value Green, Ord(Color) returns 2 regardless of whether
Color is of type TColors or TMyColors.) Values do not wrap around the beginning or end of a subrange, even if the base is an integer or character type; incrementing or decrementing past the boundary of a subrange simply converts the value to the base type. Hence, while
type Percentile = 0..99;
var I: Percentile;
...
I := 100;
produces an error,
...
I := 99;
Inc(I);
assigns the value 100 to I (unless compiler range-checking is enabled).
The use of constant expressions in subrange definitions introduces a syntactic difficulty. In any type declaration, when the first meaningful character after = is a left parenthesis, the compiler assumes that an enumerated type is being defined. Hence the code
const
X = 50;
Y = 10;
type
Scale = (X - Y) * 2..(X + Y) * 2;
produces an error. Work around this problem by rewriting the type declaration to avoid the leading parenthesis:
type
Scale = 2 * (X - Y)..(X + Y) * 2;