Program Structure
ocean.mod
If you tried to copy and run the program from the last lesson, you may have noticed that you can't run it as-is. This is
because Ocean programs require more than just source code in order to compile. This is because every Ocean project needs an
ocean.mod file. The ocean.mod file defines important metadata about a module, such as the minimum version of Ocean required,
dependencies, etc. To get started with a simple, local project, make a new directory with the name of your project. Then,
run ocean mod init <module name>, where the module name is optional (if not specified, module name will
be the same as the name of the directory). For more details about Ocean's package and module system, see 2.2 Import & Package System.
Entry Point
Every (executable) Ocean program needs an entry point. The entry point is where the execution of the program
starts, and is therefore required for executable programs. In Ocean, the entry point of a program is always the main() function of the main package of the module. Note that the main package should always be in the same
directory as the ocean.mod file. To declare the main() function in the main package, we need to first
declare that a file is in the main package. We do this by placing a package statement at the top of our
file:
package main;
Next, we need to declare the main() function:
package main;
func main() {}
Imports
Now, if we place any code inside the main() function, it will be run when the program is executed. Additionally,
you can import modules or packages at the top of a file, below the package statement. Note that when you import a module, you
are really only importing the main package of the module. To import other packages from the module, use the following
syntax:
import "<module name>/<package path>"; So, for example, to import the bar package from the foo module, you would write:
import "foo/bar"; Additionally, if you wanted to import bar's sub-package, baz, you would write:
import "foo/bar/baz"; Let's import the io package from the standard libary so we can use it later:
package main;
import "io";
func main() {}
Note that we don't have to specify a module name for io as standard libary packages don't require a module name to import.
Top-Level Declarations
Now, let's say you wanted to declare another function, hello(), that printed a message to the user. How would you do this?
In Ocean, all top-level declarations in the same package are in the same global namespace, regardless of order. That means that we could declare our hello() function below the main() function, or even in another file in the main pacage, and we
could still directly call it without having to import anything or use the package.function() notation. For example:
package main;
import "io";
func main() {
hello("bob"); // note how hello() is declared below main(), but main() can still call hello().
hello("jim");
}
func hello(string name) { // this declares a function called hello, with a string parameter called name. string is a built-in type
io.Println("Hello, " + name + "!");
}
This also applies to top-level declarations in different files in the same package. For example:
// project file structure:
// myProject
// ├-main.oc
// └-hello.oc
// file main.oc:
package main;
func main() {
hello("bob");
hello("jim");
}
// file hello.oc:
package main;
import "io";
func hello(string name) {
io.Println("Hello, " + name + "!");
}
main() can use hello() because they are in the same package.
This also goes for top-level variable declarations, such as:
package main;
import "io";
string s = "hello, world!";
func main() {
io.Println(s);
}
s is accessible from any code within the main package.