Packages
In XDK LIVE code is organized in packages, which serve multiple purposes:
- Divide the namespace: XDK LIVE programs have one global namespace per
.x
file. Unlike Java for example, there are no means to qualify the name of an element. Packages are used to keep this namespace clean. Only things which are explicitly imported from other packages are visible in that namespace. See Importing Packages for more details. - Group code: packages are a formidable way to group code which conceptually belongs together. Where other languages have modules or classes, XDK LIVE uses packages.
- Hide information: in XDK LIVE visibility of functions, types and the likes is decided on a package level. There are only two levels of visibility: things are either visible outside a package or they are not. This is very similar to how NodeJS manages visibility (think
module.export
) or how Go does it (uppercase functions/structure members/types get exported). See Hiding Information for more details.
All XDK LIVE code belongs to a particular package. Thus, the first line in every .x
file is the package
statement. The main application logic, for example, by convention is in the main
package:
package main;
...
Naming Conventions
Just now we have seen the first naming convention: the core application logic and system setup are in the main
package.
The platforms which we import – each XDK LIVE program needs to import a platform – are by convention found in the platforms
package.
The XDK110 platform for example is in the platforms.xdk110
package.
All in all you are free to name your packages however you like. The files which constitute your package content can be located wherever in the project. However, it is a good idea to replicate the logical package structure in folders. For example:
algorithm/
|- api.x package algorithm
|- statistics.x package algorithm.statistics
\- structures.x package algorithm.structures
main.x package main
Notice how we use a dot .
to indicate a sub-package relationship.
This is merely a convention and has no influence on visibility or any other implication.
Importing Packages
Packages divide the namespace, which is the space in which the names of functions and types have to be unique. Within a package all type names and functions (save for polymorphism) have to be unique. When we import a package, we import all names from that namespace into our local program. Consider the following example:
// file: mypackage.x
package mypackage;
...
export fn answerTheQuestion() {
return 42;
}
// file: application.x
package main;
import mypackage;
every XDK110.startup {
println(`The answer: ${answerTheQuestion()}`);
}
If it were not for the import mypackage
statement, the answerTheQuestion
function would not be visible in application.x
.
To import a package use the import
statement. We have seen those in previous examples when we imported the platform, which is mandatory. Thus, every XDK LIVE program file must have at least one import: the platform import.
For example:
package main;
import platforms.xdk110;
...
You can shadow imported names within the current file. If in the example above application.x
defined its own answerTheQuestion()
function, all code within application.x
would refer to that one instead of the imported function.
Hiding Information (Visibility)
By default nothing is visible outside a package, nothing is exported to the outside world. This way, if you want to make things available outside the package, that has to be a conscious decision. To do so, mark what you want to export with the export
keyword. For example:
package utility;
import platforms.xdk110;
fn saturate(config : PidController) {
...
}
export fn control(config : PidController, input : int32) : int32 {
...
saturate(config);
...
}
In this example, the saturate
function is not visible outside the utility
package, but the control
function is because it is marked with the export
keyword.
This allows you to hide functions and types which are not meant for consumption outside of package and thus to provide a well defined API.
The generated C code will respect your export choices and mark non-exported objects as static
which is “C speak” for visible only within the same file.