Resource Usage Analyzer
for a Functional Language with Exceptions

This prototype resource-usage-analyzer inputs programs written in the language defined by the following syntax and reports whether each resource created in the programs is accessed properly according to each annotated specification.

Try our resource analyzer from the following form.

Do not display usage information (faster) Display usage information

Syntax

  (Programs)
   P ::= M;;  (Program is a term followed by ;;)    

  (Terms)
   M ::= v                      (values)
       | new[spec]()            (resource creation)
       | acc[alabel](M)         (resource access)
       | if M1 then M2 else M3  (conditional branch)
       | M1M2                   (functional application)
       | let x = M1 in M2       (local binding)
       | M1;M2                  (let _ = M1 in M2 (syntax sugar))
       | try M1 with M2         (exception handling)
       | raise                  (exception raising)

  (Values)
   v ::= true                   (true constant)
       | false                  (false constant)
       | x,y,f,g, ...           (variables)
       | fun(f,x,M)             (functions)
       | lambda x. M            (non-recursive functions (syntax sugar))

  (Access labels)
   alabel ::= read              (read access)
            | close             (close access)
            | write             (write access)
	   
  (Spec expressions)            (specification in a regular expression)
   spec ::= (read*);close
          | (write*);close

Note that, currently, this analyzer is able to check correctly for only the specifications ((read*);close) and ((write*);close). Work is under way to implement a analyzer that can deal with more general specifications.

Examples

The following program creates a resource which should be accessed according to (read*);close, and accesses the resource with read operation, raises an exception and, handling the exception, the program closes the resource finally.

   /* Valid program */
   let x=new[read*;close]()
   in  try acc[read](x);raise with acc[close](x);; 

The following program fails to close a resource.

   /* Invalid program */
   let x=new[read*;close]()
   in  try acc[read](x);raise with true;; 

The following is a prototypal program that uses recursive function. In the program, a resource is created and accessed repeatedly with read operation until an exception is raised. Then the exception is handled and the resource is closed finally.

   /* Valid program */
   let z=new[(read*);close]() 
   in  try  fun(f, x, if acc[read](x) then raise else f x) z
       with acc[close](z);; 

The following is a prototypical model of programs that copy data from a read only resource into a write only resource and then close these resources. For example, a fragment of OCaml program

   let ic = open_in  "filename1" in
   let oc = open_out "filename2" in
   try 
     while(true) do
       let s = input_line ic  (** read_line may raise End_of_File exception **)
       in  output_string oc (s^"\n")  
     done
   with
     End_of_file -> flush oc; close_in ic;close_out oc;;
is expressed as the following program in our language.

   /* Valid program */
   let x = new[read*;close]()  in
   let y = new[write*;close]() 
   in
       try  
            fun(f,z, (if acc[read](x) then true else raise); acc[write](y); f true) true
       with 
            acc[close](x); acc[close](y);;

The following program is equivalent to the above program except for failing to close the write only resource.

   /* Invalid program */
   let x = new[read*;close]()  in
   let y = new[write*;close]() 
   in
       try  
            fun(f,z, (if acc[read](x) then true else raise); acc[write](y); f true) true
       with 
            acc[close](x);;

In the following program, function input_line, which take a resource and access it with read operation and may raise exception, is defined. Then, after a read only resource is created, the resource is read repeatedly using the function until an exception is raised. Finally, when an exception is raised, the exception is handled and the resource is closed.

   /*** Valid program ***/
   let input_line 
          = lambda x. if acc[read](x) then true else raise in
   let ic = new[read*;close]() in
   let f  = fun(g,x, input_line x;g x)
   in  try  (f ic) 
       with acc[close](ic);;

The following program repeatedly creates a new resource and close it. Note that, in this program, arbitrarily many resources my be created, and also arbitrarily many exception handlers can be nested.

   /*** Invalid program ***/
   let create = fun(f,x, let y=new[read*;close]() in y) in 
   let repeat = 
      fun(g,x, let z = create true
               in  try (if   acc[read](z)
	                then raise
		        else (g true;acc[read](z)))
	           with acc[close](z)) in
   repeat true;;

More examples are available from here.