BRiX
Advanced Computing Environment
Hosted by SourceForge
brix-os project page

Previous: Void ----- Up: Contents ----- Next: Functions

Modules

show notes
Features that need to be added to the page or ideas that haven't been thought out.
  • module versioning to prevent API problems with module interfaces and more importantly version mismatches with object structures which could lead to memory corruption.
    • DEFMODULE needs a version number parameter
    • IMPORT needs a way to specify minimum (inclusive) and maximum (exclusive) versions allowed for the module being imported
      		import foo 1.0 only // =1.0
      		import foo 1.0 // >=1.0
      		import foo 1.0 to 2.0 // >=1.0 and <2.0
    • types used in the module interface must be exported by the module or by one of the modules it imports. if exported by an imported module, the compiler will embed a link to the imported type in the module's interface. any module that imports this module will see the link and pull in that type from the other module, but only the type and not the entire module. directly importing that module will not cause a interface collisions with the links. the links also carry versioning information.
    • the major version number should always be incremented when the API deviates from the existing API. the minor version number should be incremented for new features or when the API is extended in a way that doesn't break compatibility with the existing API. the third version field would be incremented for each release that doesn't modify the API, such as bug fixes, minor optimizations and other minor enhancements. the developer is of course free to bump the major and minor version numbers for changes that don't break compatibility but there should be a good reason to do so. odd minor versions should be reserved for developement releases.
    • when the major version is zero the minor version should represent API incompatibilies and major feature releases while also maintaining odd versions as unstable developement releases.
    • the compiler must be able to detect API changes in module interfaces and types, and ensure the major or minor version is increments to prevent problems.
  • supported platform tags for modules. supports all by default. only supports given platforms when provided.
  • PROVIDES extension to list capabilities (with descriptions) provided by the module. importing these modules prompts the user for permission to use the capability. assembler and driver DSL modules provides a low-level capability. network module provides a networking capability.
  • type namespaces can be parameterized, should modules also allow parameterization?
  • (IMPORT long_module_name AS short_name) or
    (IMPORT short_name = long_module_name)?
    	import (foo, bar, baz) // multiple imports
    	import f = foo // short name import
    	import (f = foo, bar, baz)
    	import foo as f
    	import (foo as f, bar, baz)
  • flag to allow private submodule slots to be accessible by its parent module but not by any modules importing it or its parent?
  • module tests

A module is a container of immutable slots for functions, extensions, types or data. The compiler operates in declaration only mode while in the module scope and thus disables the := operator, allowing all declarations with the = operator. The name is required for top-level modules and not allowed for submodules which must have their name set via the = operator.

DEFMODULE name definition
  • name -- required/optional module name
  • definition -- block expression [slot declarations only]
	defmodule foo {
	  // increment function
	  increment = def (x) return x+1
	  // constant pi value
	  pi = 3.14
	  // Point type
	  Point = deftype () {
	    constructor (x, y)
	    slot (x, y) = (x, y)
	  }
	  // submodule
	  bar = defmodule {
	    ...
	  }
	}

Prefixed Slots
By default all module slots are available unprefixed to other members inside the module but prefixed when used by other modules. This can cause problems if the module defines a new type that collides with a type from another module. The `prefixed flag will require the module prefix even when used inside the module defining it.

	defmodule foo {
	  // declare a new String type
	  `prefixed String = deftype ...

	  s1 = "foo":String // tetra's String
	  s2 = "foo":foo.String // foo's String
	}

Exporting Slots
All slots are by default private to the module or submodule and not accessible beyond its scope. The `export flag exposes the slot outside of the module and the `export-root flag puts the slot in the root namespace without requiring a module prefix. Slots exported from submodules are only available in the parent module unless the parent also exports the submodule slot. Slots exported to root from a submodule are always in the root namespace of any module importing the submodule or one of its parents. Exporting to root should be used sparingly as it contaminates the root namespace of modules importing these slots.

	defmodule foo {
	  a = 1 // not exported
	  `export b = 2 // exported as foo.b
	  `export-root c = 3 // exported as c
	}

	defmodule bar {
	  import foo
	  a = foo.b + c
	}

Importing Modules
Dynamically links a module into the current module and pulls exported slots into the namespace without changing the interface of the current module. Interface and abstract modules are not fully implemented and may not be imported, only inherited. The system must always have a default implementation available for abstract module definitions so the compiler can pull it in when the abstract parent is requested for import. The implementation may supply additional interfaces beyond what its abstract parent defined but none of them will be imported unless the implementation module is directly imported.

IMPORT module
  • name -- required module name or list of module names
	import foo
	import (bar, baz)

Submodules are imported without their parent prefix.

	import foo
	foo.bar.baz()

	import foo.bar
	bar.baz()

Inheriting Modules
Module inheritance is similar to type inheritance allowing modules to extend other modules or provide implementations for interface only modules. Private parent slots are made available to the child module and exported parent slots are added to the child module's interface.

INHERIT module
  • name -- required module name

Module Binaries
If a module has exported extensions they are compiled into a separate binary. The runtime binary is dynamically linked against modules importing it while the extension binary is only loaded for compilation. Submodules are compiled into the corresponding binary unless exported in which case they are compiled into their own set of binaries and may be imported separately from their parent module.

Window objects store all widget code in anonymous modules that are bound to the window object and can not be imported. The window objects and their code are managed by Tetra and modified via IDE popups over the widgets when the window is in edit mode.

Types of Modules
The standard module definition produces a dynamically linked library containing slots imported by other modules. Tetra is however designed to manage all code in the system as a means of safety and security. Therefore, all code is handled as modules and registered to various services. These registered modules can not be imported.

Various classes of services and hardware are represented with submodules.

Previous: Void ----- Up: Contents ----- Next: Functions