The Main Function in ATS


The main function in ATS is declared as follows:

fun main {n:int | n > 0} (argc: int n, argv: &(@[string][n])): void
  = "mainats"
So this function takes an integer argc greater than 0 and a string array argv of size argc and returns no value. The syntax argv: &(@[string][n]) indicates that argv is a call-by-reference argument. If we followed C++ kind of syntax, then this would be written as something like &argv: @[string][n].

The name "mainats", which is global, can be used in C code to refer to this function. When a program in ATS is compiled that implements the main function in ATS, the following implementation of the main function in C is automatically included in the C code generated by the ATS compiler:

main (int argc, char *argv[]) {

// some initialization code is included here

mainats (argc, argv) ;
return 0 ;

}
As an example, the following ATS program prints out the command line on the standard output:
implement main (argc, argv) = let
  fun loop {n,i:nat | i <= n} // [loop] is tail-recursive
    (i: int i, argc: int n, argv: &(@[string][n])): void =
    if i < argc then begin
      if i > 0 then print (' '); print argv.[i]; loop (i+1, argc, argv)
    end // end of [if]
  // end of [loop]
in
  loop (0, argc, argv); print_newline ()
end // end of [main]
There are also situations where the function mainats may need to be implemented in C. If this happens, the function main_dummy needs to be implemented as follows:
implement main_dummy () = ()
This allows the compiler to generate proper code for the main function in C.

As an example, we present as follows a typical scenario in GTK+ programming, where the function gtk_init needs to be called to modify the arguments passed from a command line:

// some function implemented in ATS
extern fun main_work {n:pos} (argc: int n, argv: &(@[string][n])): void
  = "main_work"

implement main_work (argc, argv) = ( (* some ATS code that does the main work *) )

implement main_dummy () = () // indicating [mainats] being implemented in C

%{$

ats_void_type
mainats (ats_int_type argc, ats_ptr_type argv) {
  gtk_init ((int*)&argc, (char ***)&argv) ;
  main_work (argc, argv) ;
  return ;
} /* end of [mainats] */

%}

The code used for illustration is available here.