summaryrefslogtreecommitdiff
path: root/compiler/pstatmnt.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/pstatmnt.pas')
-rw-r--r--compiler/pstatmnt.pas39
1 files changed, 33 insertions, 6 deletions
diff --git a/compiler/pstatmnt.pas b/compiler/pstatmnt.pas
index 2ab55c1255..9de0ec0f9a 100644
--- a/compiler/pstatmnt.pas
+++ b/compiler/pstatmnt.pas
@@ -1071,7 +1071,7 @@ implementation
pure_statement:=code;
end;
- function formal_annotation(var loop_invariant : tnode) : tnode;
+ function formal_annotation(var loop_invariant : tnode; var bound_function : tnode) : tnode;
var
expr : tnode;
s : tnode;
@@ -1099,6 +1099,22 @@ implementation
formal_annotation:=cnothingnode.create;
consume(_CLOSE_FORMAL);
end
+ else if (token=_ID) and (upcase(pattern)='BND') then
+ begin
+ consume(_ID);
+ consume(_COLON);
+ expr:=comp_expr_in_formal_context(true);
+ if assigned(bound_function) then
+ begin
+ { A bound function was already specified,
+ this is an error }
+ { TODO }
+ end
+ else
+ bound_function:=expr;
+ formal_annotation:=cnothingnode.create;
+ consume(_CLOSE_FORMAL);
+ end
else
begin
expr:=comp_expr_in_formal_context(true);
@@ -1116,6 +1132,7 @@ implementation
first : tnode;
tochange : ^tnode;
invariant : tnode;
+ bound : tnode;
procedure parse_formal_annotation_star;
begin
@@ -1123,7 +1140,7 @@ implementation
begin
if not(cs_do_assertion in aktlocalswitches) then
Message(parser_w_formal_annotation_not_compiled);
- ass:=formal_annotation(invariant);
+ ass:=formal_annotation(invariant, bound);
tochange^:=cstatementnode.create(ass, nil);
tochange:=@(tstatementnode(tochange^).right);
end;
@@ -1134,11 +1151,12 @@ implementation
begin
invariant:=nil;
+ bound:=nil;
first:=nil;
tochange:=@first;
parse_formal_annotation_star;
- if assigned(invariant) then
+ if assigned(invariant) or assigned(bound) then
begin
{ ASSUMPTION :
repeat_statement and while_statement return a
@@ -1152,10 +1170,18 @@ implementation
else
begin
Message(parser_w_invariant_not_before_loop);
- invariant.destroy;
+ invariant.free;
invariant:=nil;
+ bound.free;
+ bound:=nil;
end; { else }
end; { case }
+ { Warning: order is important, first bound, then invariant }
+ if assigned(bound) then
+ begin
+ { Set the bound function }
+ twhilerepeatnode(tstatementnode(tochange^).left).setbound(bound);
+ end;
if assigned(invariant) then
begin
{ Set the invariant (include a check in each iteration of the loop) }
@@ -1168,10 +1194,11 @@ implementation
in_assert_x_y, false, ccallparanode.create(invariant.getcopy,
ccallparanode.create(fail_string, nil))), nil);
- tochange:=@(tstatementnode(tochange^).right);
end;
+ if assigned(invariant) or assigned(bound) then
+ tochange:=@(tstatementnode(tochange^).right);
end
- else { not assigned(invariant) }
+ else { not assigned(invariant) and not assigned(bound) }
begin
tochange^:=cstatementnode.create(pure_statement, nil);
tochange:=@(tstatementnode(tochange^).right);