Users › 02 Program structure
Understand how files, names, imports and visibility fit together before writing real classes.
A file starts with exactly one primary directive, followed by its members:
%class com.example.Parser
// fields, constructors, methods
%sub Lexer
// a file-private helper class
%sub Token
// another one
| Directive | Meaning | Implementation | Instances |
|---|---|---|---|
%class | public class | Lopolith | many |
%interface | interface | Lopolith | — |
%simple | singleton class | Lopolith | exactly one |
%native | class implemented in a .so | C plugin | many |
%nativesimple | native singleton | C plugin | exactly one |
For %class, %interface, %simple and the
native forms, the file path mirrors the fully-qualified name:
com/example/Parser.loth ⇄ %class com.example.Parser
The compiler checks this both for the file you compile and for every dependency it loads by name. The one exception is the file you pass on the command line, which may live anywhere.
%class com.example.Main
#import com.example.Parser
#import miao.Test as T
#importlocal Helper
// fields and methods below
%sub body.#import <fqn> brings in any fully-qualified name;
as renames it.#importlocal Name resolves Name inside the
current package (the directory of this file)._LANG
(String, Main, Exception, the built-in
exceptions) are imported automatically.#import Std before using Std.print.Once a module is loaded (directly or transitively) you may also refer to its classes by full name without an import. Short names still need an import.
| Entity | Default | Public | Private |
|---|---|---|---|
| Field | private to the class | pub | default |
| Method | public | default | _ prefix |
| Interface member | — | always | not allowed |
%sub member | file-wide | — | — |
| Type | public | default | %sub (file only) |
Fields are private unless marked pub, and methods are public
unless their name starts with _. Field access always goes through
this., even inside the class.
%sub%sub declares a class that lives inside one file. Define it as
%sub Name, use it as $Name. Its members are all
file-wide public (no pub, no _), it can implement
interfaces and have constructor overloads, and it never appears in a public
signature. It is the replacement for anonymous or one-off classes.
%simple com.example.structure.Demo implements Main
int run(int argc, String[] argv) Main@run {
$Point p = new $Point(2, 3)
return p.sum() == 5 ? 0 : 1
}
%sub Point
int x
int y
void ___init(int x, int y) {
this.x = x
this.y = y
}
int sum() {
return this.x + this.y
}
(This program produces no output; it only has to exit with code 0.)
// one line
/* several
lines */