How are EK9 source files structured?

← Getting Started · Ref: Q5

Every EK9 source file follows this structure:

1. Shebang line: #!ek9 (required first line, enables direct execution on Unix)
2. Optional comment header between doc comment markers
3. Module declaration: `defines module <dotted.name>`
4. Optional `references` block (imports from other modules)
5. One or more construct blocks inside the module

Idiomatic ordering of construct blocks (top to bottom):

  defines type        type aliases and constrained types
  defines constant    named constant values
  defines record      data-only types (fields, constructors, operators)
  defines trait       interfaces for polymorphism
  defines class       full object types with methods and operators
  defines function    standalone functions
  defines component   dependency-injected types
  defines text        internationalized text templates
  defines service     web service endpoints
  defines application wires components together
  defines program     executable entry points (always last)

Within aggregates (classes, records, traits) the ordering is enforced by the grammar:

  1. Properties/fields
  2. Constructors and methods
  3. Operators
  4. default operator (generates synthetic operators like ==, <>, $, #?)

Style guidelines:
- Use only ONE `defines <construct>` block per type per file (avoid scattered blocks)
- Multiple files CAN share the same module name, splitting a module across files by concern
- Directory structure is your choice (unlike Java, the module name does not dictate the path)

One module per file. The module name is the namespace for everything defined in it.

For module organization, run: ek9 -q organize code modules

See Q6 for organizing code into modules. See Q16 for indentation rules. See Q17 for entry points with defines program. See Q18 for comment styles. See Q20 for file extension.

Example

defines module qa.getting.started.source.file.structure

  defines constant
    Greeting <- "Hello from EK9"

  defines function
    decorateMessage() as pure
      -> message as String
      <- result as String: `[${message}]`

  defines record
    Person
      name as String: String()

      Person()
        -> n as String
        name :=: n

      default operator ?

      operator $ as pure
        <- rtn as String: name

  defines program
    ShowStructure()
      stdout <- Stdout()
      person <- Person("Steve")
      decorated <- decorateMessage($person)
      stdout.println(Greeting)
      stdout.println(decorated)

Common mistakes

E08180 — Class and record fields must be initialised inline. Leaving a field uninitialised produces E08180. Use an explicit constructor call or literal value. See ek9 -h E08180 for details.

Incorrect:

name as String

Correct:

name as String: String()

E07520 — The ? operator is inherited from the base and must use 'override' or be generated with 'default'. Declaring 'operator ?' without 'default' or 'override' triggers E07520 because the bare declaration lacks proper return semantics. See ek9 -h E07520 for details.

Incorrect:

operator ?

Correct:

default operator ?

E01030 — Defining a function with the same name as a record in the same module creates a name collision between different symbol kinds. Triggers E01030 — variable/function/type duplicated. Each name must be unique within its module. See ek9 -h E01030 for details.

Incorrect:

Person() as pure
      -> message as String
      <- result as String: `[${message}]`

Correct:

decorateMessage() as pure
      -> message as String
      <- result as String: `[${message}]`
Other ways to ask this
  • What is the structure of an EK9 file?
  • How do I organize an EK9 source file?
  • What sections does an EK9 file have?

Coming from another language?

Python: modules with imports and classes/functions at top level. Java: one public class per file with package declaration and directory must match package name. Rust: mod/crate system with use statements. Go: package declaration with func/type/var. Unlike Java, EK9 does not require directory structure to match module names.

Keywords: construct, section, first, source, defines, module, beginner, file, structure, layout, organize, start, ordering, migrate, intro