Title: JPred-P2: Runtime Precondition and Postcondition Checking in Java
1JPred-P2 Runtime Precondition and Postcondition
Checking in Java
2Precondition
- a fact that must always be true just prior to
the execution of some section of code, such as
when entering a procedure - Can be enforced with assert() statements at top
of procedure body - In software engineering, usually specified simply
as comments around a procedure body
3Postcondition
- a fact that must always be true just after the
execution of some section of code, such as when
leaving a procedure - Could enforce with assert() statements at bottom
of procedure body - Usually exists in the form of programmer comments
4Wouldnt it be nice if
public int divide( int numr, int denr) assert
( denr ! 0 ) return numr / denr
5Wouldnt it be nice if
public int divide( int numr, int denr) assert
( denr ! 0 ) return numr / denr
6Wouldnt it be nice if
public int divide( int numr, int denr) requires
denr ! 0 return numr / denr
7How about
public void deposit( Account account, Money
amount ) secureDeposit( account, amount
) assert( account ! null )
8How about
public void deposit( Account account, Money
amount ) secureDeposit( account, amount
) assert( account ! null )
9How about
public void deposit( Account account, Money
amount ) ensures account ! null secureDeposit
( account, amount )
10Get ready for this
public Person pointOfNoReturn( Person you
) requires you ! null ensures retREF
null System.out.println( you.getName()
goes away) return null
11JPred
- Dynamic method dispatch based upon predicates
public char whatGradeShouldIGive( int testScore
) when testScore gt 90 return A Public
char whatGradeShouldIGive( int testScore ) when
testScore lt 90 return F
12JPred Pre/Postconditions
public void doTermProject( Student s ) requires
s.hasALife false ensures s.avgHoursOfSleep lt
4 s.finishedProject false when
p_at_ComputerScienceGradStudent / do project
/ public void doTermProject( Student s
) / do project /
JPred-P2
13Implementation - Tools Used
- Polyglot (Cornell)
- Compiler front end framework for building Java
language extensions - Definition of new grammar
- Custom abstract syntax tree (AST) nodes
- Specialized AST traversal passes
- CVC Lite (Stanford)
- Theorem prover
- Predicate validation
- MultiJava (http//multijava.sourceforge.net)
- JPred written in MultiJava
14Implementation - Our Work
- Added requires and ensures support on top of
existing JPred Polyglot extension - Modified JPreds grammar definition files to
support the new optional keywords - Added AST nodes reqNode and ensNode along with
JPreds whenNode (formerly called predNode)
15Implementation (continued)
- Modified JPreds traversal passes
- requires support
- In the translator pass, add an if-else statement,
with the requires predicate as its guard - Enclose the method body under the ifs body
- else body outputs precondition failure message
and terminates program
16Implementation (continued)
- ensures support
- Few issues involved
- There can be multiple method exit points end of
method body and arbitrary number of return
statements - Postcondition must be checked immediately before
each of these exit points - How to specify postconditions on return values?
- Ex int f() ensures lt?gt return 12
17Implementation (continued)
- ensures support (continued)
- Locate all return statements in a method body
- Enclose a return statement in an if-else
statement - Guards are the ensures predicate
- else body outputs postcondition failure message
and terminates program
18Implementation (continued)
- ensures support (continued)
- Postcondition check on a return value requires a
store - Ex
int f() ensures lt?gt return 12
int f() ensures retINT gt 2 int retINT
12 if ( retINT gt 2 ) return
retINT else / postcondition failed /
19Implementation (continued)
- ensures support (continued)
- JPreds predicates can have three types of
expressions integer, boolean, and null - Which means postcondition check on a return value
is limited to one of those three types - Define retINT, retBOOL, and retREF keywords
- Ex Make sure g() returns a non-null reference
- Object g() ensures retREF ! null
20Implementation (continued)
- ensures support (continued)
- Define a new pass to be executed early
- Declare static retINT, retBOOL, and retREF
variables in class body - When ensures predicate specifies any of those
keywords, they are valid variables in the AST
and so Polyglot does not complain
21Example - Abstract Divide
- int absDivide( int num, int denom ) returns the
absolute value of the quotient of num divided by
denom
public static int absDivide( int num, int denom
) requires denom ! 0 ensures retINT gt
0 when denom gt 0 int result if ( num gt 0
) result num / denom else result -num /
denom return result
22Example (continued)
public static int absDivide( int num, int denom
) requires denom ! 0 ensures retINT gt
0 when denom lt 0 int result if ( num gt 0
) result -num / denom else result num /
denom return result
23Example (continued)
- Compiling the source code with JPred-P2 produces
a standard Java translation
public static int absDivide(int arg0Real, int
arg1Real) if (arg1Real lt 0) return
absDividebody1(arg0Real, arg1Real) else r
eturn absDividebody0(arg0Real, arg1Real)
Dispatch method
24Example (continued)
private static int absDividebody0(int num, int
denom) if (denom ! 0) int result if
(num gt 0) result num / denom else result
-num / denom retINT result if (retINT gt
0) return retINT else System.out.println("p
ostcondition failed retINT gt
0") System.exit(1) return retINT
else System.out.println("precondition
failed denom ! 0") System.exit(1) return
0
25Conclusion
- JPred-P2 makes it easy on the programmer to
enforce precondition and postcondition checking - By defining these predicates in the method
header, code becomes a lot more readable - Inheritance of requires and ensures clauses is an
idea for future work