Note: the command-line version of Why3 is also supporting this input format, for files with suffix .py.
Logical annotations are inserted in special comments starting with //@ or /*@. In the following grammar, we only use the former kind, for simplicity, but both kinds are allowed.
file ::= decl* decl ::= py-import | py-function | stmt | logic-declaration py-import ::= "from" ident "import" ident { "," ident } NEWLINEDirectives import are ignored during the translation to Why3. They are allowed anyway, such that a Python source code using functions such as randint is accepted by a Python interpreter (see below).
py-function ::= "def" ident "(" [ params ] ")" ":" NEWLINE INDENT { spec } { stmt } DEDENT params ::= ident { "," ident }
spec ::= "requires" term NEWLINE | "ensures" term NEWLINE | "variant" term { "," term } NEWLINE
expr ::= "None" | "True" | "False" | integer-literal | string-literal | identifier | identifier "[" expr "]" | "-" expr | "not" expr | expr ( "+" | "-" | "*" | "//" | "%" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "and" | "or" ) expr | identifier "(" [ expr { "," expr } ] ")" | "[" [ expr { "," expr } ] "]" | "(" expr ")"
stmt ::= simple_stmt NEWLINE | "if" expr ":" suite else_branch | "while" expr ":" loop_body | "for" ident "in" expr ":" loop_body else_branch ::= /* nothing */ | "else:" suite | "elif" expr ":" suite else_branch suite ::= simple_stmt NEWLINE | NEWLINE INDENT stmt { stmt } DEDENT simple_stmt ::= expr | "return" expr | identifier "=" expr | identifier "[" expr "]" "=" expr | "break" | "//@" "label" identifier | "//@" ( "assert" | "assume" | "check" ) term assignop ::= "=" | "+=" | "-=" | "*=" | "/=" loop_body ::= simple_stmt NEWLINE | NEWLINE INDENT { loop_annot } stmt { stmt } DEDENT loop_annot ::= "//@" "invariant" term NEWLINE | "//@" "variant" term { "," term } NEWLINE
logic-declaration ::= "//@" "function" "int" identifier "(" params ")" NEWLINE | "//@" "predicate" identifier "(" params ")" NEWLINENote that logic functions and predicates cannot be given definitions. Yet, they can be axiomatized, using toplevel assume statements.
term ::= identifier | integer-literal | "None" | "True" | "False" | "(" term ")" | term "[" term "]" | term "[" term "<-" term "]" | "not" term | "old" "(" term ")" | "at" "(" term "," identifier ")" | "-" term | term ( "->" | "<->" | "or" | "and" ) term | term ( "==" | "!=" | "<" | "<=" | ">" | ">=" ) term | term ( "+" | "-" | "*" | "//" | "% ) term | "if" term "then" term "else term | "let" identifier "=" term "in" term | ( "forall" | "exists" ) ident { "," ident } "." term | identifier "(" [ term { "," term } ] ")"
Click on the gears button to launch the verification. Verification conditions (VCs) then appear in the right panel, in the Task List tab, and Alt-Ergo is run on each of them with a default time limit (that can be set in the Settings menu).
When a VC is not proved, there are several options: