3. “Hello, world!” on ATS¶
ATS compiler is needed to run ATS program. In other words, ATS language doesn’t have interpreter such like OCaml language. We try to compile some simple ATS program on this chapter, before learn full-featured ATS programming.
3.1. ATS program to do nothing¶
What is the minimum program? It’s mostly a program has nothing without a empty main function. Let’s create such “ATS program to do nothing”.
1 2 | (* File: nothing.dats *)
implement main0 () = ()
|
This is the ATS program has a main function doing nothing. Detail of the code is explained as following:
- Any ATS programs start at main0 function
- Keyword implement defines a new function main0 at the code
- main0 function has been declared in ATS language implementation
- main0 has no arguments and return value is void type
- The body of the main0 function does nothing and return ()
- The () is the only value of void type
3.2. Compile and run it¶
Let’s compile the “ATS program to do nothing”. Save it as nothing.dats and run following commands:
1 2 3 4 5 6 7 | $ ls
nothing.dats
$ patscc nothing.dats
$ ls
a.out nothing.dats nothing_dats.c
$ ./a.out
$
|
An executable a.out is created by ATS compiler patscc. Of course, the executable prints nothing on console while running.
By the way, how does the patscc command work?
As in the figure, the patscc internally calls two commands.
The first command is patsopt that compile ATS language code to C language, while the patsopt does typecheck the ATS code and reports type errors. The compilation ATS to C is aborted, if typechecking found some type errors.
The second command is gcc that is familiar to everyone. C language code created by patsopt is compiled to executable by the gcc command.
3.3. Print character string on console¶
We learn how to use patscc command in the previous sub chapter. Let’s try “Hello, world!” program.
1 2 3 4 | (* File: helloworld.dats *)
val () = println! "Hello, world!"
implement main0 () = ()
|
This code includes following new items:
- val defines binding between name and value
- The val at the code binds function return value of the function println! as void value
- println! is a special keyword that prints the argument on console and return void value
Then, the code prints the character string "Hello, world!" on console.
1 2 3 | $ patscc helloworld.dats
$ ./a.out
Hello, world!
|
This result may sound strange for a beginner of functional programming who has already learned imperative programming. Conceptually, what happens at run-time in a call-by-value language such as ATS is following:
- The expression println! "Hello, world!" is evaluated to the value (), while it prints the character string "Hello, world!" on console
- val creates a bind between () at left side of = and the result value of the expression println! "Hello, world!"
- The function main0 is evaluated and does nothing
The “Hello, world!” program can be written in main0 function using where keyword, as following:
1 2 3 4 5 | (* File: helloworld2.dats *)
implement main0 () = () where {
val () = println! "Hello, world!"
}
|
Also, because main0 function returns void value, we can drop () where as following:
1 2 3 4 5 | (* File: helloworld3.dats *)
implement main0 () = {
val () = println! "Hello, world!"
}
|
More simply, we can alos write following, because println! return void value as same as the value will be returned by main0 function.
1 2 3 | (* File: helloworld4.dats *)
implement main0 () = println! "Hello, world!"
|