ODL declarations consist of named classes, parameterized classes, records, fields, slots, and constraints. The constructs class, op, fn and record introduce named scopes.
Class declarations may be nested within others. Class names introduced at the same scope level must be unique. Name resolution for embedded classes, fields and slots follows most-closely-nested rules but may be redirected via the name :: operator, where name is a named scope introducer. Any name may be qualified as local, which disables reference outside of the current scope except within constructor expressions.
The top-level declarations of an entire ODL program are considered to be encased within class System ... end. Class System must contain single user-defined operation main. An ODL implementation must support a command equivalent to (new System(...)).main(...) that constructs object system and initiates execution.
Normally, classes (new types) must be declared before they are otherwise referenced. However, mutually referential classes can make this impossible. To support mutually referential classes, they can be declared by enclosing them within with (classList) ... end. The classList specifies the classes which refer to each other. The only other exception to the ``declare before reference'' is for generator statements which may mention as-yet undeclared classes.