Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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