-
Notifications
You must be signed in to change notification settings - Fork 17
lang helloworld
For some crazy reason, when you are learning a new language, the first program that you must write is called HelloWorld
, and its sole purpose is to print the string "Hello World". We don't make up the rules, so let's do it!
We already showed the "Hello World" code in the introductory chapter of this guide, so let's show it again, and walk through what it does:
module HelloWorld {
void run() {
@Inject Console console;
console.print("Hello World!");
}
}
In the previous chapter, we introduced the module
keyword; its syntax, particularly with the "curly braces" class body should be familiar to anyone who has used Java, C#, or C/C++. HelloWorld
is a class, because modules are classes. Using the module
keyword in Ecstasy is conceptually similar to writing something like this:
public static class HelloWorld
implements immutable Module {
// every module contains the "ecstasy" package
package ecstasy import ecstasy.xtclang.org;
// paste in lots of code here that implements the Module interface
// ...
// and here are those four lines of code for doing "Hello World!"
void run() {
@Inject Console console;
console.print("Hello World!");
}
}
But instead of writing all of that (including the who-knows-how-many lines of code implied by the "..."), we just use the keyword module
, and let the compiler verify all of the rules around what a module
can and cannot do. Then the linker automatically provides an implementation of the Module interface for us. In other words, just by using the module
keyword, we get an entire Module
implementation, but it's not somehow "generated" at compile-time. This is a fairly typical approach in Ecstasy: You shouldn't have to hard-code and/or cut & paste stuff, and the compiler shouldn't be doing that stuff for you, either. So if you compile a module and look inside its structure, it won't have any of the code for implementing the Module interface in there. There are lots of reasons why -- from security, to versioning, to evolution of the language and runtime -- but regardless, this is the approach that we chose for the language.
The void run()
looks like a function definition in C for example, but here it is a method of the HelloWorld
class. (We'll explain methods and functions in an upcoming chapter.) By convention, this particular method signature is the default entry point on a module when the module is executed from the command line.
The "@Inject Console console
" inside that method declares a local variable whose name is console
and whose type is Console. It is annotated such that its value is injected by its parent ("host") container. In other words, the @Inject annotation indicates: "This variable will magically have a value at runtime, and that value will be a Console
object".
Support for injection is a fundamental component of the Ecstasy container model. From the original set of axioms, recall that "No native code can exist inside of an Ecstasy container." If it were not possible to inject a console into a container, then it would be impossible to print "Hello World" (or anything else) to the screen. Furthermore, it would not be possible to create a socket, read or write a file, access a database, or anything else that would require talking to the operating system or other native code. All access to storage, the network, and literally any OS or hardware capability must be injected, because that functionality could not otherwise be present within an Ecstasy container.
Finally, we get to that one remaining line of code in the module that calls console.print
, which is fairly self-explanatory: It prints out the String "Hello World!", using the Console
capability that was injected into the console
variable.
To compile and run this example, you will need the compile (xcc
) and run (xec
) commands that are installed with the Ecstasy Development Kit (XDK). If you haven't already installed the XDK, download a release from Github, or get the latest build from xtclang.org.
Assuming that this module is stored in a file HelloWorld.x
, and that you are in a terminal/shell/command window with the current directory already configured to the location of HelloWorld.x
, then compile the module using the following command:
xcc HelloWorld
The xcc
command will compile the HelloWorld.x
source file to the HelloWorld.xtc
compiled module file. (You can always specify the full name of the file; the command xcc HelloWorld.x
will also compile it.) To run the resulting HelloWorld.xtc
file:
xec HelloWorld
Which should print out:
Hello World!
(Again, you can always specify the full name of the file; either of the commands xec HelloWorld.x
or xec HelloWorld.xtc
will run it.)
When we run the HelloWorld
module from the command line, as shown above, the following things happen:
- The Ecstasy runtime is started, and it creates its native container using a type system that includes the
ecstasy.xtclang.org
module. - The Ecstasy runtime then creates the application container, loading the
HelloWorld
module, and sharing theecstasy.xtclang.org
module from the native container into the application container. - The runtime instantiates the singleton instance of the
HelloWorld
module inside of the application container, and invokes therun()
method on that singleton instance. - Your "hello world" code runs inside that container.
Don't worry too much about the technical details in that list; the explanation is simplified as much as possible to help it make sense. The main points are that your Ecstasy code gets loaded inside of a secure software container, your module's run()
method will be invoked, and your code is then executing inside of that new container.
When you stop and think about it, this really isn't too different from having the OS start a new process to run a C program, and the OS calls the int main(int argc, char *argv[])
entry point function. The main difference is that the C program has access to:
- The C runtime library;
- Whatever other libraries the program is statically linked to;
- Whatever other libraries (
.so
or.dll
) the program can load and link to dynamically; - Everything on the hard drive and any other OS storage that isn't explicitly protected from the user who started the process;
- All of the local hardware that isn't explicitly protected from the user who started the process;
- Its own memory, including its own running code, which it may be able to alter on the fly unless specific protections are explicitly put in place to prevent that; and
- All of the computer's memory that isn't explicitly protected from the user who started the process.
While the Ecstasy HelloWorld.x module has access to:
- A
Console
.
And that's it.
Prev: Creating your first module | Next: Understanding classes |
---|