h2. Modules/Namespaces rethought

In the initial design we had modules and namespaces.
*Module* is a unit of compilation, specifies dependencies and provides a scope for *internal* visibility.
*Namespaces* are just intended for name disambiguation, they have a syntactic for (two, actually): each file may have a namespace declaration in the header, and all the contents are placed under that namespace. Additionally, there may be namespace blocks. Each namespace occurrence has a separate block of imports.

_All this looks a little bit brittle, so we rethought the design, and propose a unified concept of *packages* that replaces modules and namespaces:_


h3. Packages

(Our packages are similar to Java's ones, but there are some important differences, so, please, read carefully.)

A *package* is a group of source files along with dependencies, default imports and other compiler settings.
* Any *unit of compilation* is a package, although some packages are not units of compilation.
* Every source file declares the package it belongs to in a *package* directive (like in Java). This is needed only for self-documentation of the code.
** If there's no *package* directive in a file, it is a script (whatever it means)
* Packages are not tied up to file system, one can have as many directories for the code in a single packages as they please. One can store a dozen packages in a single directory as well. 
* One file immediately belongs to exactly one package, though.
* Every package has a unique name and encloses its contents so that there may be two entities with the same name in different packages.

Example of a kotlin file:
{jet}
package my.example

import other.*

fun foo() {} // package-level function
class A {} // FQN is my.example.A
class B {} // many classes in a file
{jet}

Packages may *contain* other packages. By default, child packages inherit all the compiler settings from their parents.
* Every package defines a *visibility* scope. It may contain *internal* members, including child packages. Internal members are visible to all the members of the package and their members as well. 
* Only members of the same package are visible by default (without importing). Members of child and enclosing packages are accessible but require importing.

Example:
{jet}
package my.example.other // sits inside my.example

val a : <unresolved:>A = ... // class my.example.A is not visible without importing
fun foo() {} // default visibility is internal: visible to child packages and other members of this package

public class Foo {} // visible to everybody who sees this package
{jet}

To specify package *settings* such as visibility, dependencies etc, one may define a package configuration script in the spirit of former module scripts. 
* At least the root package in the project must have such a script, a single script may describe several packages. 
* If a package has no script, then it's visibility is *internal* and all the other settings are inherited from its parent.

h3. Summary. Diff from Java

How Kotlin packages are better that Java ones:
* In Kotlin package is a *unit* of compilation (optimization for *internal* things)
* Kotlin packages specify their dependencies, default imports and other compiler settings
* Packages truly nest in Kotlin (hence *internal* visibility is useful)
* Kotlin packages are not folders, i.e. not tied up to the file system
* You name it

*Your objections/corrections/proposals are very welcome in the comments.*

----

Here goes the old descriptions of modules:

h2. Overall structure

A *module* is a unit of compilation, i.e. we do not compile classes or source file, we compile _modules_.
A module descriptor contains information about source files that reside in the module, how they are divided into production code and test code, dependencies, compiler options and so on.

h3. Module scripts

Physically, modules are represented as *scripts* written in Kotlin. The compiler (or IDE, or other tool) runs a script that builds a module object in memory, and uses the information from that object to resolve dependencies and compile the sources.

A script creates objects that describe the modules and adds them to a *project* object that is passed to the script by the caller (typically, the compiler or the IDE).

h3. Class path issues & configuration

There're two kinds of class paths:
* Compiler class path: classes that Kotlin compiler uses at runtime
** module scripts are compiled against this class path
** this class path is configured in a {{.kotlinrc}} file: there's a global one, one in home dir, and one in local dir
* Module class path: classes the module is compiled against (does not necessarily contain all classes in the compiler class path)
** Specified in a module script

Example:
Compiler class path would contain things like {{maven4kotlin.jar}}, {{my_compiler_extension_1.0.jar}} and such.
Module class path would contain things like {{my_nosqldb_driver.jar}}, {{my_actor_library.jar}}, {{janes_module.jar}} and such.

h2. Information that constitutes a module descriptor
* Basic metadata
** Root namespace/module name
* Sources
** Kotlin source files
** Java source files
* Compiler options
** Kotlin compiler options
*** Extensions -- what compiler extensions to use to compile this module
*** Default imports -- what's imported by default into every source file
** Javac options
* Dependencies (each may be exported or private, and embedded, jarjar'ed or not embedded)
** JDK
** Java-style class path
** Kotlin modules
** Maven modules
** ...
* User data
** Key-value pairs

NOTE: currently there's no built-in versioning for modules planned. We intend to reuse Maven for that.

Files are treated according to their types. E.g. *.java files are Java sources, *.kt files are Kotlin sources etc. One can register custom file types in a module script.

h2. What a module script looks like

Syntactically, a script is not a normal Kotlin source file: it contains import directives followed immediately by code. And this code has an implicit receiver of type {{Project}} that has member functions for building module objects:
{jet}
import kotlin.modules.dependencies.maven.*

fun ModuleBuilder.defineModules() {
  jdk = defaultJDK("1.6")

  // Standard extensions are registered, adding custom ones
  source mask "*.jav" language java // Non-standard extension for Java
  source mask "*.kt" language kotlin
  resource mask "*.bundle"

  module ("org.example.mymodule") {
    source files "kotlin/src/*.kt"
    source root "kotlin_src"
    source root "java_src"

    kotlin extension MyCoolExtension
    kotlin import "kotlin.*"
    kotlin import "java.lang.*"
    kotlin import "java.util.*"

    javac options "-g:lines -Afoo=bar"

    classpath entries "lib/*.jar"
    classpath entry "bin/classes"

    require module "org.jetbrains.extras" 
    require maven "junit" version "3.8.1"

    resource root "resources"

    data["key"] = "value"
  }
}
{jet}

Actually, the {{module()}} is called on the *this* reference that represents current project.

One other difference from normal Kotlin is that a script can define *public val*'s. A public *val* may be used by another script that "requires" this one:

E.g., {{Compiler.kts}}:
{jet}
public val frontend = module("kotlin.frontend") {
  ...
}
public val frontend_java = module("kotlin.frontend.java") {
  ...
}
public val backend = module("kotlin.backend") {
  ...
}
{jet}

{{IDE.kts}}:
{jet}
val compiler = requireScript<Compiler>

module ("ide") {
  ...
  require module compiler.frontend
}
{jet}