ballerina-platform / ballerina-spec

Ballerina Language and Platform Specifications
Other
168 stars 53 forks source link

Unreferenced modules of a package #686

Open sameerajayasoma opened 3 years ago

sameerajayasoma commented 3 years ago

Here is the definition of the root module in the language spec:

A Ballerina program consists of one or more modules; one of these modules is distinguished as the root module. The source code for a module uses import declarations to identify the modules on which it depends directly. At compile-time, a root module is specified, and the modules comprising the program are inferred to be those that the root module imports directly or indirectly. The directed graph of module imports must be acyclic.

With Ballerina packages, the root module is always the default module of a package. Therefore in the final executable Ballerina program, we initialize modules in the module graph rooted at the root module. This behavior is there in Ballerina Swan Lake Preview 8 release.

But a package may contain isolated modules - I.e., modules that not part of the root module's import graph. We need to decide on how to deal with such modules.

Case 1: Isolated modules in a library package

This case is straightforward, IMO. Isolated modules should be allowed in library packages, and such modules should be packaged with the .bala file when pushing to a package repository.

Case 2: Isolated modules in an application package

Isolated modules may be present in the following packages:

We need to decide whether to include all the isolated modules in the final executable and init during the program initialization.

@sanjiva @jclark @hasithaa @hevayo Please note.

sanjiva commented 3 years ago

IMO all modules in the root package of the dependency graph should be included and initialized etc..

Since a module can only express a dependency on a module and not a package, why do we need to deal with isolated modules of other packages? If you want it you have to do null import: import x/y as _; so that it gets pulled in explicitly.

Kishanthan commented 3 years ago

If an isolated module in a package has a service defined, it will not be started unless we intialize all the modules of the package. This case is valid for isolated modules of a root package. But for isolated modules of a dependent package, this case may not be valid.

If we skip initializing isolated modules of a dependent package, should we skip packing them in the final executable too? Currently we pack all the modules in the final executable.

sameerajayasoma commented 3 years ago

@Kishanthan Even though we package all modules in the executable, we don't init isolated modules. There is no impact on the executable other than the size at the moment.

sanjiva commented 3 years ago

Can we not use the term "isolated" for modules? Its too confusing with the isolated concept in the language and of course this has nothing to do with that.

sameerajayasoma commented 3 years ago

Here is how we (@sanjiva @jclark @hasithaa @sameerajayasoma) agreed to handle unreferenced modules.

Case 2: Unreferenced modules in an application package

Kishanthan commented 3 years ago

So I guess to invoke the initialization of all the modules, we need to have a separate initialization logic generated for the final executable. This is an implementation detail though.

Is the following a valid scenario?

In my root package I have two separate dependency graphs formed between modules. One graph is linked to the entry module, i.e referenced, but the other graph is unreferenced (basically all the modules in that graph are unreferenced). But to properly initialize these unreferenced set of modules, we have to intialize its base module (i.e the entry module of the unreferenced dependency graph). Otherwise, the initialization may not work properly.

jclark commented 3 years ago

@Kishanthan Please have a look at https://ballerina.io/spec/lang/master/#section_8.2

jclark commented 3 years ago

Note that main is not a language-level concept. At the language level all you have is a root module. Running a program is just a matter of initializing the root module (which will recursively initialize the modules it imports) and then listening.

The root module is not usually the default module of the package. Rather then root module is created by the compiler and

The (platform-level) design described by @sameerajayasoma describes translates at the language-level into:

manuranga commented 3 years ago

Rather then root module is created by the compiler

Should the compiler generated root module be exposed to the user in any way (eg: stack trace), or can we consider it as an implementation detail?

Reason for asking this is: If it is exposed, we need to come up with a proper name and make sure it doesn't clash with user written ones. If not exposed, we can hide the whole thing in our crt0 logic. This is our current assumption.

jclark commented 3 years ago

It's an implementation detail: you can hide or expose in whatever way you feel appropriate.