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.