Pure Functional Scala (Scala Compiler Plugin that enforces pureness)
Scala
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.settings
project
src
.gitignore
README
build.sbt
plugin-export.jardesc

README

Allows the enforcement of purity in methods/functions. A function is pure if:
- it does not call an impure function
- does not read a var defined outside the function
- does not assign to a var defined outside the function
- perform any interaction with the 'world' (which is basically an impure action)
-> is referential transparent (always the same output for the same input)

A pure method can only be overridden by a pure method, overriding pure methods with impure methods is not allowed.


There are two possibilities to declare a method as impure:
	def println(s: String): Unit @sideEffect
or
	@impure def println(s: String): Unit
Both variants are equal, there are no difference between them. The compiler can infer the impurity of a method if the
last statement of the method body is a call to an impure method.
	def hello = println("Hi there) // inferred to 'def hello: Unit @sideEffect' 

Methods that would be considered impure according to the rules above can be declared as pure by the developer. The
compiler will not check if those methods really are referential transparent or cause no side effects, this is the
responsibility of the developer. Use this syntax to declare a method as pure
	@declarePure def log(s: String) { println("LOG "+s) }
	
For methods that make use of type parameters that purity might depend on the purity of those parameters. This is specified
using the @impureIf annotation:
	@impureIf('B) def exec[B](f: () => B): Unit = f()
The @impureIf annotation might reference any of the type parameters that can be used inside the method. If the method returns
a parameterized type, then that type is automatically used as @impureIf if no purity annotation is used:
	def exec[B](f: () => B): B = f()   //equals @impureIf('B) and @impureIfReturnType


A Constructor is considered a normal method, but is annotated on the class itself. The @impure and @declarePure annotations
can be used. Example:
	@impure class MyClass {
		println("Hi") // impure call
	} 
	


	
	
LIMITATIONS:
 - Type Parameter on methods that take impure functions as parameter may need to be specified explicitly
    - see HigherLevelFunctionsWithInferenceTest
    - Problem seems to be within the Scala inferencer, on 
    		m[A](f: Function[String,A]): A
    	that is called with
    		val f: String => Int @sideEffect = it _
      infers A to Int instead of Int @sideEffect. The only calls to the AnnotationCheckers are
      to annotationsConform(), where we can't fix the problem.