
0. TABLE OF CONTENTS

   1 Copyright 
   2 Installation
    2.1 Native code
   3 Staging constructs
   4 Tag elimination
   5 Offshoring
   6 Common Problems
   7 Known Bugs
   8 Credits

1. COPYRIGHT. 

  Walid Taha and collaborators maintain the copyright to the MetaOCaml
  type system extensions. Licence to use is the same as OCaml.

2. INSTALLATION

  Here is a brief guide on how to install metaocaml.
  Untar the source distribution directory. In the newly unpacked 
  directory type:

    ./configure -prefix `pwd`
    make world                                                                    
    make install

  If you want to be able to execute metaocaml from anywhere,
  replace `pwd` with your directory in your $PATH.

  Once you have installed the system, use 

    ./metaocaml 

  to start the byte code interpreter. The batch compiler can be run using 
  the command metaocamlc. 

2.1 NATIVE CODE

  Native code compilation is only supported on Linux and FreeBSD
  i386 platforms.
  For installation, type:

    ./configure -prefix `pwd`
    make world

    make opt
    make metaocamlopt
    make install

  The native code compiler can be run using the command metaocamlopt.

3. STAGING CONSTRUCTS

  The three new constructs are

    bracket: .< e >.  used to delay computation
    escape:  .~ e     used to perform a computation within brackets
    run:     .! e     used to run a computation

  A special type constructor,
  called code is used to type code expressions. For example, 

    # .< 2 + 4 >.;;
    - : ('a, int) code = .<(2 + 4)>.

  Code fragments can be spliced into larger code contexts by using the
  escape construct: 

    # let x = .< 2 + 4 >. in .< .~ x + .~ x >. ;;
    - : ('a, int) code = .<((2 + 4) + (2 + 4))>.

  The escape construct takes an expression of type ((_,t) code) and
  produces an expression of type t, but only inside of a
  code-constructing context (i.e., inside inside code brackets).
  Attempting to escape code outside of a code-building context results
  in the following type error:

    # .~ .< 2 + 3 >.;;
    Characters 3-14:
      .~ .< 2 + 3 >.;;
         ^^^^^^^^^^^
    Wrong level: escape at level 0

  Unlike the previous version of MetaOCaml, the type constructor code
  takes *two* arguments ( "int code" in the previous version becomes
  "('a,int) code" in the current). The first argument is always a type
  variable, called an environment classifier, and is used to correctly
  type the run (.!)  construct. 

  The run construct takes a code value, executes it and returns its result. 
  For example: 

    # .! .< 2 + 3 >.;;
    - : int = 5

  The run construct only works on code values which are polymorphic in
  their environment classifier, and is used to prevent nonsensical programs 
  such as the following:

    # .< fun x -> .~ (.!.< x >.) >.;;
    Characters 18-25:
       .< fun x -> .~ (.!.< x >.) >.;;
                         ^^^^^^^
    .! error: 'a not generalizable in ('a, 'b) code


4. TAG ELIMINATION

  Tag elimination (see "Tag elimination and Jones-optimality" by Taha,
  Makholm and Hughes) is a program transformation applied post hoc on
  constructed code that can eliminate unnecessary tagging and untagging
  operations on constructed code. 

  We will illustrate the use of tag elimination on a simple
  program. The data-types below implement a simple abstract syntax for
  expressions and a domain of values to which those expressions are
  interpreted.

    type syntax = Const of int | Add of syntax * syntax
    type value  = I of int 

  First, we shall introduce a new piece of syntax. For any constructor
  like I of type t -> v, we write I^ for its inverse (deconstructor)
  of type v -> t.  We will rewrite the fuction eval for expressions
  using this syntax that constructs a piece of code that evaluates to 
  a result of type value. 

    let rec eval  = function 
      |     Const i -> .< I i >. 
      |     (Add (e1,e2))   ->  
	      .< I ((I^ (.~(eval e1))) + 
		     (I^ (.~(eval e2)))) >.
    

  Now, consider the code produced by applying eval:

    # eval (Add(Const 2, Const 3));;
    - : ('a, value) code = .<(I ((I^ (I (2))) + (I^ (I (3)))))>.

  Note in the code above, the integer values 2 and 3 are injected into
  and projected from the value data-type "value".  Tag elimination can
  transform a piece of code to remove such tagging and untagging
  operations. Application of tag elimination consists of two steps:

    1. Mark constructors/deconstructors in code as "erasable." This is
       accomplished by a syntactic conventions where tags by a
       syntactic conventions where tagging/untagging operations are
       preceeded by double tilde (~~). We now rewrite eval, marking
       the tags/untags as erasable:

	     let rec eval  = function 
	     | Const i -> .< ~~I i >. 
  		 | Add (e1,e2) ->  
		      .< ~~I ((~~I^ (.~(eval e1))) + (~~I^ (.~(eval e2)))) >.
  

    2. Use the special syntax to invoke tag elimination transformation
       on the resulting code. For example, consider the following
       code:
	    
		  let z = eval (Add(Const 2, Const 3));;
		  val z : ('a, value) code 
		   = .<(~~I ((~~I^ (~~I (2))) + (~~I^ (~~I (3)))))>.

	   The syntax for invoking tag elimination is as follows: 

	   	   .&{(_, spectype) code} expr 

	   where spectype is an annotated type of the form (#Constr type),
       where Constr is a data-constructor of some datatype t so that
       Constr : type -> t. This is a "top-level" data-constructor to
       be eliminated by tag elimination, and "type" is the type of the
       argument to this constructor that will be the type of the piece
       of code after tag elimination. Thus, to erase the tags in the
       previous example we execute the following:

	     let z' = .&{(_,#I int) code} z

	   
	   The system responds with the following:
 	     val z' : ('a, int) code = .<(2 + 3)>.

	   Note that the type of z' is int (i.e., the same type as the
       argument to #I above. If tags cannot be erased (i.e., they
       don't match or are not properly annotated with erasure), a
       special projection function will be generated to coerce the
       piece of code to the same type. Consider the earlier version of
       eval, which is not annotated with erasure:

	     val z' : ('a, int) code =
 	      .<((fun I (etag_39_1) -> etag_39_1) 
				(I ((I^ (I (0))) + (I^ (I (0))))))>.

		
	   For more general information about tag elimination, see: 
	   http://www.cs.rice.edu/~taha/publications/conference/padoII.pdf

For more general information about tag elimination, see: 
http://www.cs.rice.edu/~taha/publications/conference/padoII.pdf

5. OFFSHORING

  Offshoring is the name given to using a non-standard run construct to
  execute a code fragement.  Usually, this run construct will translate
  the generated OCaml program into another language (such as C or FORTRAN),
  use a standard compiler for this target language, and run the program
  that way.

  The following functions will take OCaml code, check if it is in the
  subset we can translate, translate, compile, and dynamically load the
  produced C code:

  - with the default options:

  examples: 

  # .!{Trx.run_gcc} .<2+1>.;;
  - : int = 3
  # let q = .<fun x -> x + x>. in (.!{Trx.run_gcc} q) 3;;
  - : int = 6

  Other available run constructs are:

    Trx.run_icc
    Trx.run_f90

  - with user-specified options:

  # .!{Trx.run_gcc with compiler_flags="-g -O2"} .<3>.;;
  - : int = 3
  # ( .!{Trx.run_gcc with compiler_flags="-g -O2"; working_dir=".";
  file_name="test";main_function_name="procedure"} .<fun x -> x + x>.) 2;;
  - : int = 4

  The options in the last example are the default and full set available
  for Trx.run_gcc and Trx.run_icc.

  Here is the set of options for Trx.run_f90: 

  # .!{Trx.run_f90 with compiler = "ifort"; 
	      compiler_flags="-O3 -xW"; 
	      f90_lib_path ="/local/intel/lib";
	      working_dir=".";file_name="test";
	      main_function_name="procedure"} .<3>.;;
  - : int = 3

  C examples can be found in mex/expected_all.ml.
  F90 examples can be found in mex/fexpected_all.ml.


6. COMMON PROBLEMS

   1. To use MetaOCaml under MS Windows, please do not use "Windows
      OCaml".  Rather, use the standard OCaml system under cygwin.  If you
      happened to install the "Windows OCaml" in the past, manually remove
      some environment variables before you can install the standard system
      succesfuly.  To do that, goto START -> Control Panel -> System ->
      Advance -> Environment variables, and edit the OCAMLLIB variable and
      remove any entries in that entry.

   2. The offshoring implementation has been tested on the following
      platforms: Linux, MacOS X (1.3), Windows[Cygwin]. Due to
      differences in the implementations of dynamic linking in various
      operating systems, we cannot claim that the implementation works on
      any other operating system. Users are encouraged to experiment and
      report any problems to metaocaml-hackers@cs.rice.edu.

7. KNOWN BUGS

  1. Regular ocaml crashed if you use bracket (".< >."), escape (".~"),
     or run (".!").

  2. Escaped expressions at the same level evaluate from right to left.

  3. Objects and modules are not supported.

  4. Offshoring does not currently work with native code compilation.

  5. Our additions to Makefile may be fragile.  Let us know if you have problems
     installing the system.

8. CREDITS

  The MetaOCaml project is funded primarily by an NSF project titled:

	"ITR/SY(CISE): Putting Multi-Stage Annotations to Work"

  The project is led by Walid Taha. Most of the development
  and implementation of staging was done by Cristiano
  Calcagno. Tag elimination was first implemented by Liwen Huang and
  continued by Emir Pasalic. Offshoring was developed by Jason Eckhardt,
  Roumen Kaiabachev, Kedar Swadi and Emir Pasalic. Oleg Kiselyov and
  Kedar Swadi contributed to the implementation of timing functions.
  Oleg Kiselyov contributed to the native code implementation.

  In addition to building on the OCaml code base, MetaOCaml also builds
  on Stolpmann's DL library as well as parts of Karpov's SCaml library.

  Many members of the metaocaml-users and metaocaml-hackers lists have
  helped identify bugs and in some cases fixed them.

