3. Module system

module

A value loaded by the module system. A module has a set of functions of a single feature group as its variables. Module can be abbreviated to mod.

module system

A subsystem of the runtime which manages modules.

3.1. Module loading

A module can be loaded from the module system by specifying a string of the module name. Module loading can be done by require_from method of a varref, or MOD.require function (see kink/MOD).

Module loading is done as follows:

  • If the specified module name has already been associated with a module, module loading results in “success” status with the module.

  • If the specified module name hasn't been associated with a module, the module system tries to find the source of the module. If the source is not found, module loading results in “not found” status.

  • If the source is found, and the source is a Kink program, the module system tries to compile the program. If compilation fails, module loading results in “compile error” status, with (Msg, From_loc, To_loc), where Msg is the error message string, From_loc is the inclusive starting location of the program error, and To_loc is the exclusive starting location of the program error.

  • If the previous step succeeds, the module system tries to initialize a module. If the source is a Kink program, the compiled program is executed. It can result in an exception.

  • If initialization succeeds, and the specified module name has not yet been associated with a module, the the module name is associated with the initialized module.

Note that, during module initialization, another module loading can be done. For example, the source program of module A might load another module B.

Recursive module loading is not permitted. For example, if initialization of module A results in module loading of module A, it can cause an exception.

3.2. Module naming rule

The module name must match the regex pattern: ([a-z_][a-z0-9_]*/)*_*[A-Z][A-Z0-9_]*.

Examples of valid module names:

  • MAIN

  • kink/STR

  • kink/test/TEST

  • org/example/_internal/INTERNAL_MOD

  • com/example/_PRIVATE_MOD

3.3. Builtin modules

The runtime provides builtin modules. You can see the specification of public builtin modules at Builtin library API. There can also be private builtin modules which are not parts of the public API.

Builtin modules have higher precedence than module source program files on the file system. It means, when a builtin module is found with a specified module name, no search is performed on the module paths.

3.4. Module source program

A module can be loaded from a source program file on the file system. The module source program is searched on module paths specified by add_path function of kink/MOD module, or --path option of the commandline (see -p {Mod_path} / --path {Mod_path}).

3.4.1. File path

A module source program can be located at the file path which concatenates a module path, the path separator, the module name, and the suffix .kn. For example, assume org/example/TARAI is the module name, and the module paths are /home/you/kinkmod and /usr/share/kinkmod. In that case, the source program file can be located one of the following:

  • /home/you/kinkmod/org/example/TARAI.kn

  • /usr/share/kinkmod/org/example/TARAI.kn

3.4.2. Charset

Module source programs must be encoded with UTF-8 charset.

3.4.3. Initialization

On initialization, the source program is compiled and executed with a binding. After the execution succeeds, the binding is associated as the module with the module name.

Therefore, top level variables of the program can be accessed as variables of the module.

3.4.4. Example

Assume you have a module source program file of org/example/rat/RAT module, at /home/me/mymods/org/example/rat/RAT.kn as follows.

:new <- {(:Numer :Denom)
  new_val(
    ... Rat_trait
    'Numer' Numer
    'Denom' Denom
  )
}

:Rat_trait <- [
  'numer' {[:R]
    R.Numer
  }
  'denom' {[:R]
    R.Denom
  }
  'repr' {[:R]
    '{}/{}'.format(R.numer R.denom)
  }
]

Assume you have a program file client.kn at the current directory. client.kn uses RAT module.

:RAT.require_from('org/example/rat/')

:Rat <- RAT.new(1 3)
stdout.print_line('rat: {}'.format(Rat.repr))

You can execute client.kn as follows.

$ kink --path /home/me/mymods client.kn
rat: 1/3

Since RAT module is a binding, it has preloaded functions such as if and nada. It also contains a non-public variable Rat_trait. Access to those variables which are not parts of the public API of the module should be restricted to unit software testing.

:RAT.require_from('org/example/rat/')

stdout.print_line(RAT.nada.repr)      # => nada
stdout.print_line(RAT.Rat_trait.repr) # => ["numer" (fun ,,,

3.5. Launchable module

If a module have main function, it can be executed by the commandline. See kink and kinkw commands for details.