Lava doesn't provide a specific project notion. We believe that it is the primary purpose of file systems and directories to arrange sets of files in groups and subgroups of more or less closely related files, and we believe that you should not confuse the users by providing additional, redundant structures in the absence of a really strong motivation.
The file name suffix of a Lava file indicates the intended execution environment of the contained Lava application. Our considerations concerning execution environments are still in a very early and provisory state. Presently the Lava interpreter supports only a provisory version of a forms-oriented MDI execution environment (MDI = Multiple-Document Interface), which is associated with the .lava suffix.
A Lava file contains a top-level package (see below) which is unnamed by default. If you assign a name to it then all references to contained Lava entities will be qualified with this package name.
Lava files may "include" other Lava files. The basic std.lava file is always included. It contains the declarations of the basic built-in Lava data types (Boolean, Double, Float, Integer, String, Enumeration, Set, Chains, Array, Callback, ...). There is no special kind of "include files" like the "header files" of C++. The include mechanism is just a means to make the contents of another file available as if it were part of the including file. So it isn't an error if two Lava files include each other, and you need not worry about circular includes.
Name clashes between Lava entities contained in two included files or in the including and the included file can be resolved within the including file F by assigning unique "local alias names" ("use as" names) to the top level packages of the included files within F.
In Java a file "belongs" always to a single package and a package may extend over many files. On the other hand the Lava declaration tree which makes up a Lava file may consist of many nested packages, and every Lava package is completely contained in one Lava file.
This complete containment even of a huge package in a single Lava file is greatly facilitated by the fact that implementations can be separated from class interfaces and stored in separate files in Lava whereas the bodies of Java member functions have to be included in their respective class declarations. In this way you can have a combination of pure package and class declaration files and perhaps many separate implementation files in Lava, where every implementation file might perhaps contain the implementation of only one class.
You can declare a package to be opaque to prevent access to the contained declarations from the "outside world". In this way you can achieve similar effects as with private/friend declarations in C++ or with inner classes in Java.
Packages may have "pattern parameters" or "virtual types". Based on these they can be used to define "patterns/frameworks", i.e., groups of parameterized classes that can be derived/specialized collectively and consistently.
Lava packages may be nested within Lava files. The leaf nodes of this package tree are primarily used to constitute familiesof closely related, possibly parameterized, cooperating classes, or implementations thereof. Non-leaf nodes in the package tree would constitute collections of related families.
On the other hand, Lava files are bigger software units that play a role on the level of project and product organization:
If you want to execute a Lava file you just have to make sure that the first Lava entity in its top-level package is an initiator. Initiators play the role of "autonomous main programs" in Lava and start with the keyword "main". They may have input parameters but once started they run autonomously (even as concurrently executing threads/transactions). In particular they don't return output parameters and cannot throw exceptions to the calling level. A Lava program may (recursively) launch any number of subordinate initiators and thus consist of a collection of concurrently executing threads.
First note that implementations cannot and need never be referenced expressly in Lava but only implicitly:
If C is a "creatable" Lava class and a new object of type C is to be created then the Lava interpreter searches the current file and all directly or indirectly included files for an implementation of C. As soon as an implementation Imp of C is found a (transient) pointer to Imp is stored in the internal representation of the class C, with the effect that this same implementation Imp of C is used throughout the entire run of this application.
So you have to make sure that for every class that doesn't consist solely of abstract functions a suitable file containing the desired implementation is included anywhere in such a way that this implementation will be found at run time by searching the "include tree".
Note that it isn't a problem in Lava if two Lava files include each other or if circular include paths consisting of more than two files occur. The implementation search process reads every included file at most once.
Because Lava strictly separates class interfaces and implementations you can even have several different implementations of the same class. They should be contained in different Lava files since otherwise only the first of them (in "tree search order") will be found. In such a case it is obvious to use special "implementation include files" that don't contain anything else but include directives for implementation files. These "implementation include files" would in turn be included by the actual Lava program files and would in this way control the proper selection of implementation variants. You could then provide a number of versions of these implementation include files for various combinations of class implementation variants.
See also