Statements
The statement rules, local declarations, if, while, repeat, for, match, leave and skip, return, guard, and expression statements.
Directive statements (@breakpoint, @message) are on Directives; C++ preprocessor lines and cppstart blocks in a body are on C++ mixing.
The statement rules
Every statement ends in ;. Two expressions in a row with no ; between them are a syntax error (PR0001), never two statements, and a lone ; is no statement.
- An expression statement is an expression with an effect: an assignment (
:=and the compound forms such asLN *= 2), a call, or a C++ expression (LV.push_back(1);). An expression with no effect (LN + 1;) is SM0613 (statement has no effect). begin ... end;is a statement: a nested block in any statement list.
C++ statements are not written in a body: switch, try and throw have the PaskalCPP forms match, guard and raise, and a C++ statement keyword in a body (switch (LN) { ... }) is PR0049. A C++ statement PaskalCPP has no form for goes in cppstart source ... cppend;: see The three forms.
Local declarations
A var, const or type block is a statement in every statement list: a routine or module body, a loop body, a nested begin ... end; block and a match arm. Its names are visible from it to the end of its list (var LA: int32 = 3;, type TSmall = int8;).
- In a match arm each keyword takes one item (
1: var LY: int32 = 5;): before a later item, a label list followed by:would start the next arm. - Two locals of one name in one list are SM0004; a local var with no type is PR0001.
if, while, repeat
if C then ... [else ...] end;: each branch is a statement list, and a chain of tests nests an if in the else.
while C do ... end; tests C before each pass, so a false C never runs the body. repeat ... until C; runs the body first and ends when C is true, so the body runs at least once.
The condition of if, while and until is a bool: an int32 condition is SM0263 (a condition is bool).
There is no truthiness: write if LN <> 0 then, not if LN then.
for
for V := A to B do ... end; counts up, downto counts down. Both ends are included, and an empty range (for LI := 5 to 1) runs nothing.
module exe statements_wchar;
type
TColor = choices(cRed, cGreen, cBlue);
routine Kind(AW: wchar): string;
var
LR: string;
begin
match AW of
L'a'..L'z': LR := "letter";
L'0'..L'9': LR := "digit";
else
LR := "other";
end;
return LR;
end;
var
LW: wchar;
LI: int32;
LJ: int32;
LK: TColor;
begin
print("wide");
for LW := L'a' to L'c' do
print(" {}", LW);
end;
println("");
println("wide x {}", Kind(L'x'));
println("wide 5 {}", Kind(L'5'));
print("grid");
for LI := 1 to 2 do
for LJ := 1 to 2 do
print(" {}", LI * 10 + LJ);
end;
end;
println("");
LK := TColor.cBlue;
match LK of
TColor.cRed: println("red");
TColor.cGreen, TColor.cBlue:
if LK = TColor.cBlue then
println("blue");
end;
end;
end.
wide a b c
wide x letter
wide 5 digit
grid 11 12 21 22
blue
[Heap] Allocs: 0, Frees: 0, Leaked: 0
- V names a variable declared before the loop (a var, or a parameter that is not const);
fornever declares one. A constant as V is SM0600, and so are a type, a routine, a field, a choice value and a const parameter. - V is an integer,
char,wcharor a choices type (for LW := L'a' to L'c',for LK := TColor.cRed to TColor.cBlue); any other type is SM0601. A choice iterator takes bounds of its own choices type. A C/C++ variable mixed into the file is an iterator too (int GCpp = 0;as plain C++, thenfor GCpp := 7 to 9); its type is clang's. - The body reads V but never writes it: an assignment to V in the body is SM0602, and so is a nested
forover the same V. - A
fornests in aforover another iterator.
match
match S of label[, label]: ...; [else ...] end;: an arm holds a list of labels and a statement list. A label is a constant or a range a..b (4..6, 'a'..'z'), and else takes every other value.
- S is an integer,
char,wcharor a choice; astringsubject is SM0603. - A label is a constant: a variable as a label is SM0202. A label outside the subject's type is SM0604 (
match label 300 is outside 'int8': it never matches), a range whose low bound exceeds its high bound SM0267, and a label two arms hold SM0605, with the first label covering it as a note. - A match on a choice with no
elsenames every value or warns: SM0606 (match on 'TColor' does not cover: cBlue) lists the values no arm names. A match that names every value needs noelse.
leave and skip
leave; ends the innermost loop or match; skip; goes to the next pass of the innermost loop. Both work in while, for and repeat, and a leave in a match inside a loop ends the match only.
leave outside a loop or match is SM0607, skip outside a loop SM0608.
return
return V; returns a value of the function's return type, and every path of a function's body ends in a return: a body that can reach its end is SM0612 (missing return: 'F' can reach its end without returning a value).
return; leaves a procedure early, from inside loops and matches too. return; in a function is SM0610, and return V; in a procedure is SM0611.
guard
guard ... [except ...] [finally ...] end; takes at least one of except and finally; a guard with neither is PR0052.
exceptruns when the body raises, andexccode()/excmsg()read the exception there; outside an except body they are SM0615.finallyruns either way, last.- A guard nests in a guard, and an inner raise reaches the outer
exceptafter the innerfinally. leave,skipandreturnjump out of a guard body or an except body, andfinallyruns on the way out.
module exe statements_guard_flow;
routine Find(): int32;
begin
guard
return 7;
finally
println("return finally");
end;
end;
routine Handle(): int32;
begin
guard
raisecode(9, "nine");
except
print("except {}", exccode());
return -1;
finally
println(" finally");
end;
return 0;
end;
var
LI: int32;
begin
for LI := 1 to 5 do
guard
if LI = 2 then
print("skip {}", LI);
skip;
end;
if LI = 3 then
print("leave {}", LI);
leave;
end;
print("pass {}", LI);
finally
println(" finally");
end;
end;
println("loop done");
println("found {}", Find());
println("handled {}", Handle());
end.
pass 1 finally
skip 2 finally
leave 3 finally
loop done
return finally
found 7
except 9 finally
handled -1
[Heap] Allocs: 0, Frees: 0, Leaked: 0
- No jump leaves a
finallybody:leave,skipandreturnthere are SM0609. - A C++ jump (
break;in mixed C++) inside a guard body is SM0614: it would leave only the guard's hidden function.
What a guard catches, beyond raise, is on The runtime.