E0020: a literal outside its type’s range
An integer literal takes the type of what it meets, and must fit it (Ed.3 Table 10 gives each type’s range).
VAR s : SINT; b : BYTE; END_VAR
s := 200; (* E0020: SINT is -128..127 *)
b := -1; (* E0020: BYTE is 0..255 *)
s := INT#5; (* E0013, not E0020: INT does not narrow to SINT *)
A STRING holds one byte per character, Latin-1 (docs/dependencies.md),
so a STRING literal with a character above U+00FF is refused: write it
as a WSTRING, "...". An initial value longer than its STRING[n] or
WSTRING[n] is refused too. A WCHAR is one UTF-16 unit, so WCHAR#"X"
holds one character up to U+FFFF; ${D800}, half of a surrogate pair,
is no character, in a WSTRING either; and a single-byte literal is
written in single quotes, so STRING#"a" is refused.
VAR s : STRING[3] := 'abcd'; END_VAR (* E0020: 4 characters in STRING[3] *)
t := '€'; (* E0020: not in Latin-1 *)
w := WCHAR#"${1F600}"; (* E0020: two UTF-16 units *)
A DATE, TOD or DT literal must name a day and a time of day that exist, and that iecf holds (docs/dependencies.md): a DATE or DT from 1970-01-01 to 2106-02-07-06:28:15, a TOD in whole milliseconds, a DT in whole seconds.
d := D#2023-02-29; (* E0020: 2023 is no leap year *)
d := D#1969-12-31; (* E0020: before 1970 *)
t := TOD#12:00:00.0005; (* E0020: TOD counts milliseconds *)
x := DT#2026-11-07-12:34:56.5; (* E0020: DT counts seconds *)
An LDATE, LTOD or LDT literal counts nanoseconds, up to nine digits of a second; an LDT holds 1677-09-21-00:12:43.145224192 to 2262-04-11-23:47:16.854775807, an LDATE the midnights between.
l := LD#1677-09-21; (* E0020: no midnight an LDATE holds *)
l := LTOD#12:00:00.0000000001; (* E0020: finer than a nanosecond *)
A constant expression in an initial value is worked out by the compiler (Initial values), and its value must fit the variable as a literal’s must:
VAR CONSTANT K : INT := 300; KR : REAL := 3.0E38; END_VAR
VAR
x : INT := K * 200; (* E0020: 60000, which INT does not hold *)
r : REAL := KR * 10.0; (* E0020: infinite in a REAL *)
s : SINT := INT_TO_SINT(K); (* E0020: 300, which SINT does not hold *)
q : REAL := SQRT(-1.0); (* E0020: no number *)
END_VAR