Skip to content
LexerLangv0.1.0

Classes and modules

static and dynamic classes, module, self, and importing files with use.

LexerLang
static class Person          # called without "new"
dynamic class Animal         # only with "new"
module Settings              # a second name for static class

dynamic class#

LexerLang
dynamic class Animal
    $species as string
    $age as int32

    func __construct($species as string, $age as int32) as void
        self.$species = $species
        self.$age = $age
    end func

    func make_sound() as string
        return "This is a " + self.$species
    end func

    func __destruct() as void
        out("destroying: " + self.$species)
    end func
end class
LexerLang
$a = new Animal("dog", 3)
out($a.make_sound())

The body holds only field declarations ($name as type) and functions. Free statements are not allowed — when they would run would be unclear.

Reaching a dynamic class member without new is an error.

static class and module#

LexerLang
module Settings
    $port as int32

    func address() as string
        return "http://localhost:" + self.$port.to_string()
    end func
end class
LexerLang
out(Settings.$port)
out(Settings.address())

If the constructor takes no parameters, a single instance is created when the file loads and its members are reached directly. If the constructor takes parameters there is no such instance; the class is only instantiated by calling it:

LexerLang
$p = Person("Ahmet", 25)     # static class — no "new"

self#

Inside methods, the instance itself. It cannot be used outside a method.

Importing files#

LexerLang
use "/lib/site.lx" as site
use "helper.lx"              # without "as", the package name is used
PathResolved against
"/a/b.lx"the project root — the directory of the entry file
"b.lx"the containing file — the file next to it

The distinction is deliberate: a root-relative path stays correct when the file moves, and a relative path is short for neighbouring files.

LexerLang
$p = classes.Person("Ahmet", 25)
$a = new classes.Animal("Dog", 3)
out(functions.add(5, 10))

Scope#

An imported file runs in its own scope: it does not see the caller's variables and cannot change them. Only exported classes and functions enter the namespace — variables are not shared.

This decision shapes how the language carries state. You cannot keep a module-level "which language are we in" variable; that information either travels as a parameter or lives in $app.globals.

An imported function or class method sees the names of its own file, not the caller's.

Even if the same file is imported several times in one run, it runs once — its side effects, such as opening a connection, should not repeat. Circular imports are an error.

Exporting#

Classes whose names start with a capital letter are exported.

External libraries#

LexerLang
use_lib jwt

Coming in phase 2; today it raises an error saying which phase it is in. Quoted use is in-project, use_lib is out-of-project — where a name comes from is visible as you read.

Next#

Error handling.