A Framework for A Framework for Implementing Implementing Pluggable Type Systems Pluggable Type Systems Chris Andreae Chris Andreae James Noble James Noble Victoria University Victoria University of Wellington of Wellington Shane Arkus Shane Arkus Todd Todd Millstein Millstein University of University of California California OOPSLA 2006, Oregon, Portland JavaCOP
25
Embed
A Framework for Implementing Pluggable Type Systems Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
A Framework for A Framework for ImplementingImplementing
Pluggable Type SystemsPluggable Type Systems
A Framework for A Framework for ImplementingImplementing
Pluggable Type SystemsPluggable Type Systems
Chris AndreaeChris AndreaeJames NobleJames Noble
Victoria UniversityVictoria University of of WellingtonWellington
Shane ArkusShane Arkus
Todd MillsteinTodd Millstein
University of University of CaliforniaCalifornia
OOPSLA 2006, Oregon, Portland
JavaCOP
2/26
Types are good…
• Type-checkers help the programmer• But, they don’t always help enough!
• Existing type systems are not always sufficient:– Non-null references– Read-only references– Confined types– Style checking– …
3/26
…But not all the time
• Type systems are not always relevant:– Particularly restrictive systems– Domain-specific or limited applicability– Conflicting type systems
Conditional Constraints• If a method is public or protected and is
confined, it must be in a confined class
rule ConfinedMethodDef(MethodDef m){
where((m.isPublic() ||
m.isProtected()) &&
confined(m.type().restype)){
require(confined(m.enclClass())):
error(m, "Confined non private
method return type in
unconfined class”) }}
}
rule ConfinedMethodDef(MethodDef m){
where((m.isPublic() ||
m.isProtected()) &&
confined(m.type().restype)){
require(confined(m.enclClass())):
error(m, "Confined non private
method return type in
unconfined class”) }}
}
Condition
Failure clause
Primitive constraint
MethodDef node type
15/26
Pattern Matching rules
• Conditions on structural patterns.• Example – Anonymity preserving
– method calls with an (explicit or implicit) receiver of this are either to static methods or to other anonymous methods.
rule AnonCallsAnon(Apply a){
where(anonymous(env.enclMethod ){
where(a.meth => [this.*] || a.meth => [*]){
require(a.meth.isStatic || anonymous(a.meth)):
error(i, "’this ’ may not be used to "+
"call non -anonymous methods."); }}}
rule AnonCallsAnon(Apply a){
where(anonymous(env.enclMethod ){
where(a.meth => [this.*] || a.meth => [*]){
require(a.meth.isStatic || anonymous(a.meth)):
error(i, "’this ’ may not be used to "+
"call non -anonymous methods."); }}}
16/26
Quantification Rules
rule ConfinedClassDef2(ClassDef c){ where(confined(c)){ forall(Type s : c.supertypes ()){ require(confined(s) || s == globals.objectType): error(c, "A confined class may not extend " + "an unconfined superclass");}}}
rule ConfinedClassDef2(ClassDef c){ where(confined(c)){ forall(Type s : c.supertypes ()){ require(confined(s) || s == globals.objectType): error(c, "A confined class may not extend " + "an unconfined superclass");}}}
• Constrain properties of collection of objects– Lists, AST subtrees
• Similar to Java 5 enhanced for loop
• Example- confined class as extension– A confined class may not extend an unconfined type.
17/26
Subtype Rules• Subtyping is fundamental to Java’s type system
• Example- a value of confined type cannot be viewed at an unconfined supertype
• Applies to AST nodes change the type of an expression– Assignment, parameter passing, result returning, type casts.
• Passed: – type of the expression– supertype it must conform to– AST node where the test occurs
rule checkConfined(a <: b @ t){ where(confined(a)){ require(confined(b)): error(t, "Confined type "+a +" may not be treated as a subtype of" +"unconfined type "+b); }}
rule checkConfined(a <: b @ t){ where(confined(a)){ require(confined(b)): error(t, "Confined type "+a +" may not be treated as a subtype of" +"unconfined type "+b); }}
18/26
Predicates Declarations
• Describe complex properties without repeating.
– Readable– Reusable
• Invoked by the bodies of rules and other predicatesdeclare anonymous(Tree t){ require(t.holdsSymbol && t.sym.hasAnnotation("Anon"));}
declare confined(Type t){ require(!t.isArray()); exists(Type p : t.allparams()){ require(confined(p)); }}
20/26
Failure Clauses• Three parts
–error/warning–Position in source–Message to report
• If a statement fails, JavaCOP searches for the nearest enclosing failure clause and executes it.
require(a){ require(b); require(c): error(pos1 , "error - c has failed");}: warning(globals.NOPOS , "warning - a or b have failed")
require(a){ require(b); require(c): error(pos1 , "error - c has failed");}: warning(globals.NOPOS , "warning - a or b have failed")
21/26
•Augmented Sun javac compiler
– Passes over each class after type checking
•Defines JavaCOP API methods– Can be used directly – Can serve as a base for high-level systems
•JavaCOP rule languagejavac compiler
Errors andWarnings
Parser ASTType Checking
AugmentedAST
JavaCOP.Framework
Rest of Compiler
JavaCOP.Compiler
JavaCOP Rules
Compiled constraints(Java class)
Compiled Program
JavaProgram
The JavaCop Framework
22/26
The JavaCOP Framework Implementation
• Checks source code, not byte code– More information available
•Generic types•Many annotations
• Compiles each .java file separately– Modular design, like javac– Extract interface information from bytecode
• Performance– Less than twice the compile time
• Insulates compiled rulesets from compiler implementation
– Port to other compilers without changing the language
• Implemented in Java
23/26
The JavaCOP Compiler
•Translates rules into java code – Source–level transformation
•New code – Extends interface exposed by Framework.– Compiled into bytecode using regular Java
compiler
•Implemented in Haskelljavac compiler
Errors andWarnings
JavaCOP.Framework
JavaCOP.Compiler Compiled constraints
Compiled Program
JavaProgram
JavaCOP Rules
Parse syntax tree
Generate Java source
24/26
Applications
Successfully implemented several existing systems:• Type systems:
– Confined Types [Vitek & Bokowski 1999]– Scoped Types for Real-Time Scoped Java [Zhao et al. 2004]– Race Condition Detection [Flanagan & Freund 2000]– Generic Ownership [Potanin et al. 2006]– Javari’s notion of reference immutability [Tschantz & Ernst 2005]
• Other program constraints:– An EJB3.0 verifier– Two rulesets from the PMD Java style checker– Identifying “Degenerate Class” micro-patterns [Gil & Maman 2005]– Collecting structural information for OO metrics [Chidamber & Kemerer
1991]
25/26
ContributionThe first practical framework for pluggable
types. • Rule Language for Pluggable Types
– Clear, expressive, easy to use
• Implementation– Integrated into standard development process– Rule language compiler
• Validation– Demonstrated on a range of type systems and other
constraints
• Useful for programmers– Choose type systems as needed
• Useful for researchers– Experiment easily with novel type systems