All Classes and Interfaces
Class
Description
Common abstract base class for all specialized ASM generators.
Base class for assert expression generators (assertThrows, assertDoesNotThrow).
Result of building the assertion expression body.
Abstract base class for control flow bytecode generators.
Acts as a base for the main construct definitions.
The abstract base on most antlr listeners.
Base class for all IR generators providing common utilities for safer symbol access,
temporary variable creation, and type extraction.
C' (Steve, 2026-10-08): an ABSTRACT
$, $$ or #? declared on a type that HAS fields,
counting inherited ones, is an error (E07185), reported at the abstract operator.Once an expression has been assessed as being simple enough to process, this
consumer is called to mark the appropriate symbol(s) used in the expression as safe if the
appropriate methods are called.
Both AND/OR are very similar in processing, the only real differences are:
What operation to call and the op code to generate.
What operation to call and the op code to generate.
THE shared vocabulary for stream pipeline IR generation - extend this rather than re-deriving any
of these steps inside an individual stage.
Base class for synthetic operator generators.
An entered cycle guard: the variable holding the owner name, needed again by the matching exit.
Record bundling scope context with initialized instruction list.
Represents an abstract value in the value-tracking lattice for flow analysis.
Pulls out the common code for variable and variable-only declarations.
Validates that application blocks do not have too many registrations (E11042).
Emit error if there are too many arguments.
Validates class design patterns for Construct Misuse Detection (E11022-E11025).
Checks cognitive complexity at function/method/operator exit and emits error if too high.
Checks LCOM4 cohesion against thresholds and emits errors if exceeded.
Checks the combined complexity and statement count at function/method/operator exit.
Looks for the complexity value in the complexityCounter and adds the value to the
appropriate symbol.
Checks efferent coupling (Ce) against thresholds and emits errors if exceeded.
Checks expression complexity when a coalescing expression tree completes.
Checks inheritance depth (DIT) against thresholds and emits errors if exceeded.
Validates DI injection design quality for components (E11040).
Validates DI injection design quality for a single callable (E11043).
Validates module-level cohesion against threshold and emits E11017 error if exceeded.
Validates module-level efferent coupling against threshold and emits E11016 error if exceeded.
Validates the number of constructs declared in a module against
MetricLimits.MODULE_SIZE and emits E11027 if exceeded.Checks nesting depth at function/method/operator exit and emits error if too deep.
Checks statement count at function/method/operator exit and emits error if too many.
Uses the symbol and scope management to traverse back up stack to determine if
the outer parent is a generic type or not and also if this symbol passed in is a generic type.
Just gets the left and right hand side of values in an expression.
Just gets both of the ternary expression parts (not the control).
Check that a symbol can be accessed issues error if not possible.
THE record of which scopes are entered in which ACTIVATION during an
IRStructureWalk: the operation body is
one activation, and every per-iteration list (CompositeInstr.Activation.PER_ITERATION) starts a new one for
as long as it is walked.THE static acyclicity of a generated aggregate for the cycle collector (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §4.2,
§12.2 items 4-5, §14.2 S3).
THE add-if-not-already-there by IDENTITY:
item is added to list unless that very object is already
in it.THE write of a derived RETAINS rule: marks the callable as DERIVED and adds the rule text.
The
SAFE_POINT after_threads of one instruction list (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, T10):
after the exit of the innermost scope in this list that holds a call which starts runtime threads and finishes only
once they have all stopped (StartsAndStopsRuntimeThreads) - an async pipeline's statement scope, the scope
of a server's accept or serve.Common code of Aggregate Construct types.
Deals with the creation of various aggregate types.
Predicate to see if an aggregate mandated pure in its construction.
Support for taking one aggregate and manipulating the methods and the like to be applied
to another aggregate.
THE order of the members of an aggregate body (E01086, Steve 2026-10-11): properties first, then constructors and
methods, then operators (an explicit
operator, override operator or default operator X,
in any order among themselves), and a bare default operator as the LAST item of all.The first member of a body out of order.
E01086: the members of an aggregate body (class, record, trait, component, dynamic class) out of the order EK9
requires - properties, then constructors and methods, then operators, then at most one bare
default operator as the last item.Data structure to facilitate checks on methods on an aggregate.
Code quality metrics for a class, record, or component.
This is typically a 'class' or an interface type where it can include the definitions of new
properties.
An aggregate, but one that can have zero or more traits (like interfaces).
EVERY operator of one name declared ABOVE an aggregate - each level's own overloads, nearest level first, never
Any's.Enforces 'allow only' constraints on traits and classes (sealed type pattern).
Reviews all the modules and looks for all the 'Programs' that have been defined anywhere.
Checks that all the text bodies that are on the super are also present in the language variant.
THE "is a value of EXACTLY this type always set - its '?' the one synthesised for a field-less type
(
IsSynthesisedIsSet, Q-COMPONENT-?), answering true?" Read by phase 5's value tracker (F3, Steve
2026-10-07): s <- FieldlessType() then if s? is provably true (E08088), as Integer() is
provably unset.Checks call sites for ambiguous positional arguments.
Emits the
Any-typed comparison bridge methods (_eq(Any) / _cmp(Any)) for
generated user aggregates.True when any stage's operator is
opType.Search for a symbol of any category with the matching name.
THE search for the built-in Any through a scope: the fully qualified name, of category ANY - a category only
AnyTypeSymbol has, so nothing a user declares can answer it.Special type that is super of Aggregate and super of Function (if they don't have supers).
Search for a symbol of any types category with the matching name.
Check that an application definition is configured in an acceptable form.
Generates a single global
_Application JVM class from application registrations.Binding information for a service registration that has HTTP routes.
THE application close (Steve, 2026-10-26, closeable matrix Q3 / row H2): an application closes every component it
registered that has an
operator close, when the program ends.Creates the appropriate IR Construct for an application declaration.
Checks for the appropriate use of the APPLICATION of xyz on a method declaration.
THE registrations of every application in the program (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11): each
register X() as Y with aspect of A() of every general and service application.Resolves each class in an 'allowingOnly' list (checking it is a suitable CLASS genus) and registers it
as an allowed extender of the supplied aggregate.
Resolves each trait in a 'traitsList' (checking it is a suitable CLASS_TRAIT to extend) and adds it
to the supplied aggregate.
Checks if the body of a method/operator is appropriate.
Checks if the body of a function is appropriate.
Holds argument processing results for method/function calls: the temporary variable holding each evaluated
argument and the resolved type of each argument.
THE labelling of a call's positional arguments from the parameter names the compiler resolved -
use this, do not split an argument list by hand anywhere else.
The corrected text plus one note per call labelled;
notes empty means nothing moved.THE argument question the argument readers ask (
RetainsArgument, HandsBackArgument,
KeepsArgumentBeyondResult, DefinitelyKeepsArgument, MayKeepArgument), so they differ only
in which rules count (wanted) and in whether the unknown opt-out answers for them
(unknownCounts): does a rule of callee (declared, derived, or the generic's own) that matches
wanted take the argument given at parameterIndex as its source? With unknownCounts, a callee
declaring unknown answers yes - also for an index it does not declare.Automated Readability Index (ARI) adapted for source code.
THE value each list of a chain hands to the chain's result: an arm's body result, the default's result - keyed by
the list's identity (two equal lists are two places).
Designed to capture the ASM specifics for byte code generation.
Specialized ASM generator for CREATE_ASPECT_PROXY instruction.
Generates a synthetic proxy class for aspect weaving.
Details for the CREATE_ASPECT_PROXY IR instruction.
Method signature information for proxy class generation.
High-level IR instruction for creating an aspect-woven proxy.
Validates assertDoesNotThrow expression and sets the return type to Void.
IR Generation for the assertDoesNotThrow expression.
EK9 assertDoesNotThrow expression - validates that an expression does not throw.
Validates assertPanic expression - the test-only counterpart to assertThrows that traps an
org.ek9.lang::Panic.IR Generation for the assertPanic expression.
EK9 assertPanic expression - asserts that the wrapped expression fires an
org.ek9.lang::Panic.Checks that the assert statement actually has a boolean result from the expression.
IR Generation for the assert statement.
Specialized ASM generator for AssertThrowsInstr processing.
Validates assertThrows expression - checks that the type argument extends Exception
and sets the return type of the expression to that exception type.
IR Generation for the assertThrows expression.
IR instruction for test-only assertion constructs that wrap expressions in try-catch.
EK9 assertThrows expression - captures an expected exception type and expression.
Used as simple one-liners to check a value and issue an illegal argument exception if empty.
THE assignment of an assignmentExpression to a symbol (the expression is generated by
generators.assignmentExprGenerator), in one of two AssignExpressionToSymbol.Modes - TWO per construct on the set,
generators.assignToNewSymbol and generators.assignToExistingSymbol (IR tidy W3.9, EXPR-15), never
one per assignment.What the assignment does to the variable's previous value.
Specialized generator for EK9 assign-if-unset (:=?).
Assign-if-unset generator using unified CONTROL_FLOW_CHAIN approach.
THE check of an assign-if-unset statement (
:=?) whose outcome the value tracker has DECIDED - both
outcomes, one class, one reading of the target (E08095 and E08097).Data class to hold parameters for assign-if-unset generation.
Used to decouple checks from the grammar contexts.
Just really pulls up the appropriate symbol from the expression into this context.
Creates IR instructions for assignment expressions.
Checks the assignments for operator : := = and :=? that's all.
Used in the full resolution phase to check assignments.
Check the assignment to a variable can be a single assignment or a deep copy type assignment.
Every assignment statement under a node, in source order - not counting code that runs later (a dynamic function's
body, a dynamic class's methods).
Process assignment statement: variable = expression
Uses RELEASE-then-RETAIN pattern for memory-safe assignments.
THE declared (target) type an
assignmentExpression is given to - use it, do not re-derive the walk.THE assignment statement an identifier is the TARGET of - on its left-hand side, reached directly or through an
object access (
this.count: 1) - or empty.THE heads that cap an
async (StreamDemand, decision 15 d): those reached from the async through
stages that pass EVERY item on - map, call, tee and another head - in pipeline
order.T8 (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11): in a stream pipeline that contains an
async stage, every
function a stage is given is a concurrent entry point - not only the element functions the workers run.Designed to add in methods on the aggregate where the 'traits' use is 'traits by'.
The ek9 developer does not need to redeclare incoming or returning parameters for dynamic functions.
THE back-edge placement of IR_OPTIMISATION: a point instruction at the end of every loop body of an operation - the
back edge, reached once per iteration after the body's own scope has dropped its values - unless one of the same
opcode is already last.
Supplies the compiler phases for the back end.
THE rewrite of a double-quoted String's text as a backtick String, delimiters included - use
InterpolatingBacktickString or LiteralBacktickString, the two spellings it gives; never re-derive
it.Test if a symbol is a BARE-defaulted operator, i.e.
Completes every bare 'default operator' once types are known, after every source has been through
EXPLICIT_TYPE_SYMBOL_DEFINITION (front-end audit FE74, F2).
THE test for a generic's bare type parameter
T itself, as opposed to a generic that HAS type parameters.Represents a basic block in the EK9 IR - a sequence of instructions with single entry and exit.
Factory for fairly basic symbols.
The
SAFE_POINT before_threads of one instruction list (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S0b):
ahead of each call that starts runtime threads (StartsRuntimeThreads).THE reading of a binary or prefix
expression alternative for the phase-1 operand-parentheses checks -
E08269 (CoalescingOperandParenthesesOrError), E08273 (NotOperandParenthesesOrError) and E08274
(DoubleNegationOrError).Generates IR instructions for binary operations (e.g., addition, subtraction, comparison, etc.).
CONCERN: Binary operator invocation with memory management.
THE operator token of a binary expression (
IsBinaryExpression): the coalescing token, the comparison
coalescing token, the op label, or - the 'in' alternative has no 'op' label - the in token.Parameters for binary operator invocation.
Holds one thing an application-block statement (a registration or a block statement) starts running: a call it
makes - a registration's constructor, a call in its arguments, an aspect's constructor - or a dynamic function or
class it creates.
Creates IR instructions for block statements.
THE
OperationBodyLocator of members declared in an aggregate's parts, matched by symbol identity (classes,
records, traits, components).THE
OperationBodyLocator of members declared in a service, matched by symbol identity: its methods first,
then its service operations (a service has no aggregate parts).THE body method of a program: the compiler-made
_main that holds what was written in the program, and
which IS the program wherever a person reads about it.THE step from an evaluated condition to what a branch reads - use this, do not re-derive it.
Parameters for boolean primitive extraction.
Creates evaluation instructions for Boolean._ofFalse() static method call.
Creates evaluation instructions for Boolean._not() method call.
THE IR
CallDetails for the non-virtual EK9 Boolean logical operators that the lowering
synthesises - _and, _or and ~.THE Boolean truth guard rule (Steve, 2026-10-07, decision D9.2) - use this, do not re-derive it.
THE rule B of the closeable ownership decision (Steve, 2026-10-21): may a value of this RETURN type hold a
borrowed VIEW of a closeable that was passed in - i.e.
Represents an unreachable program point — a contradiction in constraints.
Builds a grouping stage's per-item boundary condition into the drain inner body and returns the variable holding
its primitive boolean (the helper's
isKeyChanged/isBoundary result, already primitive).The outcome of walking a pipeline's stages from a source that is not bounded (
BoundednessWalk).THE walk of a pipeline whose source may be unbounded:
head bounds the stream; while it is not bounded
every stage needsBounded accepts is a violation; and once an async has run on the unbounded
stream, an async barrier (IsAsyncBarrier) is a violation even after a head.The symbol a recorded symbol BINDS its occurrence to: for a call, the callable it resolved to, never the call
itself; anything else (null included) as it is.
Specialized IR instruction for control flow operations (BRANCH, BRANCH_TRUE, BRANCH_FALSE, ASSERT, RETURN).
Specialized ASM generator for BranchInstr processing.
The runtime tracker a bucketing stage accumulates into, and what it hands downstream.
Everything a buffering stage needs.
The ordered
ValueClassId vocabulary for a built-in leaf type (BuiltinTypeClassModels), or empty
when not seeded.Just resolves a number of built-in types so that internal compiler code can be more explicit.
The built-in-type seed for the input-variation metric's denominator: the
TypeClassModel (class count + confidence) for each EK9 built-in.To be used in EK9 source code to assert that generated JVM bytecode matches expectations.
Checks if there are any directives that relate to @BYTECODE in the parsed module and validates
the generated JVM bytecode against expected output.
Executes generated EK9 bytecode within the current JVM.
Result of executing a generated EK9 program.
Restores the fallbacks a
BytecodeExecutor.redirectUncaptured(PrintStream, PrintStream) call displaced.Context for bytecode-generation control flow.
Dispatch case for FOR_RANGE_POLYMORPHIC three-way generation.
Normalizes JVM bytecode output from javap for stable test comparisons.
Functional interface to get the appropriate ErrorListener for a callable.
THE identity of a callable in the phase-5 call graph —
module::Aggregate.member(T1,T2) for
a method, module::Aggregate.member for any other aggregate member, and the plain
fully-qualified name for everything else.Metadata about a callable entity (function, method, operator, constructor, program).
Builder for CallableInfo to support incremental construction during AST traversal.
THE reading of what one callable does with its own parameters (and with each local made to refer to one): every
occurrence of such a variable is judged through
ObjectSharing and handed to
CloseableArgumentKeeping, which decides - after every source is walked - which parameters the callable
KEEPS beyond the call.THE declared parameters of a method, operator or function a RETAINS rule names; none for anything else.
THE shared check that a callable's returning values have been initialised: one class for methods, operators,
service operations and functions (it was four copies, one of which had drifted and dropped two guards).
THE short display name of a callable's identity:
some.module::Type.method(some.module::ParamType) reads as
Type.method(ParamType) - every module qualifier dropped, from the owner and from each parameter type
(a parameterised type's Dict of (m::K, m::V) included) - and a compiler-made name made readable
(FriendlyInternalName: _List_<digest> reads List, _Function_<digest> reads
fn).THE "can the existing operator be called with the candidate default's arguments?" - each candidate parameter type
assignable to the existing one's, same count.
THE evaluation of a call's arguments (EXPR-1): each argument expression is evaluated into its own managed
temporary (retained and scope registered by
VariableMemoryManagement), in source order, and the
temporary's name and resolved type are collected.Whether each argument's temporary carries debug info for the argument's own source position.
THE callback-reachable operations of a program: those the runtime may call - directly, or through other operations -
while one of its C frames is live below them (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §14.3).
Context information needed for resolving method calls and constructing CallDetails.
The ownership facts of one call (EK9_IR_OWNERSHIP_MODEL.md §5): which arguments the callee CONSUMES (every other
argument is GUARANTEED - borrowed for the call), whether the result is OWNED (+1, the caller must end it) or
UNMANAGED (no count at all), and whether the call may throw.
Used with CallInstr, holds all the necessary details to make a call.
The four kinds of CALL - see the record javadoc.
Composable builder for creating CallDetails with cost-based method resolution and promotion support.
Result of building CallDetails including any promotion instructions needed.
THE factories for the recurring
CallDetails shapes in IR generation - hold one
(private final CallDetailsFactory callDetailsFactory = new CallDetailsFactory();) and call it.Provides IR Call details for making a call to the EK9 Boolean type to call the _false() method.
Just provides the IR Call details for making a call to the Ek9 Boolean type to call the _true() method.
Supplies the call details to get a Boolean false value.
Represents an edge in the call graph from caller to callee.
THE symbol an IR call runs, read back from what the call names: its target type (a user construct of the program's
IR first, else a type or function the program resolves by fully qualified name - a core type, a parameterisation),
the method by its IR name (
OperatorMap.resolvedMethodName(MethodSymbol), so _addAss finds +=) and the
fully qualified types of its parameters; a function's _call is the function itself.THE method or function a recorded symbol CALLS, when it is a call that hands back a value made elsewhere: a
method, operator or function call - never a constructor, whose result is always fresh.
THE method, operator or function an expression CALLS when the whole expression is that call -
a.get(k),
first(), a + b, (a.get(k)) - so its value is whatever the call handed back.Call graph for EK9 programs with bidirectional edges.
Collects call graph information during AST traversal in Phase 5 (PRE_IR_CHECKS).
How a collector gets the closeable ownership decision for its source.
Specialized IR instruction for method calls (CALL, CALL_VIRTUAL, CALL_STATIC, CALL_DISPATCHER).
Specialized ASM generator for CallInstr processing.
Generates IR instructions for function/method calls.
Metadata about method/function/operator calls that can be used by backends for optimization.
Extracts call metadata from symbols for use in IR generation.
Designed to deal with this following part of the EK9 grammar.
Details required for processing function calls in a context-aware manner.
True when the constructor makes an explicit
super(...) call (recorded in phase 3).Generate function invocation for a call stage.
Just re-uses the bulk of method symbol for when we want to make a symbol that is a call
to an actual method.
THE single source of truth for the descriptor OWNER and dispatch of a resolved call - the signpost of the family;
hold its parts, one question each, never re-derive them:
DefiningType - the type where a resolved method's body is actually emitted (its "defining
type"), the descriptor owner.
IsVirtualCall - the virtual-dispatch decision of a resolved call.
IsOpenAggregate - is a type open for extension (traits and abstract functions always are).
IsVirtualForSynthesisedCallee - the dispatch flag of a call the compiler synthesised.
IsNonDispatchableLifecycleMethod - the constructor, _i_init and _c_init, never
dispatched.
Reuse them from BOTH the resolved-method path (CallDetailsBuilder) and the chained object-access path
(ChainedCallDispatch) so the two never re-derive - and drift on - the CALL descriptor owner.Classification of call site types for call graph analysis.
The JVM lowering of
CANCEL_POINT (EK9_BACKEND_IR_CONTRACTS.md Contract 24): one instruction,CANCEL_POINT: a point where an async task the pipeline no longer needs stops (EK9_BACKEND_IR_CONTRACTS.md
Contract 24).THE placement of
CANCEL_POINT (EK9_BACKEND_IR_CONTRACTS.md Contract 24): an IR_OPTIMISATION pass over the
ownership form, run after SafePointPlacement, which states which operations are
callback-reachable.V-C (EK9_BACKEND_IR_CONTRACTS.md Contract 24), over the placed IR beside V-S: a
CANCEL_POINT only in an
operation CancelPointPlacement.isPlacedIn(OperationInstr) accepts - never in code no async task can run, nor in a class
initialiser - and in every such operation at the end of every loop body (BackEdgePoints.isLoopBody(CompositeInstr.NestedList)), so no
loop a task runs can keep it from stopping.Blocks direct assignment from sanitized parameters to local variables.
Pass 1 of the EK9 source formatter: Canonical Indentation.
🔑 THE canonical text for reconstructing a literal through an
org.ek9.lang _of(String) factory -
the single place that turns a literal's raw source lexeme into text _of(String) can actually read.Checks that gated system types are only used in publishable packages when the
corresponding capability has been declared.
THE identity set of a symbol and every copy of it captured inside a fragment of the COMPILED tree - what
SymbolUses counts as the same variable.A statement that gives one of the object's own properties a dynamic function or class capturing 'this'.
The capture-assignment statement (
CapturedInto) in which this 'this' is captured: it is the whole
expression of one entry of the capture list of the dynamic function or class that is the statement's whole
right-hand side.The capture-assignment statements (
CapturedInto) a constructor body makes, in source order, each with
the property it sets - not counting code that runs later (a dynamic function's body, a dynamic class's methods).Decides THE capture constructor of a dynamic class, creating the sole synthetic constructor when it must.
THE entry state of a dynamic class's capture constructor: its captures are stored before its first statement
(before
_i_init, and before a this(...) call), so each one is set from the start of its body.Records that a constructor is THE capture constructor of its dynamic class (
IsCaptureConstructor, which is
the only reader).THE parameter types of the constructor a dynamic class or a dynamic function is created through: one per captured
variable, in capture order, named from the construct's OWN captured variables - exactly as
FieldsFromCapture
declares its fields, so the call and the constructor it calls cannot disagree.Capture ownership by FRESHNESS (R-E, Steve 2026-10-06) - never by the named/unnamed syntax of the capture.
THE copy a dynamic function or class makes from one argument of its capture list (
CaptureAliases follows
these).The property of this object that the assignment statement gives a dynamic function or class capturing 'this'
itself (
child :=? (owner: this) with trait of Child as class ...), if it does - the parent link.Records what the captures of a dynamic class are to its constructors (phase 3 only, once the capture constructor
is decided).
THE "is this symbol one of the variables a dynamic function or class captured?" - by IDENTITY, never by name.
THE phase-3 answer to "whose code is running here?" for a property field (a private property or a capture) -
shared by the access check (E06180 in
IdentifierReferenceOrError) and the "read it through a capture"
wording of an unresolved name inside a dynamic body (IdentifierReferenceOrError, IdentifierOrError).A field of the code around a dynamic body, whether that body is a dynamic class's (else a function's), and
whether the code around it is itself denied the field (a super's property, D81).
Used to actually hold the captured symbols.
Just focuses on the ability to possible capture variables from an enclosing scope.
The entries of the capture list whose expression is 'this' itself, when this right-hand side IS a dynamic
function or class; empty for anything else.
THE stores of a dynamic class's or dynamic function's captured values into its fields (DFN-6): each captured
variable, in order, is a property of the construct - a slot its OBJECT owns - and takes its own reference to the
value captured:
SLOT_ASSIGN this.x, x [copy, init] (OwnershipStatements.propertyAssigned(String, String, boolean, DebugInfo)),
lowered to STORE this.x, x; RETAIN this.x.IR instruction for explicit type casting.
Specialized ASM generator for CastInstr processing.
THE dispatch decision of a method call made in an object-access CHAIN (
a.b().c(), super.m(),
TraitName.m()) - a pure function of the resolved method, the receiver's static type and the call's shape
(EXPR-17).Every type a close of this type reaches through its chain - the static types of the closed fields and the
owner of the parent close - for the call graph (each is called by the generated close).
The call chain that starts at a variable or
this: a link that may return a VIEW of what it was called on
makes the result the same object as (part of) the receiver.Single step in a
DeadlockChain's rationale trace.The value of a Character constant: one Unicode code point (Steve, 2026-11-04), ordered as the runtime orders
Characters.
The value of a Character literal - quotes removed and escapes decoded (
DecodedEscapes) - the text a
Character constant is recorded with.THE value of an EK9 Character literal (quotes already stripped), as its Unicode code point (Steve, 2026-11-04: a
Character is one code point, so a literal above U+FFFF such as an emoji is one - it was an internal compiler error,
D94, while this returned a 16-bit char).
Deals with normal operators (i.e.
Checks that the use of the variable only if it has a web variable correlation is valid.
Checks that methods from a super and one or more traits do not conflict.
If the aggregate is a generic parameterised type this function triggers a check for duplicated methods.
Error when the definition of a service is invalid.
Error when the definition of a service operator is invalid.
Checks that a service operation has a security posture, either inherited from
its parent service or declared on the operation itself.
THE check that a service is written in its one form (Steve, 2026-10-11):
for before every URI - the
service's own (Items for :/items open) and each operation's (byId() as GET for :/{id},
operator += for :/) - and as before an HTTP verb.What an operator check needs: the operand, where the operator is used, and the operator search.
How trustworthy a type's value-class set is — the honesty tag for the input-variation metric.
Creates the appropriate IR Construct for a class declaration.
The debug-time reader of one class's EK9 source lines: the source it was compiled from (
SourceFile, the
.ek9 name) and every line any of its methods has code on (LineNumberTable).Decides whether a construct's modifier (
as open / as abstract) may legally be
toggled to a proposed state — the "declaration viability" of the modifier refactoring.The four modifier toggle modes.
Outcome of asking whether a class's modifier (
as open / as abstract) may be
changed — the "declaration viability" layer used to gate the class-modifier toggle tooling and
to decide whether the IDE should even offer the refactor.THE
OperationBodyLocator of the members of a monomorphised COPY, matched to their declarations in the
generic's aggregate parts by source token: phase-6 type substitution clones each method and keeps its source token
(the same object), so the token is what still links a clone to the declaration it came from.THE re-typing of members that were cloned from a template onto their new owner - use this, never a variant.
THE record of which constructor parameters a constructor KEEPS as a closeable property, and the deferred verdict
on every construction that hands such a parameter a value that is not new (R4 of the fresh-store rule, E81062).
What a construction does with the argument it is given at one position - decided only after every source has
been walked (
CloseableArgumentKeeping.check()).A variable of one callable's body - one of its parameters, or a local that may refer to the same object -
compared by identity.
R7 of the closeable ownership rules (Steve, 2026-10-05): closeability cannot be erased by a store (E81059).
If you hold it, you close it (E81067, Steve 2026-10-06, D8/C5): a class, record, component or dynamic class with
a closeable property - or a capture it owns (R-E) - must DECLARE its own
operator close:
default operator close or one it writes.The NAMED half of the closeable ownership rule (Steve, 2026-10-05): "A closeable value you never NAME is
owned by the statement that created it and closed when that statement finishes; a closeable value you
NAME must be declared as a try-with-resources resource." (E81056).
THE rule that a closeable type is never a type argument (E81061, Steve 2026-10-06, option A - strict).
Checks if a symbol should be tracked as a closeable resource.
R5 (Steve, 2026-10-05): a method, operator, function or dynamic function whose DECLARED return type is closeable
must return a NEW instance (E81057).
THE fresh-store rule for closeable SLOTS (R-A, Steve 2026-10-06, decisions D3 and D9, with R-D): every closeable
object has exactly ONE owner, so a closeable value may enter a slot that will close it only when nothing else
already owns it.
THE target of a compiler-generated
close call - try-with-resources, the closeable temporaries a
statement owns and the generated close chain all reach it through ResourceCloser.closeCall, so they
cannot name different owners or dispatch differently.THE generated close chain in IR - use it, never build a property close by hand (Steve, 2026-10-06: "if you hold
it, you close it"; the C++/Swift destructor model).
The fields the type's close closes, in acquisition order: owned captures (
OwnedCaptures), then own
closeable properties - never an injected one, nor the delegate a by-delegation proxy close forwards to
(the exclusions are listed on CloseSteps).Generates synthetic IR for
default operator close (_close): nothing but the generated close chain
(CloseChain, deciding through CloseSteps).The close operator is never called by EK9 code (E81060, Steve 2026-10-05, 2026-10-06).
THE close operator of an aggregate: the one
operator close a call to close resolves to (its own,
or inherited), or empty when it has none.THE decision of what a type's
operator close is responsible for - use it, never re-derive it.THE generated chain of a type's close (
CloseSteps): what it closes (ClosedProperties) and the parent
close it then calls (ParentClose).E07187 (D24 Q4 REVISED, Steve 2026-10-20): the comparison coalescing operators
<? and
>? select one operand by <=>.E08269 (Steve, D6, 2026-10-07): a coalescing operator - the Elvis
?:
and the comparison coalescing family <? >? - may not be an UNPARENTHESISED operand of a
DIFFERENT binary operator, nor take one as an operand.Used for variable forms of simple code flow analysis.
Designed to be used in a transient manner when interacting with variables.
Generate all type of aggregates, typically classes, components, records, etc.
SINGLE THREADED.
MULTI THREADED
Generate all constants that have been defined.
SINGLE THREADED
Preparation to generate code.
SINGLE THREADED
Optimise the generated code.
Tracks cognitive complexity within functions/methods/operators.
Tracks method-field relationships to calculate LCOM4 (Lack of Cohesion of Methods v4).
THE shared "promote a collection-literal element to the collection's resolved element type" step.
What a value of one type needs to enter a slot of another (EXPR-11).
Represents a variable known to be a collection or container type with both SET/UNSET
and EMPTY/NON-EMPTY state tracked.
Parameters declared the way other languages declare them (was
ParameterDeclarations.commaSeparated):
-> a as Integer, b as String - several parameters on one -> line.Pass 4 of the EK9 source formatter: Comment Interior Re-indentation.
Just for details that are common to all factories.
For use when looking to find common types.
Which common type
CommonTypeOrError is asked for.THE common-type deduction - for collections (List/Dict literals, ranges, stream 'cat') and for the
operators that SELECT one of their operands (?:, <? >?, the ternary).
Given a list of symbols (normally variables), this code will get the type from each of those symbols.
Fixed set of constants that tend to be used to 'squirrel' away data - these are the keys.
Given a symbol, this check that the type that the symbol has can support the '<=>' operator.
The fields a generated
<=> walks for one type: its properties and, for a dynamic class, its captures
(GeneratedOperatorFields; D62 - a capture is a field, not a property).Generates synthetic IR for the _cmp (<=>) operator.
Specialized generator for EK9 comparison coalescing operators (
<?, >?).CONCERN: Comparison evaluation with boolean primitive extraction.
The canonical vocabulary of EK9 comparison-operator glyphs, as named subsets, so that PRE_IR checks
reference a single source instead of hand-spelling (and silently diverging) their own switch/Set
each time.
Parameters for comparison evaluation.
Represents the whole program(s) that the developer is attempting to create.
Holds a reference to the name of the file being compiled a checksum of the
file and the date time last modified.
Check to see if any of the compilable sources have errors.
Populated in the compilable program and altered during each of the phases of compilation.
As and when sources are processed during each phase of the compilation.
For compiler, errors, warning and other information from the compiler.
Identifies the ordered set of compilation phases used in EK9.
Register this event listener with the compiler to pick up on
any warnings of errors during compilation.
THE phase a
-D"ek9.internalError.at" value names: null when it is unset or blank, the
phase when it is a phase name (surrounding spaces ignored, case kept).Effectively a tuple for returning if the phase was a match for the required
compilation phase to be run to and if this phase ran ok.
One step of a compilation: it runs exactly ONE
CompilationPhase, and says which.Conceptual compiler.
Shared compiler surface for MCP tools, Oracle extractors, AI sessions, and the IDE.
A diagnostic entry from compilation, usable by any
CompilerAccess consumer.THE one statement of which error codes concern COMPILER DEVELOPMENT rather than writing a program (site-examples
spec §6, Steve 2026-10-11, Q5): E50200 to E50390, the codes the development directives report -
@Error,
@Resolved, @Complexity, @IR, @BYTECODE, @Probe, @Squirrelled,
@InputVariety, @Obligations and the rest.Our wrapper for an unchecked exception.
Used to drive how the compiler operates.
THE marking of a type whose every member the COMPILER writes - an enumeration and a constrained (or alias) type:
each member is synthetic and has a source token, set by the front end where the members are made.
Marks the specific activity of a compiler phase.
THE definition of which callees are compiler↔runtime PLUMBING rather than part of the EK9
program.
Just expends the standard reporter to use the EK9Comp message prefix.
Evaluates a
ConstraintExpr against a compile-time-constant subject value, returning a
tri-state verdict.PASS = constraint satisfied; FAIL = provably violated; UNKNOWN = cannot determine statically.
Is the value of an expression KNOWN WHEN THE PROGRAM IS COMPILED - that is, made only from text written in the
source? Used by
UrlTextKnownAtCompileTimeOrError (E08275, decision U3 of
docs/architecture/EK9_URL_TYPE_DESIGN.md §0).Designed to give a broad indication of complexity, this is not true pure Cyclometric Complexity.
One popped region: its total complexity, and how much of that came from expressions.
To be used in EK9 source code to assert that a specific class or function has a particular level of complexity.
Checks if there are any directives that relate to complexity in the parsed module.
Creates the appropriate IR Construct for a component declaration.
An instruction that holds nested instruction lists - THE one statement of which lists a composite has, in which
order, and whether each runs once or once per loop iteration.
How often a nested list runs each time its composite runs.
One nested list.
Detects tautological and contradictory compound conditions using range algebra (E08086/E08087).
May a compound assignment (
target += item, target :~: item) to a value of this type keep its
operand? A container (a parameterised type, a bare T) does; so does a type of the program's own, whose
operator is written in EK9 and may store it - as any call of the program's own may keep its argument
(KeepsArgument; the verifier, 2026-10-21: registry += item, Registry's += adding
to its list, was read as keeping nothing, so a loaned closeable was closed by its statement and then used).THE whole
+ chain (WholeAddChain) round the cursor: the smallest binary + expression
containing it, then its chain (was StringExpressionClassifier.findEnclosingConcatExpression).THE rendering of a
+ chain as one backtick String - shared by the rewrite tool (StringConcatRewriter)
and the E11068 repair (ConcatenationInterpolation); hold one, do not re-derive the operand rules (was
StringConcatRewriter.renderChain).A
+ chain rendered as a backtick String, or the first operand that cannot be one: set
rendered with the operand counts, or conflictKind/reason naming the refusal.THE E11068 repair - a String built from three or more
+ parts - for every editing tool.The rewritten text and one note per rewrite;
notes empty means nothing moved.THE record of what a generic's body USES of its conceptual
T, and the reading of it.How the generic's body asks a type built on its type parameters to order, which decides the verdict where the
parameters are replaced: exactly the one the same type gets when it is written directly (phase 5's
RetractedComparatorUseOrError).One step towards a
<=> on a bare type parameter, recorded on that parameter (D89, D91 step 4): the body of
a method or function orders the parameter's values itself (into null - a <=> on them, or a value
given to a function delegate), or hands them on to another body that may (into, whose own parameter
intoParameter they become - the generic's own method, the same parameter; a generic function, the type
parameter they are bound to).One ordering the generic's body asks of a type built on its type parameters.
You may think why this mapping.
THE shared conceptual-to-concrete type replacement - use this, do not re-derive a variant.
Finds all concrete (non-abstract) subtypes of a given abstract aggregate type.
Recursively resolve a type reference to the leaf CONCRETE type symbols it actually couples to,
skipping conceptual
Ts.Sets
CONCURRENT_ENTRY_POINT = "TRUE" squirrelled data on function/method symbols
passed as the handler argument to stdlib thread-spawning calls
(TCP.accept, TCP.acceptUntilComplete, HTTP.serveUntilComplete, Signals.register) -
a plain call (CallOrError) or a method call on a receiver (ObjectAccessExpressionOrError: the usual
server.accept(handler) form, never marked before 2026-10-31).Propagates the
CONCURRENT_ENTRY_POINT = "TRUE" squirrelled marker transitively
along the call graph (Step 6b, slice 1).Record to group conditional evaluation instructions with the resulting condition name.
Result of condition and body generation: the condition case details
plus any post-loop instructions from stages like JOIN.
Record representing a single condition case within a CONTROL_FLOW_CHAIN.
Result of condition evaluation with primitive boolean extraction.
Result of evaluating a condition against abstract values.
THE prelude of a condition statement -
assert and require (OPS-7): the statement coverage probe,
the debug info that is ALWAYS created (the source location is essential for reporting a failure, not just for
debugging), the truncated expression text for the failure message, the condition evaluated into a managed
temporary (optionally bracketed by the coverage assert window) and its primitive Boolean.The evaluated condition of an assert or require statement.
THE confined-type fact (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, T12; Steve, 2026-10-31: "at compile time we can
check which types have no connection to long lived application based components, so they could never be long
lived").
Designed to encapsulate the fact that two token are in conflict for a Symbol.
Detects confusingly similar variable, parameter, and field names within the same scope.
Checks that either all parameters are named when making calls, or none are named at all.
Detects arithmetic expressions that always produce a constant result (E08083).
Detects coalescing expressions whose result is predetermined (E08094).
Detects comparisons where both operands are literals (E08082).
THE shared "read a module-level constant" step - use this, do not re-derive a variant.
The instructions reading a constant, and the variable now holding the fresh copy.
Creates the appropriate IR Construct for a constant declaration.
Checks constant organization within a multi-file module and emits errors if constants are scattered.
Generates a per-module
_Constants JVM class from constant IRConstructs.A very simple type that holds a single distinct value.
Represents a variable known to hold a specific constant value.
THE recovery of the base type a CONSTRAINED type narrows — call this, do not re-derive it.
THE construction bodies of a constrained type (DFN-3): the constructor that takes a value (a copy of a base or
constrained value, or a conversion), the fallible factory
of, and ? - each deciding whether the
value it holds is usable for the constraint (_viable).A constrained-type construction whose argument value is KNOWN at compile time and provably violates
the constraint is an error (E08260), not a runtime Panic.
THE shared resolver for a constrained-type construction site — a constructor call whose constructed
type is a
CLASS_CONSTRAINED aggregate carrying a constraint, together with its single
base-type argument symbol.THE delegation bodies of a constrained type (DFN-3): every method and operator cloned from the base forwards to
the base value held in
_delegate, re-wrapping a base result as the constrained type, and a mutation
re-validates the delegate afterwards; #^ (and _base()) hand back a COPY of the delegate.The base enumeration of a CONSTRAINED enumeration (
RedSuit as CardSuit constrain as ...); empty for a base
enumeration and for anything not enumeration-based.THE members of a constrained enumeration (
RedSuit as CardSuit constrain as "Hearts" or "Diamonds"):
the base enum's values, in declaration order, whose name satisfies the constraint - each with its BASE
ordinal.Creates the appropriate IR Construct for a constrained type declaration.
The instructions every part of a constrained type's generation shares (
ConstraintLowering,
ConstrainedConstruction, ConstrainedDelegation): the delegate and _viable field loads and
stores, the base value's copy, the _isSet of a base value and the call metadata of the base and
constrained constructors.THE description of the constrained type being generated, built once per type by
ConstrainedTypeDfnGenerator and read by its three parts (ConstraintLowering,
ConstrainedConstruction, ConstrainedDelegation) - never mutable per-type state on a generator.THE place a constrained type (
Age as Integer constrain as ..., or a plain alias Coord as Point)
gets its base's constructors, methods and operators cloned onto it - in TYPE_HIERARCHY_CHECKS.A serializable model of a constrained-type constraint, captured in phase 3 and stored on the
constrained
AggregateSymbol so later phases (and module-cache reloads) can evaluate it
without the original parse tree.A boolean combination of two constraints.
A leaf: the implicit subject value compared against a literal via
operator
(default ==; != normalised to <>, matching phase 3 / IR lowering).THE rendering of a constraint back to its EK9 source form —
>= 16 and <= 100.THE shared reading of a constraint's literals as
magnitude + suffix — use this, do not
re-derive it.THE lowering of a constrained type's
constrain as expression (DFN-3): the Panicking check a value handed
in must pass (ConstraintLowering.emitConstraintCheck(List, String, String, DebugInfo)), its non-throwing twin that records viability
(ConstraintLowering.emitViabilityCheck(List, String, String, DebugInfo)), and the walk of the constraint's parse tree to a Boolean (ConstraintLowering.walkConstraint(EK9Parser.ConstrainTypeContext, String, List, String, DebugInfo)).Decides whether a
constrain as expression can be satisfied by ANY value of its base type —
a declaration-site check, needing nothing but the constraint and the base.Immutable constraint state mapping variables to their abstract values.
Finds values a constrained type can actually hold, by PROBING the constraint rather than reading it —
the recovery path for when every value we knew how to guess turned out to be inadmissible.
THE shared fold of a
constrain as expression into the inclusive numeric window
[lo,hi] it narrows to — call this, do not re-derive it.THE display name of a construct - the name a person reads for it at RUN TIME (F2, Steve 2026-10-08, Contract 21 in
EK9_BACKEND_IR_CONTRACTS.md).THE way a construct's field declarations are made - hold one and use it, never build a
FieldCreator and a
FieldsFromCapture by hand again: ConstructFieldDeclarations.addPropertiesAndCapturesTo(IRConstruct, IRGenerationContext, AggregateSymbol) for an aggregate (its properties, then
its captures) and ConstructFieldDeclarations.addCapturesTo(IRConstruct, IRGenerationContext, ICanCaptureVariables) for a function (captures only).The calls that ALWAYS run when a callable runs, collected for FE77's construction-recursion check (E08263) by
the phase-5 call-graph collector, in the same walk that builds the call graph.
A call to a resolved function, method, operator or constructor.
A constructor running its type's property initialisers (
_i_init).One always-run call.
What an always-run call reaches.
T() inside a generic - a construction of whatever type each parameterisation substitutes for
T.FE77: construction that can never complete (E08263).
THE steps a constructor of an aggregate takes before its own body - use this wherever those steps are generated
or modelled, so the generated code and the phase-5 call graph cannot disagree about what construction runs.
ONE file mapping every generated construct to a hash of the IR it was generated from.
THE human-readable label of the construct a symbol represents ("service operation", "operator", "method",
"function", "callable"), for the size diagnostics that judge it against its
StatementBudgetOf
(AcceptableStatementCountOrError, AcceptableCombinedComplexitySizeOrError).THE resolver of phase-5 quality metrics for one operation, for every IR generator that registers a
function entry with
CoverageProbePlacer.The per-construct obligation rollup accumulated during the phase-5 walk of one callable body, then
squirrelled as
OBLIGATIONS_TOTAL/DISCHARGED/UNDISCHARGED at construct exit
(docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §2.1/§2.4).Checks that a specific constructor can be called on a particular type of Aggregate.
THE constructor call: every source call that constructs an object is lowered here, and nowhere else.
Walk 0 of PRE_IR_CHECKS — the "all-constructors initialise the field" pre-pass.
THE properties a constructor of
aggregate is responsible for: for a dynamic class its captures first (they
live in the capture scope, not the class's own symbol table), then its DeclaredProperties.Extracts collection/container state information from constructor calls and literal expressions.
Inside a constructor body, 'this' must not be passed as an argument to any NON-PURE call.
Where generated bytecode goes, and where it is read back from.
THE marker of what a construct's pre-flow and control expression prove safe for Optional / Result / Iterator
access (E08030) - one class for
if, switch, try, while, for and the ternary
(it was six near-identical subclasses).THE maker of the E08030 construct markers (
ConstructSafeAccessMarker), one per construct that can prove an
Optional / Result / Iterator access safe: ConstructSafeAccessMarkers.forIfBlock(), ConstructSafeAccessMarkers.forSwitch(), ConstructSafeAccessMarkers.forTry(),
ConstructSafeAccessMarkers.forWhile(), ConstructSafeAccessMarkers.forFor() and ConstructSafeAccessMarkers.forTernary().THE shared construct-scope layer for phase 2: it pushes the scope recorded against each construct in
enter* and pops it in exit*, so push and pop can never drift apart.Resolves the single nominal super type a construct extends, so backends can read it mechanically
from the IR (
IRConstruct.getSuperType()) rather than each re-deriving it from the symbol.A given construct from a specific source should be output to the targetFile.
THE single enumeration of the type references a construct makes through its signature —
super (
extends), traits (implements), field types (composes), method /
function parameter and return types (references), and closed-over captured-variable types
(captures).One signature-level type reference: the relationship
kind and the (raw) referenced type.The result of running the Symbolic/Contract engine (
SymbolicEngine) over one construct
(docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §3/§4.4/§6).A concrete input that violates an obligation — the witness a developer can paste into a test.
A branch proven dead (unreachable for every input) by a contradiction in its path condition.
An obligation the engine proved cannot fail within the bounded model — the green
✓ entry.THE look-ahead of the safe-access proofs (E08030): may anything in a region of source - read AHEAD of the walk -
change the object a proven Optional / Result / Iterator refers to (
ProvenContainerChange)? Use this for
any proof that must judge code it has not walked yet; never a private scan.Collects
CONTAINER_UNWRAP obligations from an object-access chain for the census — one per
Optional.get / Result.ok/error / Iterator.next call, discharged by
GUARD when the access is safe.Does a rule's token range contain the cursor (line, col)? Both 1-based, the end inclusive.
THE content hash of the classes under some packages as a class loader would serve them: where a class is on
several roots, the first root (the one the loader resolves) counts.
Checks for the containing construct type and whether it is marked as abstract or not.
Main dispatcher for CONTROL_FLOW_CHAIN bytecode generation.
Record containing all information needed to create a CONTROL_FLOW_CHAIN instruction.
Unified IR generator for EK9 control flow operators using CONTROL_FLOW_CHAIN.
Unified IR instruction for all EK9 control flow constructs.
Checks that an expression used as a control (if/else if, while, do/while, a ternary) is a condition: a Boolean,
or a type that promotes to one with '#^'.
EK9 switch/try control type symbol - this can effectively return a value if it is configured
with returning part.
THE copy constructor of a type: a PUBLIC constructor taking exactly one argument of EXACTLY that type -
Step(Step).Generates synthetic IR for the _copy (:=:) operator.
THE "can a copy into this owner meet an object of a different class?" - only when the owner may have sub-types.
Is the aggregate of a genus that can own a copy: the extensible data-carrying aggregates (a trait is an interface,
and has no fields to copy).
Compiler self-verification directive (NOT an end-user feature) asserting that the Layer-2 symbolic
engine found a specific witnessing input for a construct
(docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §4).
Checks any
@Counterexample directives in the parsed module against the squirrelled Layer-2
witnesses (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §4).Tracks efferent coupling (Ce) - the number of external types a construct depends on.
Used for checking covariance based on a variable.
Emits the covariant-return bridges an operation's IR asks for (
OperationInstr.getBridgeReturnTypes(),
front-end rationalisation N07).THE recording, in the IR, of an override's narrower (covariant) return - front-end rationalisation N07,
Steve 2026-10-02: "this needs to be made clear at the IR generation level".
Resolves the user-facing display name for a function/method symbol used in
coverage and quality reports.
Specialized ASM generator for CoverageFinalizeInstr processing.
Specialized IR instruction for coverage finalization (COVERAGE_FINALIZE).
Represents coverage information for a single function/method.
THE join key for a construct - the display name (
CoverageDisplayName) minus its one cosmetic exception.THE serialisation of a source file's coverage metadata (IR tidy W3.9, INFRA-10) - the probes and functions a
CoverageProbePlacer registered, its module-level injection counts and file readability scores - as the JSON
the runtime computes coverage from.Coverage tracking modes that control how probe hits are recorded.
Represents complete coverage metadata for a compiled module.
THE coverage name of a function/method symbol, before the display-only transform - the one resolution both
CoverageDisplayName (bareConstructor true) and CoverageIdentity (bareConstructor
false) give; the class javadoc of CoverageDisplayName has the four cases.Specialized ASM generator for CoverageProbeInstr processing.
Represents details about a single coverage probe placed in the IR.
THE identities of coverage and profiling instrumentation (IR tidy W3.9, INFRA-10): a module, a function and a
probe each get a deterministic FNV-1a 64-bit hash of their source context, so ids are unique across every source
file without any coordination during parallel compilation, and two parameterisations of one generic produce the
SAME ids for the same source lines (which is what lets
CoverageProbePlacer.absorb(CoverageProbePlacer) de-duplicate by id).Specialized IR instruction for coverage probe recording (COVERAGE_PROBE).
Places coverage probes at control flow points during IR generation.
Enumeration of coverage probe types placed at control flow points.
Emits the profiling exit handler that wraps profiled method bodies.
Specialized IR instruction for coverage module registration (COVERAGE_REGISTER).
The source-level names a coverage name is made from (see
CoverageDisplayName): a callable's own name, and
an aggregate's name.THE fully-qualified name to use as a coverage/profiling IDENTITY for a callable - stable across every
parameterisation of a generic.
THE registry of "dangerous values" per obligation kind for the Symbolic/Contract engine — the single
place that answers which concrete base-domain values would violate this obligation.
THE emission of a diagnostic raised by a whole-program analysis, which finds its error listener by LOOKING UP the
source its token belongs to (call-graph detectors, the deadlock check, construction recursion, injection
reachability).
A synthetic call-graph edge representing thread-boundary-crossing dispatch
— passing a function as the handler argument to
TCP.accept,
Signals.register, or as a stage in cat ... | async.THE per-type owner constant of the property-cycle guard (Contract 13 in
EK9_BACKEND_IR_CONTRACTS.md) -
hold one and use it, never a String literal built per call.Validates that a module does not contain data clumps (E11053).
Tracks function/method/constructor parameter signatures for data clump detection (E11053).
An immutable (type, name) pair from a parameter, ordered for deterministic comparison.
One callable's parameter signature for data clump analysis.
Walk 3 of phase 5: dedicated AST walk for the data-race check (slice 1, step 7).
To be used in EK9 source code to assert the DATA-TOUCH verdict for a tracked parameter of the
callable on the next line — does this callable, or anything it calls, mutate the structure, and
does a reference to it escape? (design
docs/tooling/EK9_DATA_TOUCH_ANALYSIS_SPEC.md
§8.5).THE reading of a Date literal (
2024-01-15); throws DateTimeParseException.THE reading of a DateTime literal (
2024-01-15T10:30:00Z); throws
DateTimeParseException.Full rationale for a single detected deadlock — either
E08252 (nested enter
on different lock identity) or E08253 (cross-thread same lock).Which slice of the generated debug information a
@DEBUG directive asserts against.To be used in EK9 source code to assert that ONE slice of the generated debug information for a
construct matches expectations.
Validates
@DEBUG directives: asserts that ONE slice of the generated debug information for
a construct (a DebugAspect) matches the expected golden.Debug information for IR instructions to enable source mapping and debugging.
Creates the debug information for the symbol provided.
Generates debug information for JVM bytecode.
A variable declaration's instructions as its two halves, known where they are generated: the DECLARATION (the
variable's slot, and any declaration that must outlive the evaluation with it) and the INITIALISATION (everything
else - the value production).
The close operator this type declares itself, if any: own scope, not abstract, not a delegation proxy.
THE direct dependencies a
defines package block declares, in the order written: every entry of its
deps and devDeps Dicts whose key and version are both String literals (a malformed Dict is
PackageProperties' E06260, not this class's business).One declared dependency: the Dict it is in, its module name, its version and the token of its entry.
THE operator of one name a type declares in its OWN scope, preferring the overload that takes the type itself when
there are several (
ExactSingleParameter) - and otherwise ANY overload (a zero-argument $ or
? has no parameter to match).The nearest concrete
<=> above the type that compares its level with itself, read from the methods as
DECLARED - a retracted one included (getAllNonAbstractMethodsInThisScopeOnly does not filter the
retraction), so OrderingAvailability.orderingSurvives(MethodSymbol, ISymbol) gives the same answer whichever types phase 5 has
already visited.The concrete
<=> this one LEVEL declares comparing itself with itself, read as DECLARED (a retracted one
included), preferring the one taking exactly the level.THE properties a type DECLARES itself, the property half of the fields an object of it carries (the other half,
for a dynamic class, is
CapturedVariables).The type a callable declares it returns, if it returns one - what
NarrowedReturnTypes and
NarrowedFunctionReturnTypes compare.THE sameness a type itself declares (B18) - its own non-abstract
<=> comparing it with itself, else its
== - hand-written or defaulted, never one GENERATED from it (IsGeneratedFromSameness).The exit code a test DECLARED with
"EXIT:<n>", or null when it declared none (IsTestProgram has
the encoding contract).Does the callee (or, for a member of a parameterised type, the generic's own member) declare a rule matching
wanted - or the unknown opt-out, under which nothing may be assumed.True when this declaration is an operation's returning variable (
<- rtn as T: v or <- rtn as T?
of a function, method or operator), owned by the caller - not the returning variable of a switch/while/for/try
expression.THE inverse of
CallableIdentity: the declaring construct of a call-graph identity.THE decoding of the escape sequences in an EK9 String literal's text (quotes already stripped):
\t,
\n, A, \101, etc.Useful function that generates the decorated/internal name for generic types that have been
parameterized.
Given a symbol, this check that the type that the symbol has can support the '--' operator.
Record containing default case management information for CONTROL_FLOW_CHAIN constructs.
PRE_IR_CHECKS confirm-or-retract for the BARE
default operator comparison family.The generated copy of a closeable holder is refused (R-A, Steve 2026-10-06, decision D9; E81065).
THE test that an operator was written as
default operator X (or added by the bare default operator):
the DEFAULTED squirrel, so the compiler wrote its body.THE decision of which operator a GENERATED comparison is answered by - hold one and use it, do not re-derive it.
THE test of whether a type already has what a
default operator would give it - hold one and apply it, do
not re-derive it.E01086 - a bare
default operator with something after it in the body.Checks that operators that have been 'defaulted' could actually be implemented.
A
defines <block> line (class, function, program, ...) at any indent but two.THE type that DECLARES a resolved method (its enclosing scope) - i.e.
Does
callee say, by an EXPLICIT rule - declared by a built-in or derived for a user callable - that it
keeps the argument it is given at parameterIndex somewhere other than its result? The narrower question
than KeepsArgumentBeyondResult, which also counts the inexpressible unknown opt-out: an unnamed
closeable given to a callee that DEFINITELY keeps it is E81072; one given to a callee that may is handed on.Does
callee say, by an EXPLICIT rule - declared by a built-in (readyHandler <- receiver) or derived
for a user method - that it keeps the object it is called ON beyond the call: stores it in an argument or where
nothing here can name it? The receiver's half of DefinitelyKeepsArgument: an unnamed closeable that is the
RECEIVER of such a call is E81072 (D80 follow-up, 2026-10-21: Tracked("r").registerIn(kept), whose body is
items += this, closed the receiver and then the list held a closed object).Just go through and define the symbols and scopes putting into the ParsedModule against the appropriate context.
THE chokepoint pass that makes a zero-length JVM exception-table entry impossible to emit: copy the class bytes
verbatim (frames/maxs preserved — no recomputation, so no class loading is needed) except that every method is
filtered through
SafeExceptionTableMethodVisitor, dropping any exception-table entry whose start and end
labels resolve to the same offset.After a this(...) call, the properties the delegated-to constructor sets have a value for the rest of the
delegating constructor - and only those.
To be used when checking if a variable Symbol is a function delegate and can accept a set of call arguments.
THE load of a wrapper's
delegate field, borrowed for the scope - shared by the constrained types
(ConstrainedTypeInstrs) and the Scenario-2 wrappers (Scenario2WrapperHelper), which each had a
byte-identical private copy (DFN-3, MONO-8).True when the constructor delegates to a sibling with
this(...) (recorded in phase 3,
ThisOrSuperCallOrError).A Lexer, but one that delegates to the actual lexer that in plugged in.
Generates synthetic IR for trait delegation methods.
THE index of the first stage that ends a pipeline's demand segment, or -1 when every stage streams
(
StreamDemand, decision 10 rule B).THE text of a denied bare-name reference (
CaptureEvaluationScope.deniesAccessTo(ParseTree, ISymbol)), the same at every site:
what was named and where it is declared - reference to 'name' on line: N:.THE place a dependency lives in a library folder: unpacked as the directory
<lib>/<name>-<version>, or
zipped as <lib>/<name>-<version>.zip (the zip's name is FileHandling's).Reports (E06263) each DIRECT dependency of a
defines package block that is not installed in the library
folder, on that dependency's own line in its deps or devDeps Dict - so the IDE, MCP, LSP and
ek9 -c tell the same truth, where only the CLI's resolver used to (exit 17).Generates synthetic IR for every comparison operator a type's <=> answers: <,
<=, >, >= - and == and <> whenever the type has its own
<=> (Steve, 2026-09-29: a defaulted comparison can never disagree with the type's ordering, so
a == b exactly when (a <=> b) == 0).THE parse-tree DESCENDANT collector for the compiler - use this, do not hand-write a recursive
for (i < getChildCount()) collector.De-Serializes a byte array back to compilable program.
THE gate for a test construct (
assert, assertThrows, assertDoesNotThrow,
assertPanic, @Test) that may only appear in a dev source: reports
TEST_CONSTRUCT_IN_NON_DEV_SOURCE with the construct's name.Reports DI/AOP analysis to stderr when the
-di flag is set.Generates JVM bytecode for DICT_LITERAL IR instructions.
Details for the DICT_LITERAL IR instruction.
A single key-value pair in a dict literal.
Generates IR instructions for dict literal expressions.
IR instruction for dict literal construction with pre-sized allocation.
Creates/Updates an ek9 Dict (Dictionary/Map) of a specific types if the expressions are typed correctly.
Wraps the SHA 256 digest and the resulting byte array into objects,
so we can deal with check objects rather than raw bytes.
A Checksum.
Loads DI analysis guidance messages from individual .txt resource files listed in a manifest.
CONCERN: Direction check evaluation for polymorphic for-range loops.
Parameters for direction check evaluation.
Configuration for for-range loop direction (ascending vs descending).
Provides basic interface for the EK9 internal @ type directives.
Main() @Test - an annotation written after the declaration it marks, Java-and-Kotlin style.THE shared recovery of a symbol's generated
.class bytes for the back-end directive
listeners (@BYTECODE, @DEBUG).Just focuses on creating directives, these are used when testing EK9 source code.
Provides the listeners for directive checks.
THE one-line text of a directive mismatch (Steve, 2026-10-11, lane lang-syntax): which directive, its line, and
what the compiler actually found -
line 6: @Error: FULL_RESOLUTION: NOT_RESOLVED - the compiler found no
error on line 7 [E50230].Extracts the compilation phase or throws an illegal argument exception.
Finds the next line number from where a directive has been used.
Specification of a directive, all the common details used in a range of directives.
Extracts the 'spec' from the free format data in the directive.
Extracts the symbol category or throws an illegal argument exception.
Extracts the symbol name or throws an illegal argument exception.
To be used in EK9 source code, for things like internal tests
or compiler directives, instrumentation, reified type retention etc.
THE shared sink for directive-test
@IR/@IR_PARAMETERISED/@LLVM/@BYTECODE
UPDATE blocks emitted by the directive listeners when a golden mismatches.Detects discarded return values in bare statement calls (E11050, E11051, E11052, E11055).
Why an obligation is considered discharged (proven safe) by an existing analysis, or
DischargeReason.UNDISCHARGED when no analysis proves it — the discharge-detection order of
docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §2.3.THE dispatcher half of "what may a call through this declaration run" (the closeable route-matrix verifier,
2026-10-22): a call to a dispatcher entry point runs, at run time, the handler most specific to its argument's
type - so the entry returns and keeps whatever any of its handlers does.
Validates that no reachable type in a dispatcher's hierarchy resolves ambiguously
between two or more handlers at equal cost.
Validates that dispatchers on sealed traits have handlers for all permitted types.
A trait may not supply a dispatcher handler (E07825, front-end rationalisation D21, Steve 2026-10-20): a dispatcher
and every one of its handlers live in one class hierarchy.
Links a dispatcher entry point to the handlers its dispatch table can route to, so a call that
resolves to the entry point reaches the handler that actually runs.
Reports a dispatcher handler whose parameter type has no concrete form anywhere in the program,
so no value can ever have that runtime type and the handler is dead code that looks live.
THE single source of truth for the handler set of a dispatcher entry point - hold one and ask it.
THE single source of truth for "what types can actually arrive at this dispatcher parameter" - hold one and ask it.
Validates that dispatcher handler parameter types are reachable from the base dispatch type's
hierarchy.
THE single source of truth for "which handler WINS for this concrete type" - hold one and ask it.
A winning handler and the assignment cost it won at.
THE dispatch facts of a CALL - the four
CallDetails fields that say WHERE the call goes and HOW it gets
there: the type it names (targetTypeName), whether that type is an interface (isTraitCall),
whether the call dispatches through the vtable (isVirtualCall) and whether the named type is externally linked
(isExternTarget - EXTERN or PRE_BUILT, see IsExternallyLinked; Steve 2026-10-28).Specialized ASM generator for DISPATCH_TABLE instruction.
Details for the DISPATCH_TABLE IR instruction.
A single entry in the dispatch table mapping concrete type(s) to a handler method.
Generates precomputed dispatch tables for dispatcher methods during Phase 7 IR generation.
High-level IR instruction for a precomputed dispatch table.
THE shared "Pass 3" that prepends a DISPATCH_TABLE to every dispatcher operation of an aggregate.
ConstructDisplayName with a dynamic construct among the type arguments left as its mangled name, so two
parameterisations over two different dynamic classes never share it (both are Box of cls in
ConstructDisplayName).Extracts doc comment text from HIDDEN channel tokens.
THE value of an EK9 Float literal's text as a
double - EK9 Float is 64-bit.E08274 (Steve, 2026-10-08, C1, Q8, Q9): a negation is never applied to a negation -
not not b,
~~b, - -x, not ~b, - ~x, ~ -x and the same PARENTHESISED,
not (not b), ~(~b), -(-x), -(not b), are compile errors.THE E07901 repair - a double-quoted String holding
${ - for every editing tool.The rewritten text and one note per rewrite;
notes empty means nothing moved.A double-quoted String holding
${ is an error (E07901): a double-quoted String is never
interpolated, so "${count} items" prints those characters rather than the count.Specialized generator for EK9 do-while loops.
The evaluated
hasNext() condition of a drain loop: its own scope, the instructions that
compute it, the variable the helper's hasNext() call wrote and the primitive-boolean variable
the loop branches on.Detects when a second 'defines package' block appears in a module
and emits a dedicated error rather than a generic duplicate symbol message.
Every declaration in this package block that sets a property an earlier one already set - reported (E50050)
as
DuplicatePackagePropertyMessage, at the later declaration's name.The message for a package property set twice (
DuplicatePackageProperties), after
In '<module>' package: .Resolves the variables to be captured and defines new variable symbols against the appropriate scopes.
D62 (Steve's rule, D55/D58): the retraction of a bare
default operator's ordering family reaches the dynamic
classes too.Checks that a dynamic class does not used naming when used inside a generic type/function.
Creates the appropriate IR Construct for a dynamic class declaration (anonymous inline class).
The dynamic-class half of
SuperConstructorAccessOrError (D98, fuzz6 2026-11-09).THE emission of a dynamic class or dynamic function where it is written (INFRA-2): generate its construct in a
fresh
IRContext (counter isolation), add the construct to the IR module, evaluate the captured
expressions, then construct it with those captured values.THE monomorphisation of a dynamic function or dynamic class declared inside a generic body - hold one at every site
that generates or constructs one, never a variant.
Checks if a dynamic function body is needed and provided, and that a body whose super returns a value can
actually return it (not every path throws - E07380, as for a named function; front-end audit FE65).
Creates the appropriate IR Construct for a dynamic function (anonymous closure).
Deals with handling any returning values in a dynamic function.
Dynamic Variables when captured have to either be identifiers in their own right,
but if they are some type of expression, method call, etc.
Classifies a call-graph edge by its threading semantics, per
EK9_CONCURRENCY_MODEL.md §5.2.THE edit distance behind the compiler's "did you mean" hints for a misspelt WORD - a keyword
(
repair/ParseSuggestions) or a package property name (PackageProperties): optimal string alignment,
where an insertion, a removal, a change and a transposition of adjacent characters (esle,
verison) each count one; case-sensitive.This class provides an empty implementation of
EK9Listener,
which can be extended to create a listener which only needs to handle a subset
of the available methods.This class provides an empty implementation of
EK9Visitor,
which can be extended to create a visitor which only needs to handle a subset
of the available methods.Looks for Java classes that have been annotated with the annotations that allow them to be exposed
as 'extern' ek9 components.
Custom ClassWriter that doesn't require loading classes during frame computation.
The main EK9 compiler (HERE FOR COMPILER ENTRY).
THE set of EK9 core modules - the modules only the compiler bootstrap may define.
Responsibility of dealing with aspects of the ek9 directory structure.
Custom error strategy for EK9 that produces human-readable error messages.
THE single builder of an EK9 executable "fat" jar from a compiled project — extracted so the CLI
(
Ec.repackageTargetArtefact) and the IDE (PipelineRunner.buildForDebug) share ONE
packaging path and cannot drift (they had a private copy in the CLI only, which is why the IDE's
debug build produced no jar).Defines all exit codes used by the EK9 compiler and generated code.
THE marker line EK9 writes FIRST on stderr when EK9 ITSELF fails - the CLI, the compiler, or
the generated
ek9.Main entry point rejecting a program's arguments - e.g.The code a line names when it is EXACTLY an
Ek9FailureMarker (surrounding whitespace aside), else empty.THE source for EK9's word keywords (
Ek9Keywords.WORD_KEYWORDS); whether a keyword can still be used as a NAME is
IsReservedWord.Loads the language basics into a Compilable Program.
Original good for python but too pythonesque for EK9 -
needed reworking to remove # comment and tabs for indenting.
Just wraps up the creation of the EK9Lexer from an inputStream.
This interface defines a complete listener for a parse tree produced by
EK9Parser.THE single source of truth for EK9 literal types — the finite, closed set of
built-in types a literal can denote.
THE closed taxonomy of EK9 compiler-generated method kinds carried by the
Ek9MethodKinds
class attribute (C.2), each with its debugger MethodDebugPolicy bitset.The versioned
Ek9MethodKinds class attribute (C.2): a per-method map of
(name, descriptor) -> Ek9MethodKind + MethodDebugPolicy bitset, letting the EK9
debug semantics layer decide step-filtering and frame re-presentation.One per-method record: the method (name, descriptor), the
Ek9MethodKind wire
kindCode, and its MethodDebugPolicy bitset.Orchestrates the EK9 source code formatting pipeline.
A cut down visitor that just deals with packages at a basic level.
Models a token that we need to create as a synthetic token.
Fixed and Known EK9 types that the compiler needs to know exist.
Used to cache built in types as they are so frequently used.
This interface defines a complete generic visitor for a parse tree produced
by
EK9Parser.Specialized generator for EK9 Elvis coalescing operator (:?).
THE embedded form of a program's licence files, for a native executable's data: per file a NUL,
ProgramLicences.EMBEDDED_MARK, its name, a newline, its text and a NUL - found again by scanning
(ProgramLicenceReader).THE one emitter of "a construct (or a reference) conflicts with a reference" errors.
What the conflicting construct is, as it is worded in the error message ("defines function, but ...").
Error when a reference is made, but it cannot be resolved.
To be called when an unreachable statement is encountered to emit an error.
Detects when a 'defines' block (class, function, trait, etc.) is empty
and emits a clear semantic error rather than letting it fail as a generic parse error.
Detects @Test programs that have no validation - neither assertions nor expected output files.
The constructor declaration this node is directly in, or null when it is in some other method, a function, or
code that runs later (a dynamic function's body, a dynamic class's method).
THE "which method or operator is this node directly in?" - the declaration whose code runs when this node runs.
THE "is this node inside a property's initialiser, and which one?" - the
PropertyInitialiser a node is in.True for a stage that is lowered as a drain (or emits only after its loop): a
head downstream of it
cannot bound what flows into it, so the demand segment ends there.True when the final step of the object-access chain (
ObjectAccessFinalStep) is a method/operation call
rather than a plain field identifier - e.g.A single
MutexLock.enter(...) or MutexLock.tryEnter(...) call site
observed during analysis.Distinguishes the two variants of MutexLock acquisition: blocking
enter() vs non-blocking tryEnter().Generates synthetic IR for enum constructors (copy and String).
Creates/Updates an enumerated type adding methods as appropriate.
Creates the appropriate IR Construct for an enumeration declaration.
Generates synthetic IR for the enum #< (first) and #> (last) operators.
Generates synthetic IR for the enum ++ (_inc) and -- (_dec) operators.
Generates the anonymous iterator class for enum iteration.
Generates synthetic IR for the enum iterator() method.
Specialized ASM generator for ENUM_ITERATOR_IMPL instruction.
Details for the ENUM_ITERATOR_IMPL IR instruction.
High-level IR instruction for generating enum iterator implementation.
THE generator for the enumeration operators that are "primitive field in, at most one call, out"
(_eq, _cmp, _isSet, _string/_promote, _hashcode and _json); each operator is one row, a
EnumPrimitiveOperatorGenerator.Shape.The one call made on the converted receiver(s); a null call means the converted field IS the result.
Which "is set" guards run before the body.
One row of the table: the operator, its return type, the guard, the primitive field loaded from each
receiver, how that primitive converts to an EK9 type, and the optional call on the converted value.
Generates synthetic IR for enum operators that accept a String parameter.
Generates synthetic IR for the _eq (==) operator.
Emits the JVM
equals(Object) / hashCode() methods for generated user aggregates that
declare value semantics, bridging them to the EK9 == (_eq) and #?
(_hashcode) operators via org.ek9.lang.HashSupport.Derives a type's
TypeVariety — its value-class count + confidence — for the
input-variation denominator (design §11.1).The one-line meaning of a semantic error code, from the compiler's own classification - the caption of an error
example (
ErrorDirectiveText).THE error code of a diagnostic as a consumer shows it: the code of its semantic classification (
"E08020"),
or "" when it has none (a parser error).To be used in EK9 source code to assert that an error will be created.
The classification an
@Error directive names (ErrorDirectiveText).The error codes the source's
@Error directives name, in source order, without repeats
(ErrorDirectiveText).Checks if there are any directives that relate to errors in the parsed module and tallies those up
with any errors held for the phase of compilation.
The phase names the source's
@Error directives give, in source order, without repeats
(ErrorDirectiveText).THE text-level reading of the
@Error: PHASE: CLASSIFICATION directive lines in an example SOURCE - for the
readers that show an error example to a person or a model, not for the compiler (which parses directives with the
grammar and checks them with ErrorDirectiveListener).THE loader of the error catalogue's examples (
errorExamples/<CODE>/, site-examples spec §6, decisions D2
and D11): for each error code a bad.ek9 that fails with exactly that code (its @Error directive is
kept in the source, where the gate reads it) and one or more good*.ek9 that fix it.One source of the catalogue.
One example of a code: a single file (
bad.ek9, good_open.ek9) or a directory (bad/,
good/) whose files compile together as one workspace.We need an error listener for the lexing parsing and also our own tree
visiting.
Fine detail of the error.
The type of the error.
The details of an error, position, etc.
What is the semantic nature of the error.
Escape analysis metadata for IR optimisation phase.
Escape level classification.
Lifetime scope classification.
Record containing evaluation variable management information for CONTROL_FLOW_CHAIN constructs.
THE test "this method or constructor takes exactly these parameter types, in this order" - each by
isExactSameType, never by assignability, promotion or a cost-based match.THE test "this method or operator takes exactly ONE parameter, and its type is EXACTLY this type" - by
isExactSameType, never by assignability.Just wraps any exceptions in a runtime CompilerException.
Just catches exceptions and ignores them.
THE rule that an Exception, or any sub-type of one, has no
operator close (E81074, Steve 2026-10-26,
decision (b) of the closeables lane): an exception is a VALUE carried to a handler, not a resource.Checks that the symbol passed has a type and that the type is compatible with an EK9 Exception.
Detects call chains deeper than one level (E11069).
Checks for excessive type traversal in method chains (Law of Demeter).
Single source of truth for directory names that should be excluded from
workspace file walks, watch registrations, and glob-based source discovery.
THE glob exclude patterns of
ExcludedDirectories.NAMES, suitable for use with
Glob(List, List).Detects excluded keywords and emits clear educational error messages.
Represents a variable known to hold any value except a specific constant.
THE file name of a program on this platform:
ek9.exe, clang.exe, java.exe on Windows,
the bare name elsewhere - for every search of PATH or a folder for a program by name (Windows looks for an
exact name there; only its own shells add .exe).THE flattening of the instructions a back end EXECUTES in an instruction list: every instruction, depth-first
through every nested list a back end runs - a chain's condition cases (
guardUpdates,
conditionEvaluation, bodyEvaluation), its default, try body and finally, and a for-range loop's
initialisation, continue condition, direction/condition/setup/guard/increment/progress lists and body (the walk
IRConstruct.allBodyInstructions() describes).THE executed instructions of one operation (one callable), flattened as
ExecutedInstructionsIn describes -
the per-callable unit an IR analysis reads.An exception that when caught at the very outer edge of the compiler will cause the application
to exit with a specific error code.
THE expansion of the E11031 document tokens:
text with NonDescriptiveNames.BANNED_NAMES_TOKEN
replaced by NonDescriptiveNames.PROSE and NonDescriptiveNames.ALTERNATIVES_TOKEN by
NonDescriptiveNames.ALTERNATIVES - for every loader of a document that publishes the list (rich error
messages, message packs, Q&A answers, the CLI/AI help, the site).Where each directive says its error is, as
"<line>:<CLASSIFICATION>" - the line after the directive,
counting from 1 - in source order (ErrorDirectiveText).THE check for whether a
@Test program carries expected-output companion files — the
validation mechanism EK9 accepts INSTEAD of assertions.The exit code a test program must end with for the test to pass: the one it declared with
"EXIT:<n>" (DeclaredTestExitCodeOf), else 0.THE smallest
EK9Parser.ExpressionContext whose token range CONTAINS the cursor (line, col), 1-based - "what
expression is the cursor inside" without an explicit selection (was
StringExpressionClassifier.findExpressionAtCursor; ExpressionSpanningSelection is the exact-range
form).Tracks complexity of coalescing expression trees with depth-based multiplier.
Checks that an expression is a condition - a Boolean, or a type that promotes to one with '#^'
(
IsCondition, THE rule for every condition) - emitting
ONLY_COMPATIBLE_WITH_BOOLEAN otherwise.Ensures that 'expression' is now resolved and 'typed' or a not resolved error.
This listener just deals with expressions and the types that result from expressions.
THE smallest
EK9Parser.ExpressionContext whose token range exactly matches a selection - its
TokenRangeOf is [startLine, startCol, endLine, endCol], all 1-based (was
StringExpressionClassifier.findSmallestEnclosingExpression).While we don't add these in the scoped structures when compiling.
Creates IR instructions for expressions.
Useful in expressions to contain the left and right hand symbols.
A simple record that can be used when processing expressions.
Test if a symbol is externally implemented.
The native footprint of a field-bearing extern base (
Exception, Money, ...), or empty for a user
type or a field-less extern type.Facade that combines ANTLR parsing with the ExternSourceVisitor to generate
extern representations of EK9 source files.
Visitor that walks an EK9 parse tree and emits an extern source representation.
THE test for "is this symbol provided from OUTSIDE this workspace's EK9 source?" — a built-in, or any
member of an
extern construct.Extracts the literal an expression resolves to, or null if it is not a (possibly negated) literal.
Represents a field/property declaration in an EK9 construct (class, record, component, etc.).
Classifies fields in an aggregate as service-type (abstract/interface) or data-type (concrete).
Result of field classification for an aggregate.
Creates the appropriate Field object for the symbol and adds it to the construct.
THE rule of Q-COMPONENT-? (Steve, 2026-10-07): a type with NO fields, counting inherited ones, is set whenever it
is present.
Gives every class, component and service with no fields, counting inherited ones, its synthesised '?'
(
FieldlessIsSet, Q-COMPONENT-?, Steve 2026-10-07), after every source has been through
EXPLICIT_TYPE_SYMBOL_DEFINITION: supers are linked only then.Generates synthetic IR for the _fieldSetStatus() method.
Creates the synthetic
_fieldSetStatus method symbol used as an IR carrier.Accepts a ICanCaptureVariables (either a function or an aggregate).
THE field-slot rule: the index of a property in an object's flat field layout, as every back end lays it out and
as the IR's
LOAD_FIELD/STORE_FIELD/RELEASE_FIELD index states it (Contract 2: the index is
the slot).A field as
STORE_FIELD describes it - the object, the field's name, the type that owns it, the field's type
and its index (or OwnershipInstr.NO_FIELD_INDEX where STORE_FIELD looks it up by name).Writes each generated class to its own file - the behaviour every jvm writer had inline.
Designed to abstract out all file handling for the compiler.
File-level metrics including ARI readability.
Gate the flowing element on a predicate:
filter continues downstream when the predicate is
true, reject when it is false.The code named by the FIRST line of a stderr capture (after the JVM's launcher lines) when that line is an
Ek9FailureMarker, else empty.Generate a nested iterator loop for a flatten stage.
An EK9 Float literal's text read as a Java
float (underscore separators allowed, 1_000.5).Detects conditions that are always true or always false based on data flow analysis (E08086/E08087).
Maps compiler error codes to their corresponding path in forAI.json.
A foreign spelling (was
ForeignSyntax.trailingColon): a trailing : on a control line
(if x:, else:, while x:) - Python's block colon; EK9 blocks are opened by indentation alone.A foreign spelling (was
ForeignSyntax.blockComment): a C block comment (slash-star ...A foreign spelling (was
ForeignSyntax.genericType): List<String>() / as List<String> /
Dict<K, V> - EK9's List() of String / List of String / Dict of (K, V).A foreign spelling (was
ForeignSyntax.hashComment): a # note comment line - EK9's
// note.A foreign spelling (was
ForeignSyntax.logicalOperators): a && b / a || b - EK9's
a and b / a or b.Generates IR for for-in loops and expressions: for item in collection.
Deals with the for loop for phase 3, which is basically working out the type of the variable being iterated over
and ensuring that the expression is something that can be iterated over.
Result of a formatting operation.
The state of the formatter after processing.
Predicate to determine if an expression is a Boolean logical operator (and/or)
with Boolean type operands.
When looking to calculate complexity of methods/functions it is important to
work out if parts of an expression are in some way conditional.
Generates IR for for-range loops and expressions using FOR_RANGE_POLYMORPHIC instruction.
Pulls the type from the 'range' into the loop variable, so it is correctly typed or emits an error.
JVM bytecode generator for FOR_RANGE_POLYMORPHIC IR instruction.
Specialized IR instruction for EK9 polymorphic for-range loops.
Dispatch case for ascending loops (direction < 0).
An extra condition evaluated at the top of every iteration, before the range test:
evaluation is
run, then the loop ends unless primitive is true.Dispatch case for descending loops (direction > 0).
Container for all three dispatch cases in a for-range loop.
Whether the counter has REACHED the end:
primitive is read after the body, and the loop stops BEFORE the
increment when it is true.Dispatch case for equal loops (direction == 0).
Non-executable metadata about the loop structure.
The run-time PROGRESS check of a range whose counter type can wrap or not move (Time, and every user-defined
range type - decided at compile time by
RangeProgressCheck, never by a back end).Scope identifiers for different parts of the loop structure.
Whether this iteration's loop value is usable:
evaluation is run right after the loop variable is set up
and the body is skipped (the iteration still reaches its end check and increment) unless primitive is
true.Deals with checking the 'for' statement/expression.
Coordinates for-statement IR generation by delegating to specialized generators.
Checks the for structure via the code analysers.
EK9 'for' type symbol - we need a scope because we declare a new variable as the loop variable.
Test if a (generic base function) symbol is forward-target dispatched: the closed set of extern
abstract function types a built-in invokes through the erased base
_call(Any...) path with
the argument held RAW — MutexKey (via MutexLock.enter) and Comparator (via
PriorityQueue.withComparator/Ek9Sort).A Boolean LEFT operand for a short-circuit AND: a FRESH SSA temp (a head's
counter < limit, never a
load of an alloca-backed var) plus its primitive.Supplies just the front end of the compiler.
THE split of an example source into its
<?- ... -?> JSON front matter and its EK9 body - the one reader
of that format.THE EK9 source after an example's
FrontMatter, trimmed and without a trailing //EOF; the whole text
(likewise trimmed) when there is no front matter.THE JSON of an example source's
FrontMatter: the text between the markers, trimmed, or null when
the text has no well-formed front matter.Supplies all the phases for a full compilation from end to end.
Takes a fully qualified ek9 name and produces a name that is suitable for jvm use.
Takes a fully qualified ek9 name and produces a name that is suitable for llvm use.
Takes a fully qualified ek9 name and produces a name that is suitable for jvm internal use.
Takes a fully qualified ek9 name and produces a name that is suitable for llvm internal use.
Unified function call processor using CallDetailsBuilder for method resolution and promotion.
To be used when checking if a function can accept a set of call arguments.
Check is the data passed in enabled a delegate function to be resolved and if so return that Function.
Creates the appropriate IR Construct for a standalone function.
Links an abstract function to every concrete function that implements it, so whatever reaches the abstract one -
a call through a variable of its type, or a concurrent-entry-point mark on it - reaches the bodies that can run.
THE lowering of a function CONSTRUCTED as a value to its singleton instance - hold one and use it.
Generates synthetic IR for the function _isSet (?) operator.
Per-function summary of lock activity.
THE member symbols of a function construct (IR tidy W3.3, DFN-5/MONO-4): a function - named, dynamic or a
Scenario-3 parameterisation - is generated as a class with a constructor, a
_call method and a ?
operator, and these are the symbols of those three.Code quality metrics for a single function/method.
Checks that the function correctly overrides the signature if it has a super.
THE coverage and profiling probes of one function, method or operator - every IR generator that instruments a
callable registers it and places its probes through this; never a private copy of the choreography.
The probes of one registered function; each is null when its kind of instrumentation is off.
Emits the function-singleton pattern: every named EK9 function has exactly one instance.
The inter-procedural summary of a callable (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md
§3.4) — the facts about it a caller needs to reason across the call boundary without
re-analysing its whole body.
A single
require precondition: param OP literal, keyed to the parameter's position so
a call site can map it onto the matching argument.Scope for functions that are part of a module.
Search just for a matching function by name.
Provides fuzzy symbol search functionality using Levenshtein distance.
THE single source of truth for the gated-type → required-capability mapping and
its coverage rules.
Used to see if it is possible to resolve types, both simple and parametric.
THE fields a generated operator (
?, $, $$, ==, <=>, #?,
_fieldSetStatus) walks for one aggregate: its DeclaredProperties, then the variables a dynamic class
captured (CapturedVariables; each becomes a field).Struct-style data holder for all Phase 7 IR generators and helpers.
THE test of whether a parameterised type made inside a generic's body is a dependent (generic-in-generic)
reference of that generic: it is parameterised, still generic in nature, and every bare type parameter it names
(at any depth:
List of List of T) is one of the generic's OWN type parameters.A generic type's inferring constructor must take exactly its type parameters, in the same order - that is
what lets 'Box(21)' infer 'Box of Integer'.
THE rule for when a call to a generic FUNCTION may infer its type arguments from its arguments (D12, Steve
2026-10-19): only when the function's parameters are exactly its type parameters, in order, and nothing else -
the shape of a generic class's inferring constructor (E06050).
Used to model the scenario where a generic type has another dependent generic type used within it.
Widens a GENERIC construct's input-variety denominator to span the types it is actually
parameterised with (design D11/W5b).
THE mapping from a member of a MONOMORPHISED parameterised type back to the member of the GENERIC it
was substituted from.
The generic template a parameterised type was produced from (
List, Dict, a user Cache), or
empty when the symbol is not a parameterised type.🛑 THE parameter names of a generic type's synthesised inferring constructor, one per type parameter, in order
(one of the
SyntheticParameterNames; never invent arg/arg1).To be used in EK9 source code to assert that a type can or cannot be resolved.
Checks if there are any directives that relate to @Genus in the parsed module and checks the
resolution through the symbol and its genus.
Attempts to locate an Trait by name.
Extracts the EXISTING variable a pre-flow assigns: the target of a blind assignment (
v := e()) or an
assign-if-unset (v :=? e()).Given a 'type' (the IAggregateSymbol passed in), see it would be possible to
iterator over it with some other type.
Used for file path matching GLOB not regex.
THE parent's parent of a parse-tree node, or null when either is missing.
THE cycles of a directed graph: only the components of
StronglyConnectedComponents (THE Tarjan - iterative,
successors asked lazily, self-loops kept) that are cycles.THE reader of guard CO-OCCURRENCE — which of a callable's parameters, or which FIELDS of one
parameter, the code tests together.
Parameters, or fields of one parameter, that a condition (and its enclosing conditions) test
together, with the provenance needed to re-check it later.
Evaluates conditions with optional guard variables for all control flow constructs.
Result of condition evaluation containing both instructions and primitive condition.
Orchestrates the common guard + scope + return variable pattern shared by
control flow generators (while, do-while, for-range, for-in, try-catch).
Context record passed to core generator lambdas.
THE test of a guard (
PreFlowCanSkipBody) whose skipping skips a WHOLE switch or try - its
other cases, default, catch and finally too (D40) - so an analysis records the state there as a skip path and joins
it back after the construct.THE node whose recorded symbol is a guard's TARGET - the variable its implicit gate set-checks: the
variableDeclaration of v <- e(), or the identifier of v :=? e().Record containing guard variable management information for CONTROL_FLOW_CHAIN constructs.
E08270 (Steve, 2026-10-07, Q4): reading a
<- guard's variable in a LATER else if / else
block of the same if chain, before anything assigns it there.May the call hand the argument it is given at
parameterIndex back as (part of) its result -
return <- <that parameter>? The narrower question than RetainsArgument, which also counts an
argument kept anywhere else (receiver <- item) and the unknown opt-out: the closeable ownership
decision reports a hand-back (E81072) and treats any other keeping as handed on.THE calls that hand values to runtime threads for the life of a server or of the program
(EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S2): one handler serves every connection, the ready handler runs on
its own thread while the caller serves, and the signal dispatcher keeps its handler until the program ends.
THE "does the author's source give this type its OWN '?'" - hand-written,
default operator ? or the bare
default operator - for tools that edit source (adding a type's first field must also add a '?', E07235).Predicate to check if an aggregate type has a close() operator defined.
THE "does this type have any fields, counting inherited ones?" (Steve, 2026-10-07, Q-COMPONENT-?): its own fields
(
GeneratedOperatorFields - properties and a dynamic class's captures) or any property of a super, all the
way up.True when the text carries
FrontMatter (its FrontMatterJson is there).THE "is the aggregate's self copy GENERATED" (
SelfCopy, IsGeneratedCopy).THE "did the developer write an
== that takes the type itself" (not a defaulted one).Generates synthetic IR for the _hashcode (#?) operator.
Given a symbol, this check that the type that the symbol has can support the '#?' operator.
THE allocation-free form of
moduleName.equals(INaming.getModuleNameIfPresent(symbolName)) for a QUALIFIED
name: is the text before the first separator exactly moduleName? Always false for an unqualified name, so a
caller that must treat an unqualified name differently tests INaming.isQualifiedName(String) first.THE "has the aggregate its own REAL
<=> that takes itself" - hand-written, or defaulted (and not retracted)
over fields that can all really be ordered.THE reading of phase 5's property-cycle mark (
phase5/PropertyCycleMarker): can an object of this type reach
itself through its properties? Hold one and ask it - never the squirrelled data directly.THE shared test for "is this type orderable?" - does it have a REAL
<=> operator, one it
declares itself or inherits from a real (user) super, as opposed to only the degenerate Any._cmp
that EVERY type inherits and which is not value ordering.THE shared test for "does this type have a REAL
<operator>?" - one it declares itself or
inherits from a real (user) super OR from a trait (its own, a super's, or a trait's trait), as opposed to only the degenerate Any.<operator> that
EVERY type inherits (e.g.Generate comparison and conditional wrapper for a head or skipping stage.
Checks the possible operation variable, literal or function for suitability for use with
'head', 'tail' and 'skip'.
A runtime helper a stream loop drains - the async executor, a group/split tracker's stored buckets, the tail
buffer: the variable holding it, its type and its
hasNext/next pair.Converts bytes to Hexadecimal and back.
Does the text between a double-quoted String's quotes hold
${? A double-quoted String is never
interpolated, so the compiler rejects that (E07901) and names both backtick spellings
(InterpolatingBacktickString, LiteralBacktickString).THE HTTP access kind of a service operation's parameter: where in the request its value comes from.
THE defaulting of a service parameter that declares no
HttpAccess: it is a PATH parameter bound to the
placeholder of its own name.The
HttpAccess kind a text names, or empty when it is not one of the six words (the lexer's text, the
HTTP_ACCESS squirrel, the IR's binding).Checks HTTP Access for service operations because some require HTTP_SOURCE, but others do not support it.
Interface for an aggregate, typically a class or something like that.
Really a Marker interface for generic classes and generic functions.
Interface for dynamic functions and classes so that dynamic variables can be captured.
Given an identifier, this consumer checks if it is a property of some aggregate.
Deals with the checking and setting initialised of the identifier.
Used for pure identifier resolution and recording.
THE check of a READ of a local or returning variable that may still be uninitialised (E08020): every grammar
position that loads a variable's value hands its read node here - this is the one consumer, do not write another.
Ensures that 'identifierReference' is now resolved and hangs together and is 'typed' or emit "not resolved" error.
The position of a symbol in a list by IDENTITY, or -1: symbols of the same name in different scopes must not
match (a parameter list read for occurrences,
CallableParameterOccurrences, and for closeable slot stores,
CloseableSlotStoreOrError).Classifies where a lock-identity descriptor originates.
Specialized generator for EK9 if/else statements.
Generates IR for if/else statements using CONTROL_FLOW_CHAIN.
Checks the IfStatement is valid or emits errors.
Deals with checking if all paths through if/else/else-if/else result in variables meeting criteria.
Interface to abstract FunctionSymbol away as concrete implementation.
Interface for main entry point visitors that generate target-specific main entry points
for EK9 programs (e.g., main methods for JVM, main functions for native binaries).
Used by functions and methods as they may return a symbol (variable).
Typically used with programs.
To be used in EK9 source code to assert that a type can or cannot be resolved as extending a type or function.
Checks if there are any directives that relate to @Implements in the parsed module and checks the
resolution through the symbol and its hierarchy.
THE construction step of a function construct (named, dynamic or a parameterisation, generated as a class): its
constructor calls its super function's no-argument constructor when that super is a real EK9 super
(
NotImplicitSuper).Used to assist with determining the naming of symbol names.
A construction call that reaches a constructor which leaves properties without a value (E08264).
CONCERN: Loop counter increment/decrement.
Parameters for increment/decrement evaluation.
Given a symbol, this check that the type that the symbol has can support the '++' operator.
THE indent level Pass 1 gives each line -
CanonicalIndenter lays the lines out by it, and
LineSplitter asks it where a line it makes will be kept, so formatting the result again changes nothing.The levels of a source's lines.
The index of the first stage whose operator is
opType, or -1.THE spelling of inequality the compiler resolves: a developer's
!= is the operator <>
(method _neq); everything else is returned as written.A stream whose source the compiler can PROVE infinite may not reach a stage that waits for the end of the stream
(E10050) - decision 15(a), phase 1.
Calculates the Depth of Inheritance Tree (DIT) for aggregate symbols.
THE inherited
:=:(Super) signatures a GENERATED copy owner overrides (Q5b,
PolymorphicCopy): every :=: declared up its super CLASS chain
(AllOperatorsAbove) whose single parameter is a super type of the owner - one per distinct parameter type,
nearest first - unless the owner itself already declares that signature.THE rule for a sub-type that adds handlers to a dispatcher it inherits (front-end rationalisation D2, Steve
2026-10-02: "we have little choice but to do 'A'").
Gives each sub-type that adds a handler to an INHERITED dispatcher its synthesised entry point
(
InheritedDispatcher, front-end rationalisation D2), after every source has been through
EXPLICIT_TYPE_SYMBOL_DEFINITION: supers are linked and parameter types known only then.The body of a synthesised inherited-dispatcher entry point (front-end rationalisation D2): call the entry point it
overrides on the super, directly (a super call, never virtual), and return what that returns.
C2 fix 2 (Steve, 2026-10-08): a type that ADDS fields must declare its own
$, $$ and :=:
when it would otherwise INHERIT one (E07238), as E07235 already requires of ?.THE sameness a type INHERITS - from its super chain (stopping before
Any) or any of its traits (its own, a
super's, a trait's trait) - if any, sealed or not.The slots an aggregate's super chain occupies before its own properties in the flat field layout
(
FieldSlots): each super's properties, up to the first extern base, which adds its native footprint
(ExternFootprint) and ends the walk.Uses various components to load the Ek9 builtin types into a CompilableProgram.
An injected component is always set, so any check that it is set is always true - dead code that reads as
though the injection might not arrive (E08266).
Tracks injection counts within functions/methods/operators.
Pops the injection count from the counter and stores it as squirrelled data on the symbol.
Detects circular dependencies in component injection chains per application (E08190).
THE components of an application that sit on a circular injection chain (E08190), as
InjectionCycleOrError
found them - and THE rule that E08190 suppresses E08200 for them (Steve, 2026-10-11): in a cycle no registration
order works, so "reorder registrations" is advice that cannot be followed.Validates ordering in application blocks (E08200).
Validates DI injection design quality across a construct's methods (E11041).
Parallel to
InjectionCounter, but tracks the DISTINCT injected component TYPE
(fully-qualified names) per scope rather than just the site count.Holds generated classes in memory instead of writing a file per construct.
Models the concept of an Intermediate Representation construct.
Used for double dispatch when visiting nodes.
One in-place write whose reach
ReachOfInPlaceWrite reads.Does an in-place write of an object of this type (a mutating operator:
other -= 5, other++,
this :=: copy; or a stream target's |) run code of the program's own (D66)? A concrete built-in's
operator does not, unless it may call that operator back on an element (MayBeCalledBack: a
Dict merge merges the elements that share a key).One dimension captured by an
INPUT_CLASS_PROBE (design
EK9_INPUT_VARIATION_METRIC_DESIGN.md §5) — either a declared argument or the receiver as the
implicit p0 (§4.5).Specialised ASM generator for
InputClassProbeInstr — the input-variation numerator probe
(design EK9_INPUT_VARIATION_METRIC_DESIGN.md §5).THE input-class probe of a public construct's entry - the dynamic input-variety numerator (design §5) - and the
LOAD_FIELD walk that decomposes a record dimension into its leaves (IR tidy W3.9, INFRA-10: it was the IR
generating quarter of CoverageProbePlacer).Specialised IR instruction for the input-variation numerator (INPUT_CLASS_PROBE).
What this instruction is: an entry probe, or one edge of a §5.3 assert window.
The input-variation figures for one public construct, computed over its flattened leaf
dimensions (records decompose to fields; receiver-p0 included) — design §4.1 / §4.6.
Computes a public construct's input-variation
InputVarietyDenominator — the pairwise
opportunity space of its parameters (design §4.1).Records the input-variation figures — the 1-wise FLOOR (headline) and the pairwise DENOMINATOR
(ceiling) plus the per-leaf confidence — on each callable (method / function / operator),
squirrelled for the metrics / MCP surface next to
COMPLEXITY.To be used in EK9 source code to assert that a specific class, function or method has a
particular input-variation DENOMINATOR — the pairwise opportunity space its signature admits
(design
EK9_INPUT_VARIATION_METRIC_DESIGN.md §4.1, §11.5).Checks if there are any directives that relate to the input-variation denominator in the parsed
module, and validates them against the value the compiler squirrelled in phase 5.
THE reading and marking of
INPUT_VARIETY_RECEIVER: the input-variety FLOOR of this method counts its
receiver as dimension p0 (coverage design section 4.5), so the phase-7 numerator probe emits a receiver cell.THE marking of
INPUT_VARIETY_RECEIVER: the input-variety floor of this method counts its receiver as
dimension p0.True if the given parse node sits anywhere inside a 'require' or 'assert' statement.
The call-graph identity of an aggregate's property initialisers -
module::Aggregate._i_init(), the
method the generated code runs them in, and the name a stack trace shows.Discriminator for the
CastInstr.instanceOf(String, String, String, InstanceOfKind, DebugInfo) IR instruction.Checks that variable only and variable declarations have symbols that have been referenced.
THE single-source-of-truth for registering per-module coverage AND profiling metadata into the
runtime singletons
parent-side — i.e.THE integer-literal reader for a relational operand, shared by
RequirePredicateReader and
SymbolicEngine's division, guard and constraint paths: the literal's value, or null when the operand is not
an integer literal.THE value of an EK9 Integer literal's text.
THE way to make the compiler fail INTERNALLY on demand (Steve, 2026-10-08): with
-Dek9.internalError.at=<PHASE> on the compiling JVM (a CompilationPhase name, e.g.Holds the details for creating and internal 'decorated name' for a generic type that has been
parameterised.
Given some sort of generic type a function or a type with a set of 'type parameters',
create a unique internal name for that combination.
Generates IR instructions for interpolated string expressions.
The backtick String, delimiters included, in which every
${...} of a double-quoted String's text
evaluates - what the writer almost always meant (E07901).Phase C.3 of slice-2 deadlock detection — Phase 5 lock-order-cycle model.
Phase C.2 of slice-2 deadlock detection: compute per-function
mayEnter
summaries by composing direct enters with reachable enters via the call graph
and CrossThreadEdge list.THE line or column of a diagnostic map as the keyed repairs read it: the int of a
Number, else -1.THE line or column of a diagnostic map read leniently: the int of a
Number, or of its text when that
parses as one, else -1 (SourceRepairs' syntax layer and ServiceDeclarationForms each held this
copy, identical).A stack of integer counters, one per nested function/method/operator scope, accumulated during AST
traversal.
Error when the definition of an enumerated values could be invalid.
MULTI THREADED over sources.
Rather than smatter the Java code with 'stringy' constants for the IR, they are defined here.
In EK9 every construct becomes one of these nodes.
Static factory for creating complete tree of IR generators ONCE per construct.
Centralized context for IR generation within a single executable scope.
Deals with visiting all parts of the EK9 structure in a module (compilable source).
To be used in EK9 source code to check that the IR generated matches what is expected.
Checks if there are any directives that relate to @IR in the parsed module and checks the
resolution through the symbol and checks the IR that was generated.
THE normalisation applied to generated
@IR / @IR_PARAMETERISED golden content
before it is compared against - or emitted into - a directive body.Enumeration of the IR generation frame types actually pushed on the
IRGenerationStack.Central state management for IR generation, following the proven SymbolsAndScopes pattern.
Stack-based scope, debug, and context management for IR generation.
MULTI THREADED
All symbols resolve and so should be able to create an intermediate representation.
Base class for all IR instructions in the EK9 intermediate representation.
Converts the single IRInstr supplied by the supplier into a List with one element in.
Stateful instruction builder that uses the IR generation context automatically.
Represents the Intermediate Representation of the EK9 code for a particular EK9 module.
Enumeration of all IR opcodes used in the EK9 intermediate representation.
SINGLE THREADED.
To be used in EK9 source code to check that the IR generated for parameterized types
(generic type wrappers) matches what is expected.
Checks if there are any directives that relate to @IR_PARAMETERISED in the parsed module
and validates the generated IR for parameterized type wrappers.
THE IR rewriter: rebuilds an instruction list bottom-up.
Represents a single frame on the IR generation stack.
THE structured walk of the IR: every instruction, in every nested list, in rendering order, with each nested list's
role and
CompositeInstr.Activation (once, or once per loop iteration).What a walk tells its visitor.
THE "did the body use the member from a pure scope" (
NoteConceptualAccess).Is this expression's outer operator a binary
+ with two operand expressions? THE "this is a concat chain"
gate of the string-expression editors (was StringExpressionClassifier.isAddExpression).THE test that a symbol has no type because the expression it was declared from is already reported (E-7): its
readers stay silent rather than adding a 'type not resolved' for every later use.
Is
operator a plain store (: := = :=?) rather than a mutation - by the
operator's TEXT, as SymbolWrites.Write.operator() carries it.True when the node is the identifier of a property ASSIGNED by the statement it is the target of
(
me: ... or this.me: ...) - writing the property, not reading it.True for a stage that is a pre-loop barrier after an
async: on a source that is not bounded before
the async, a later head bounds only the async's output, and the windowed async driver cannot feed a
trailing barrier - the head must come before the async.THE "is this a binary expression?" of the phase-1 operand rules: any
expression alternative with both a
left and a right operand.THE test for a BOUNDARY PRIMITIVE: a method on a real EK9 type that exists only for IR/code generation -
_true, _false, _set, _of, _ofTrue, _ofFalse.THE "is the type built on conceptual type parameters without being one": a parameterisation with a bare
T
among its leaves (DictEntry of (K, Integer), List of (OrderedBox of T)), or a generic template named
in its own body (this < other inside OrderedBox of type T, which is OrderedBox of T)
(TypeParametersUnder).THE capture constructor of a dynamic class: the constructor whose parameter types are EXACTLY the capture types,
in capture order (
TakesExactlyTheTypesOf) - the one the definition site builds the object through, and the
only one the captured values are stored by (Steve, 2026-10-28: "we need an exact match").THE "is this symbol one of the variables a dynamic function or class captured?" - by IDENTITY against
CapturedVariables, never by name: a name join would take an unrelated variable of the same name (an outer
local, a property) for the capture; the E08251 check once did.THE "is this symbol a capture of the callable whose returning variable is being read" of the return-source
readings (
ReturnSourceClassifier, ReturnSourceOrigins): by IDENTITY (IsCapturedVariable),
one the callable (a dynamic function) or the type it belongs to (a dynamic class) captured.THE test, for a chained call (
ChainedCallDispatch), of whether definingType is a strict ancestor of
receiverType through the CLASS super-chain (IAggregateSymbol.getSuperAggregate() - class
inheritance only; traits are NOT on this chain).True when values of this TYPE have a close the compiler must see run (
CloseableResourceToBeChecked.isManagedCloseableType(ISymbol)) - THE question for a type that is not a field, for example
the component an application registers (the application closes it at program end).THE test of whether an application closes this registration at program end (
ApplicationClose): the type
it is registered AS, or its implementation, has a close.True when the method is a type's close operator.
THE coalescing test:
?:, <?, >? (??, <=?/>=? keep their grammar
tokens only so phase 1 can report E01096/E01095 - they never reach here).True for a stage that buffers its input into a collection (
group, split, async): the
stages a pre-sort drain must not run through, because it would treat them as a no-op pre-sort stage.THE "does the generic's body select between values of this conceptual
T with a comparison coalescing
operator" (NoteCoalescingComparison).THE test that an error code concerns compiler-development directives - the
CompilerDevelopmentCodes range
(E50200 to E50399).THE test for a constructor of a type that only the compiler may create -
Panic.<init> (Steve, decision 10,
2026-10-05; one of the three kinds of CompilerPlumbingCalls).THE "does the generic's body use this member of
T" (NoteConceptualAccess).FE77's "is this type concrete?": a type that names no conceptual type parameter anywhere in it - not a bare
T, not a parameterisation with a T among its arguments (at any depth), and not a generic type
itself.THE reader of the concurrent-entry-point mark (
MarkConcurrentEntryPoint): has this symbol been marked as a
root of the data-race model? Never read the squirrel raw.THE rule for what a condition may be: can a value of this type (first argument) be a condition, given the
Boolean type (second argument) - a Boolean, or a type that promotes to Boolean with '#^'.
THE rule for "is this expression a whole CONDITION": the control of an
if/else if/switch
head, of a while, or the expression of a require or assert.THE reader of the confined-type fact (phase5 ConfinedTypeMarker; design §13.11 T12): can no value of this type be
reached from anything shared between threads? A type with no mark - not yet decided, or not a user aggregate - is
shared: fail closed.
Is this store a construct's pre-flow - which its construct's marker (
ConstructSafeAccessMarker) judges for
E08040, before it marks the construct safe, so the store's own check (SafeAccessRepointOrError) leaves it.Checks if a type has the $ 'toString' method or a 'promotion' #^ to a String method.
Concept of a scope where functions, methods and variables can be declared.
The main type of scope in use a block is just like a set of instruction inside an if block
or a while block whereas a non-block is as the whole class/function/component level.
For symbols that are both a pure symbol but can also define a scope.
THE "is this aggregate a copy OWNER" - does it declare its own
:=: taking itself (SelfCopy)? E07238
guarantees a class adding fields is one (PolymorphicCopy).THE test for "does this fully qualified name (
module::Name) live in an EK9 core module": the module
part, by exact membership (IsCoreModule).THE test for "is this module EK9 core": exact membership of
Ek9CoreModules.NAMES, never an
"org.ek9." prefix (see Ek9CoreModules for why the namespace as a whole is not core).True when the operator is a close the developer asked for with
default operator close.THE reading of how a function call finds the function instance it invokes - hold one and ask it, never read the
DELEGATE_CALL mark by hand.THE test "is this dependency in the library": its dependency vector (
name-version) is unpacked as a
readable directory, or zipped as a readable file, in the DependencyInstallation's library folder.THE "is this a comparison B18 generates from the sameness?": a
<> < <= > >=
comparing the owner with itself (IsSelfComparison) - always generated, never written.Was the callee's retention DERIVED by phase 5 (a user callable) rather than DECLARED (a built-in's
@Ek9Retains)? The closeable ownership decision treats the two differently: a derived link is honoured
only where the return type may hold a borrowed view (support/BorrowedViewReturn).Predicate to check if a source file path represents a development source.
THE "is this an enumeration?" - the symbol's genus is
SymbolGenus.CLASS_ENUMERATION.THE "is this an enumeration TYPE, a base enumeration or a constrained one?" -
IsEnumeration, or a constrained
type over an enumeration (ConstrainedEnumerationBase).True when the source carries at least one
@Error directive - an error example (ErrorDirectiveText).True when the RHS hands back a temp that ALREADY carries a producer +1 (so this consumer must
SCOPE_REGISTER only, never a second RETAIN — a second RETAIN leaves two RETAINs against one
SCOPE_REGISTER = a +1 ARC leak on the LLVM backend).
THE test of one directory name against
ExcludedDirectories.NAMES: should a file walk skip a
directory with this name? Hold one and test with it; a whole path goes through IsExcludedPath.THE whole-path counterpart to
IsExcludedDirectoryName: true when ANY path element is an
excluded directory (build output, VCS, IDE cache).A variable (never a constant: each read of one is a copy) or
this/super.THE "is this an explicit
default operator X", as opposed to one added by the bare default operator
or one generated from the sameness (IsGeneratedFromSameness).THE test for "is this type EXTERNALLY LINKED?" - what
CallDetails.isExternTarget states (Steve,
2026-10-28: "extern should be externally linked in some way; defaulted/synthetic methods are not external").Whether a symbol is a literal value that may be lifted into a module constant - the symbol-side companion to
LiteralTypeNameOf (the parse-context side).True for a stage that forces a
for-range stream down the BUFFERED (drain-to-buffer) path: every stage
that ends the demand segment (EndsDemandSegment) except join, which streams (it emits its
result after the loop, so the range needs no buffer for it).THE "fresh value" predicate: true iff an expression evaluates to a NEW object - one nothing else holds a
reference to.
Which reading of "fresh" is asked.
Predicate to determine if a symbol is a function delegate.
THE "is this
:=: generated rather than written by hand" (default operator :=:, or the bare
default operator, and not abstract).THE "is this a comparison GENERATED from the type's sameness" (B18 - never written or requested).
True when the symbol is a generic TEMPLATE (e.g.
THE "did the developer write this operator's body" (not
default operator) - the sameness rules' meaning of
hand-written (B18, D24).THE "is this the zero-argument
#?" - the hash code that goes with a type's sameness (B18).THE
ACC_SYNTHETIC gate (C.1) on a MethodDebugPolicy bitset: a generated method is marked
synthetic iff its policy is exactly hide-always.THE "is the sameness this type declares ONE sameness for its whole hierarchy?" (D24 rule 1).
🛑 THE characters of an EK9 identifier: true when the text is one whole identifier by the lexer's
Identifier : Letter LetterOrDigit* with Letter : [a-zA-Z] and LetterOrDigit : [a-zA-Z0-9_]
(EK9LexerRules.g4), keywords included.True when a character can continue an EK9 identifier: an ASCII letter, a digit or
_ - the lexer's
LetterOrDigit : [a-zA-Z0-9_] (EK9LexerRules.g4).True when a character can begin an EK9 identifier: an ASCII letter - the lexer's
Letter : [a-zA-Z]
(EK9LexerRules.g4).THE "was this entry point synthesised by
InheritedDispatcher" (front-end rationalisation D2) - the
INHERITED_DISPATCHER squirrel.THE test of E08270's domain (
GuardVariableReadWhereUnsetOrError), for a rule that must not report the same
use a second time (E08096, OperatorKeepsValueUnsetOrError): is at inside a later block of an
if chain (an else if or the else) whose earlier block's <- guard declares
target, provably unset there (ProvablyUnsetGuardOf).THE test of whether a member the compiler synthesised is instrumented (given coverage and profiling probes by
FunctionProbes): only what an author would recognise.THE lines the JVM launcher writes on stderr before
main runs - Picked up JAVA_TOOL_OPTIONS: ...
(and _JAVA_OPTIONS, NOTE: Picked up JDK_JAVA_OPTIONS) whenever such a variable is set.THE test of whether
typeName is an EK9/Java primitive type (uses the I/L/F/D-family opcodes rather
than the reference A-family).THE test for a layout token (INDENT / DEDENT / NL / EOF,
LayoutTokens.LAYOUT_TOKENS): a token whose
position is synthetic, never the end of anything a reader sees.A field (or capture) whose type is a managed closeable (
IsCloseableType).Predicate that returns true iff the symbol IS the
org.ek9.lang::MutexKey
generic function itself, or a parameterised form of it (e.g.Predicate that returns true iff the call's resolved target is a constructor of
MutexLock (or a parameterised MutexLock of T).Predicate that returns true iff the symbol IS the
org.ek9.lang::MutexLock
generic type itself, or a parameterised form of it (e.g.THE "is this a negation applied to one operand?" - word
not b, ~b or unary -x.🛑 THE E11031 check: true when
name is one of the NonDescriptiveNames (case-insensitive), or a
positional one followed by digits (arg0, arg1, ...).THE test of the compiler-synthesised LIFECYCLE methods, which are never dynamically dispatched: the constructor
itself plus
_i_init (instance field initialisation) and _c_init (class/static initialisation).Is the property this identifier names reached through some object other than this one:
from.name, or
this.partner.value? Only a first member after this - or no receiver at all - is this object's own
property.THE test of whether a type is open for extension (can have subclasses) - the openness half of a call's dispatch
decision (
CallTargetResolution).THE ORDERING operator family test:
<, <=, >, >= and <=> - each delegates
(directly, or via DerivedComparisonGenerator) to <=>, so each needs the receiver AND every field type to
be orderable.Is the type the named built-in type itself, or does it have it as a trait: IS-A by the type hierarchy.
THE test of a built-in OUTPUT CHANNEL (Steve, 2026-10-27: "
> udpConnection and > stdout,
> stderr all feel normal"): the type IS-A org.ek9.lang::IO - Stdout, Stderr, a file output, a
UDP or TCP connection, a StringOutput, and a user type taking those traits.THE reader of the statement-ownership mark (
MarkStatementOwned): is this recorded symbol a call whose
closeable result its statement owns, and so closes? Phase 5's call graph and phase 7's call generation ask here;
never read the squirrel raw.True when the capture was marked as owned by the dynamic class that made it.
THE owners of the closeable temporaries made inside them: a block statement, or what is in no statement - a
returning variable's or a property's initialiser, or a text's string.
True when the symbol is a concrete PARAMETERISATION of a generic (e.g.
THE "is this a PARTIAL BUILT-IN" (
PartialOrdering): a core built-in whose runtime class declares a
comparison group (org.ek9.lang.ComparisonGroup) - its <=> is defined only within a group of its own
values and unset between groups (a currency for Money, a unit suffix for Dimension).True if this String literal is a plain double-quoted one - the only String form EK9 reads at compile time
(
PlainStringValue); a backtick String is not a compile-time literal (E07902).Is this type a
PRE_BUILT parameterisation - a generic type whose parameterised form ships ready-made in the
runtime (Iterator of Integer is _Iterator_2648..., a Java class in ek9-lang and a C struct in the
native runtime), marked by phase 6's ParameterizedSymbolCreator.markIfPreBuilt.THE "is this a prefix expression?" of the phase-1 operand rules (
BinaryExpressions): the operator comes
first and there is one operand (PrefixOperandOf), and the operator is one of
BinaryExpressions.PREFIX_OPERATORS - so not word not (IsWordNot).Is this recorded symbol a property field (a property, or a capture held in one) - false for no symbol.
THE reader of
MarkPublishedHandler's mark: is this a function handed to runtime threads for the life of a
server or of the program (design §13.11, S2)?THE reader of the registered-type fact (phase5 RegisteredTypeMarker; design §13.11 S2): can a value of this type be
reached from what is published for the life of the program - an application's registrations, a handler given to
runtime threads? A type with no mark - not yet decided - is registered: fail closed (a store into it publishes,
which costs memory, never safety).
THE "is this token one of the removed coalescing operators?" -
<=?, >=? (E01095), ?? or
??= (E01096), all reported by RemovedCoalescingOperatorOrError.THE question "is this a keyword that CANNOT be used as a name?" - true only for one of the
Ek9Keywords.WORD_KEYWORDS that fails to parse as word <- 1 in a minimal program.THE "is this a declaration of its owner's sameness?" (B18): a
<=> or == comparing the owner with
itself (IsSelfComparison).THE "does this operator compare its owner with ITSELF?" of B18 (
Sameness): an
operator taking exactly one argument of a type the owner is assignable to.True when the symbol is a property that the constructor this node is in stores 'this' into - so, in that
constructor, the property is 'this' under another name.
Creates CallDetails for _isSet() method invocation.
Creates evaluation instructions for _isSet() method calls.
Generates synthetic IR for the _isSet (?) operator using AND (flattened-aggregate) semantics.
Checks that aggregates with properties/fields define their own '?' (isSet) operator.
Given a symbol, this check that the type that the symbol has can support the '?' operation.
THE reader of the signal-reached fact (phase5 SignalHandlerNeighbourMarker; design §13.11 S2c, option A): can a
signal handler reach a value of this type - through what it captures or injects, never into a MutexLock payload?
A field of such a type written by code that runs beside a signal handler is shared state (E08251).
THE "is this a literal with its sign folded in?" -
-5, -2.5, -10#GBP: not a negation - it
calls nothing - but SPELT with one, so E08274 counts it when a negation is applied to it (- -5 is
5).THE test of "is this assignment token TYPE a plain one" -
:=, =, : or :=?: a
simple object-pointer assignment, not a deep or mutating operator (+=, :~:, :^:,
:=:).Is this expression a single string-literal primary - double-quoted or backtick interpolation? The rewriter's
idempotency check and the extractor's admission gate (was
StringExpressionClassifier.isSingleStringLiteral).Does the first rule's character span lie within the second's and differ from it - is it strictly smaller? (Was two
identical private copies in
StringExpressionClassifier.) By character index, not by tree ancestry - that is
IsWithin.THE test of whether a pipeline part is a stage's operand (
| map with holder.mapper(),
| sort with Ranked().comparator(), | head counter.limit(), a tee's transform or side
target).Is
operator (as SymbolWrites.Write.operator() or WritingOperator gives it) the target of a
stream - >, >> or SymbolWrites.TEE.THE access rule through a receiver: may the symbol be reached from the scope the access is made in.
THE "is this '?' the one synthesised for a field-less type (
FIELDLESS_IS_SET)?" of Q-COMPONENT-?
(FieldlessIsSet).THE compiler-synthesised MEMBER set -
_i_init, _c_init, _fieldSetStatus,
_copyAccepts, _base (Steve, F3a 2026-10-08: one predicate, widened from the lifecycle pair) - hold
one and ask it, never a second list.Was this call completed from its declared target (
TargetTypedConstruction,
TargetTypedConstructionMarker).THE test of whether a pipeline part is the side target of a
tee (| tee in target, its last
pipelinePart).THE test of whether a
tee's side target (its last pipelinePart) is a bare identifier - a local the pipe can
name, so it needs no pre-loop state (StageState.TeeSink holds an expression target).THE answer to "is this a
@Test program?" (and, with its siblings, what execution group it is in) — use
this, do not read the squirrelled key directly.THE test of whether a scope is the BASE of a
text construct - genus SymbolGenus.TEXT with no
LANG squirrelled data (each defines text for "<lang>" block is a locale variant that carries its
LANG; see TextFactory).THE test of whether a construct is an abstract TEXT base type (not a locale-specific variant).
THE test of whether a construct is a TEXT locale-specific variant (e.g., Greeting_en, Greeting_de).
The expression is
this itself.Predicate that returns true iff the call's resolved target is a stdlib method
which invokes its function/handler argument on a different thread than the
caller.
THE test for a unicode escape: a backslash, a 'u', then exactly four ASCII hex digits - the lexer's own
UnicodeEscape.A declaration whose retention was not DECLARED by a built-in: it carries no RETAINS, or only derived marks
(
IsDerivedRetention).Whether a candidate is a legal EK9 module name: true when the grammar's
dottedName rule accepts it in full
(surrounding whitespace allowed; null and blank are not).THE test that an identifier's recorded symbol is a VARIABLE (a local, a parameter, a returning variable, a
property), not a call or a type: the occurrences the flow checks follow an object through.
THE virtual-dispatch decision of a resolved call (
CallTargetResolution): false for constructors,
private methods (cannot be overridden), and targets not open for extension (effectively final).THE dispatch flag for a call the compiler SYNTHESISED, where the callee type may not have been threaded through
(
CallTargetResolution).THE "is this Windows" test - use this, never a private
os.name check (there were four, two of them
contains("win")).THE test for "is this node anywhere inside that one (strictly below it)".
Whether this symbol is a test program or a method declared inside one (
IsTestProgram has the
encoding contract).THE "is this word
not applied to an operand?" - not b.A sink is write-through - it never accumulates what it is given - only when its type IS-A
org.ek9.lang::StringOutput (Stdout, Stderr, a StringOutput).Does
operator write the thing it is applied to - an assignment (IsAssignmentOperator), or a
mutating operator (OperatorMap.isThisMutatingOperator(String), never a copied list).Represents the concept of what functionality a Symbol should have.
Defines helpful and require methods to assist in the definition of the nature of a symbol.
D66 gap (Steve, 2026-10-21): does a
for ... in loop over a value of this type run code of the program's
own? THE test: the loop calls iterator() and then hasNext()/next() (or those two on the
value itself), so it is a call that is not pure when the type - or the iterator its iterator() declares to
return - has one of those methods that is not pure and is supplied by the program: a method written in
EK9, or an abstract one of a built-in trait or abstract type (Iterator, Iterable) a program
implements.THE lowering of an iteration SOURCE - shared by
for x in source (ForInGenerator) and a stream's
cat source (StreamStatementGenerator); use it, never a third copy.Helper record for iterator setup results.
The internal model of a parse token - typically created.
Used in various ways to hold a token from the parse, so we can reference back to source code.
THE jar file of a
jar:file:/path/to/file.jar!/package URL, percent-escapes decoded - shared by the
runtime's extraction (RuntimeClassExtractor) and its content hash (ContentHashOf).THE indentation-aware slicer for
javap -v -p -l output — the shared helper that both
BytecodeNormalizer (strip a section) and the @DEBUG directive (keep a section) build
on.THE indentation-aware slicer for
javap -v -p -l output: the header+body text block of each occurrence
of a named section, in source order (no trailing newline per block).THE join of a source's lines back into its text - the inverse of
LinesOf (was SourceLines.join).Generate join (left-fold reduction) wrapper for a join stage.
THE content of a JSON string for hand-built JSON text: the characters to put between the quotes, escaped as
RFC 8259 requires -
" and \, and EVERY control character below U+0020 (\b \f \n \r \t by
name, the rest as \u00XX).The callable a
CloseableArgumentKeeping record is about: a member of a parameterised type is judged by the
generic's own declaration (GenericTemplateMember), anything else by itself.For when we just need to read ek9 files and pull out bits and bobs
rather than actually compiling.
Why the last
JustParser.readSourceFile(File, Ek9SourceVisitor) returned false - so a caller says the right thing.Converts EK9 type names to JVM type descriptors.
The JVM class-file version every generator stamps (
JvmOpcodes.CLASS_FILE_VERSION).THE licence files the compiler puts with every program it compiles for the JVM, in
ProgramLicences.FILE_NAMES order: the runtime's licence, its NOTICE and the third-party notices, read from
the compiler's own resources (RuntimeLicenceTexts).Target for a Java virtual machine.
JVM internal type names and descriptors that the compiler uses when generating bytecode.
May the callee keep its argument? Built-ins say so in their RETAINS; anything else may.
May
callee keep the argument it is given at parameterIndex somewhere other than its result - into
its receiver, another argument, or anywhere (receiver <- item, unknown)? The question a
constructor passing its own parameter on asks to know whether the parameter outlives the construction.May
callee keep its receiver beyond the call - an explicit rule, or the unknown opt-out?A rule saying the RECEIVER itself is kept:
<parameter> <- receiver or ambient <- receiver.THE "does this RESOLVED operator keep an unset receiver unset, whatever its argument?" - the
KEEPS_UNSET
squirrel the bootstrap reads from @Ek9Operator(keepsUnset = true) (see
UnsetKeepingOperator).True for a stage whose buffer keeps UNSET elements, which is EVERY stage lowered with a buffer (each stage that
ends the demand segment,
EndsDemandSegment: sort, tail, join, group,
split, async): a stream STAGE never drops an unset element - removing them is the developer's
filter (Steve, 2026-10-21: "async also passes unset results"; the D24 sort rule, 2026-10-20, places them
after every sorted group).True when a TERMINAL's target is a
List (the built-in, any parameterisation): collect as List of X,
> list, >> list and a tee ... in list target append each element with the List's
+= (_addAss), which keeps an unset element, never with its | (_pipe), which drops
it (Steve, 2026-10-21: "keep them through +=").What may come to HOLD the argument
callee is given at parameterIndex, other than its result: the
receiver (RetentionRule.RECEIVER) and the names of the other parameters it may store the argument into
(receiver <- item, items <- item).Specialized IR instruction for control flow labels (LABEL).
Specialized ASM generator for LabelInstr processing.
THE true last line of a parse rule: the 1-based line of the LAST real-content token under a node, or -1 when it
holds none.
THE join of the value-tracking lattice: the least upper bound of two values at a branch convergence point.
THE order of the value-tracking lattice: does one abstract value admit every run-time state another admits?
THE layout repairs - the faults in how a source is laid out rather than what it says, each with exactly one
reading and none able to change which code runs.
The repaired text and one note per repair; notes empty means nothing changed.
THE tab rule: a source with each LAYOUT tab replaced by two spaces (was
LayoutRepairs.replaceLayoutTabs).THE shared knowledge of EK9's LAYOUT tokens — INDENT / DEDENT / NL / EOF — and the one correction
every consumer of a parse-rule's END position needs because of them.
THE number of leading spaces of a line, for the repairs (was
SyntaxProbe.indentOf and
SourceLines.indent, the second delegating to the first).One field step in a
LeafPath — everything a backend needs to load that field from the value
on the stack, with no further symbol lookup.One scalar leaf dimension of a callable's input space, together with the field path walked to
reach it from the declared parameter (design EK9_INPUT_VARIATION_METRIC_DESIGN.md §4.5/§4.6).
THE types a reference to this type couples to, in order: the generic template it was produced from (empty
for a plain type: a built-in container, or a user generic's own module,
GenericTemplateOf) and then every
leaf concrete type argument (ConcreteTypeArguments).THE "must a generated
#? on this type leave this field out?" - the reading of phase 5's property-cycle marks
(phase5/PropertyCycleMarker) for the hash (Contract 13).Due to way Antlr does is class generation we need to make an interface to decouple to
enable debugging and alternatives.
Checks the left hand side and the right hand side for assignment compatibility.
Access the Symbol for the lhs of the preflow statement.
Compares two multi-line strings line-by-line for equality.
THE split of a source into its lines for the text rules: a mutable list, keeping a trailing empty line so that
JoinedLines gives the text back (was SourceLines.split).Pass 4 of the EK9 source formatter: Line Splitting.
THE call shapes for the raw
org.ek9.lang::List buffer that stream pipeline staging
drains into - use these, do not hand-roll a fourth variant.Generates JVM bytecode for LIST_LITERAL IR instructions.
Details for the LIST_LITERAL IR instruction.
Generates IR instructions for list literal expressions.
IR instruction for list literal construction with pre-sized allocation.
Creates/Updates an ek9 list of a specific type if the expressions are typed correctly.
The backtick String, delimiters included, whose value keeps every
${ of a double-quoted String's text
as characters.Generates JVM bytecode for EK9 literal values.
Extracts constant values from EK9 AST literal nodes.
Deals with generating the correct IR Instructions for processing any form of literal.
IR instruction for loading literal/constant values.
Specialized ASM generator for LiteralInstr processing.
Parameters for literal value loading.
A simple record that can be used when processing literals.
THE declared (target) type of a List or Dict literal - use it, do not re-derive the walk.
THE literal-context to fully-qualified-type-name resolver: the EK9 type a parsed literal denotes (e.g.
Checks for C++ target architecture.
Abstract Target for LLVM code output, can be for Go or C++ (with different Ek9 std library and
memory management.
THE JVM local-variable LOAD opcode for a type (ALOAD for object/reference types and null) - single-sources the
per-type opcode switch the generators had duplicated.
Authoritative validator for EK9 locale identifiers used in
defines text for "<locale>"
blocks.Used in many ways via composition.
THE names of the
LocalScopes phase 1 creates, and the only place their text is spelt.Metadata for a local variable needed for LocalVariableTable generation.
Generates deterministic internal names using SHA-256 hashing.
THE location of a symbol for a message: "on line 6 in 'filename.ek9'".
Extracts a string for the form "on line 6 in 'filename.ek9'".
Single source of truth for slice-2 deadlock analysis results.
Walk 4 of phase 5: data-collection walk for slice-2 deadlock detection
(Phase B.1 — intra-function scope).
Outbound-encapsulation check: data inside a
MutexLock must be purely contained —
the lock holds the only reference to its protected payload.Catalogue entry for a single lock identity tracked by the slice-2 deadlock analysis.
Tracks which physical
MutexLock object(s) a variable may currently
refer to at a given program point.How much the compiler's one program lock (
SharedThreadContext) is used and waited for - the measure of
what serialises the front end.One reading of the counters.
Workspace-wide lock-precedence graph used by Phase 5 cycle detection.
One observed nested-enter relationship between two distinct lock identities.
THE shared encodings of lock-analysis stable ids - use this, never re-spell a
source:line:col location key
or the placeholder: prefix.THE token-identity rule of a
LockIdentityValue: two identity tokens are the same token when they are
structurally equal PlaceholderTokens, and otherwise only when they are the same object (==) - an
ISymbol's structural equals would merge two different locks.Wrapper for logging.
Defines the necessary structure for processing logical operations line AND/OR/XOR.
Specialized generator for EK9 logical operations (AND, OR) with short-circuit evaluation.
Record to group logical operation context information.
IR instruction for logical operations (AND/OR) with short-circuit capability.
The type of logical operation.
Detects logical tautologies and contradictions (E08085).
The two ownership rules that need to know which instruction lists run once per loop ITERATION (an activation),
not just which scope ids exist - EK9_IR_OWNERSHIP_MODEL.md §12, stage 0, stated in today's opcodes:
A value is owned by the activation that makes it (model V-F, the A11 rule).
Encapsulates all data needed for generating a FOR_RANGE loop case (ascending or descending).
Shared helper for guard variable evaluation in control flow constructs.
THE loop condition in its own per-iteration scope (IR tidy FLOW-10): the scope is entered and left on every
iteration so the condition's temporaries are released each time round.
What an evaluator hands back from inside the iteration scope.
Validates that a module does not contain repeated magic literals (E11065).
THE contexts in which a literal is never a magic literal, for both magic-literal checks (E11064, a number in a
comparison, and E11065, a repeated String): the fix itself (a constant declaration), a pre/post-condition
(
require, assert), a constrain declaration, and a NAMED argument - the label documents the
value and the compiler checks it against the declared parameter (E06240/E06250), so it cannot lie.Detects bare literals used as operands in comparison, relational, matching,
and range expressions (E11064).
Tracks literal occurrences across files for repeated magic literal detection (E11065).
One recorded occurrence of a literal.
Generates the unified ek9.Main class that provides a standard Java entry point
for executing EK9 programs with automatic discovery and reflection-based invocation.
Contains all the information needed for target-specific visitors to generate main entry points.
JVM-specific main entry visitor that generates ek9.Main class with Java bytecode.
LLVM/C++ main entry visitor for generating native binary main entry points.
Locates the appropriate main entry visitor for the appropriate target architecture.
A bit of a catch 22, need to issue errors and the like when traversing an identifier in
some circumstances.
CONCERN: Literal loading with memory management.
Returns the appropriate operator text symbol for the expression.
Generate function call and pipeline item reassignment for a map stage.
THE mark of a CONCURRENT ENTRY POINT - a function or method whose body may run on another thread (a service
operation, a handler given to a thread-spawning call such as
TCP.accept, an element function of an
async stream stage).The reason a dynamic class (or closed class) never ends - its effective
hasNext()'s
NEVER_ENDING_ITERATION mark, made by NeverEndingIterationMarker - if it has one.Record, on a user method, operator or function, that the argument given for a parameter may be kept beyond the
call - the rule
<destination> <- <parameter> (RetentionRule.destination() and
RetentionRule.source()), exactly the text a built-in declares: the destination is receiver (stored
in a property of the object), another parameter's name (added to the object that argument refers to),
ambient (held where nothing here can name it: a capture, a returned closure, a call that keeps it) or
ReturnRetention.UNIMPLEMENTED.Record, on a user method or operator, that the object it is called on may be kept beyond the call -
<destination> <- receiver, exactly the text a built-in declares (HTTP.whenReady's
readyHandler <- receiver): the destination is another parameter's name (the receiver is stored in what
that argument refers to) or ambient (held where nothing here can name it: a capture, a returned closure, a
call that keeps it).Record that an abstract declaration nothing implements MAY keep each of its arguments
(
unimplemented <- <parameter>, ReturnRetention.UNIMPLEMENTED); the keep counterpart of
MarkReturnsEachParameter.Sets the
CONCURRENT_ENTRY_POINT = "TRUE" squirrelled marker on every
non-constructor, non-operator, concrete method of the supplied aggregate.THE dispatch union (Steve, 2026-10-21, D61): a call through
declaration may run override - a
method that overrides it, or a function (dynamic functions included) whose super function it is - so the
declaration also returns whatever the override does, and keeps whatever the override keeps (the lane
callee-keep, 2026-10-21: receiver <- item, <otherParam> <- item, ambient <- item).THE mark of a function handed to runtime threads for the life of a server or of the program - the handler given to
TCP.accept, acceptUntilComplete, HTTP.serveUntilComplete or Signals.register
(design §13.11, S2).An abstract declaration no program code implements: which implementation runs cannot be known, so its result may
be any of its arguments -
return <- <each parameter>.Record, on a user method, operator or function, that what it returns may be the argument given for the
parameter
parameterName - return <- parameterName, exactly the text a built-in declares
(List.getOrDefault's return <- defaultValue).Record, on a user method or operator, that what it returns is (part of) its receiver
(
ReturnRetention.RECEIVER_INTERIOR, exactly the text a built-in declares).THE mark that a call's closeable result is owned by the block statement that makes it, so that statement closes
it when it finishes (the unnamed half of the closeable ownership rule, Steve 2026-10-05).
THE line with its literals masked out, for a text rule searching for code (was
SourceLines.masked): the
content of every String, backtick String and character literal replaced by MaskedLiterals.MASK, and a trailing
// comment likewise - same length, so an index found in the mask is an index in the line.There are times when it is necessary to compare a range of symbols to see
which is the best match.
An initial stuff for match results.
Does what
callee returns possibly share an object with its receiver or an argument.THE test of whether an object of this type may be handed to a built-in that calls a member of it back that is not
pure (D66).May the value of this expression BE an object that exists already - rather than a fresh one: a variable (not a
constant, which is read as a copy),
this/super, a call whose RETAINS says its result may be its
receiver's interior or an argument (MayAlias), or a coalescing operator's result or a
ternary's when EITHER operand may be (the result is one of them: the same route ObjectSharing follows for
the operand itself).Is the expression, looking through parentheses, of a SHAPE whose value may be an object that already exists -
a variable,
this/super, a call, or a coalescing operator or ternary (whose result IS one of its
operands) - so only MayBeExistingObject, once phase 5 has derived the RETAINS of the program's own
callables, can say whether it is.May the value given to a name be, or hold, an object from OUTSIDE the code being analysed (D66) that the name is
not recorded as sharing with:
this - itself, or held by a list, a Dict, a constructor's or call's
arguments or a dynamic function's or class's capture list (box <- Box(this)) - or a result a call, a
coalescing operator or a ternary hands back that may be an existing object.May a value of this type be of a type of the program's own - whatever it declares? A trait, an abstract class, an
open class (
Any included) or a generic's T.May a callee change the objects it is given as arguments? Not when it is
pure, nor when it is a concrete
built-in method or function that runs no code of the program's.The MAY half of
DefinitelyKeepsArgument: does callee say, by an EXPLICIT rule, that it keeps the
argument - or is it an abstract declaration nothing implements, which MAY keep any argument
(ReturnRetention.UNIMPLEMENTED)? An unnamed closeable given to such a callee is E81072 (nothing could close
it); a named try resource given to it is allowed.THE test behind E07187 (D24 Q4 REVISED, Steve 2026-10-20): can two values of this type be of DIFFERENT run-time
types whose
<=> is UNSET? Then <? and >? have no lesser or greater value to select, and an
unset value cannot be built to stand in for one (a T() may be set, absent, private or abstract, and would
run developer code).May a call through another declaration run this callable - a method of an aggregate (dynamic classes included,
constructors not), or a function (dynamic functions included)? The callables the dispatch union of the RETAINS
derivations (
ReceiverInteriorReturns, CloseableArgumentKeeping) unions over.May the call (or stream stage operand)
call run code of the program's own - something that is not
pure and not a concrete built-in? Such code may change any object it can reach, an object kept where the
caller cannot name it included.THE tolerant reader for a symbol's measured
CommonValues.COMPLEXITY, for consumers that
treat "not measured" as zero rather than as an error.THE writer of a measured
CommonValues.COMPLEXITY for a symbol that phase 5 will never visit; its tolerant
reader is MeasuredComplexity.Specialized IR instruction for memory operations (LOAD, STORE, ALLOCA, REFERENCE).
Specialized ASM generator for MemoryInstr processing.
Loads alternative error messages and DI guidance from a zip file.
Single source of truth for which access modifier is legal on a method / operator / constructor
within a given aggregate genus.
THE one place a
METHOD_AMBIGUOUS diagnostic is emitted in phase 3, and the only place its three message
shapes are spelt.Useful when attempting to traverse up stacks to find both the method and its parent aggregate.
Shared context for a method that must be coordinated across all generators.
THE debugger step-filter / frame-decoder policy bits carried per generated method by the
Ek9MethodKinds class attribute (C.2).Derives an
Ek9MethodKind for a compiler-generated method emitted through the IR funnel
(generateGeneralMethodFromIR / generateGeneralConstructorFromIR in
AsmStructureCreator).The debug-time reader of one class's
Ek9MethodKinds attribute (C.2): parses the class bytes
into a (method name + descriptor) -> Ek9MethodKind / MethodDebugPolicy
lookup.THE key of a method in the
Ek9MethodKinds attribute: its name and descriptor, space separated.Per-class accumulator of
Ek9MethodKind entries, populated as methods are emitted and
turned into the Ek9MethodKinds class attribute just before visitEnd() (mirroring
how the SMAP is collected then attached).Just checks that named operator methods:
mod, rem, abs, sqrt, close, contains, matches, empty, length
are not being used as just method names.
To be used when resolving a method by name and call arguments within a specific scope (an aggregate).
Check overrides on methods.
Result of method resolution including cost analysis.
Simple record tuple to combine the scope to be searched and the method signature to be searched for.
Represents some type of method that exists on an aggregate type scope.
Quite a few option to a method search.
Create a MethodSearch symbol for an operation that could have a single expression or two expressions.
Models a set of result for a search for methods.
A single enforced quality/architecture metric limit, self-describing enough that BOTH the phase-5
checker that fires the error AND the MCP/IDE enquiry layer that reports headroom can read it from
the one place — see
MetricLimits for the registry and the rationale.How a measured value is compared against the limit.
A compound limit that fires only when an absolute cap AND a relative ratio are BOTH exceeded, and
only once the module is at least
minConstructs in size (small modules are naturally
disconnected and are exempt).A per-genus threshold table:
byGenus holds explicit limits, fallback covers genera
not listed, and exempt genera are not checked at all (so MetricLimit.GenusLimit.limitFor(SymbolGenus) is empty and
MetricLimit.GenusLimit.isOver(int, SymbolGenus) is always false for them).A gate on a fractional score rather than a count — E11020 multiplies a construct's complexity
ratio by its statement ratio and fires above 0.50, so neither operand is a limit in its own right
and the threshold cannot be an int.
A single-threshold limit with a comparator.
THE shared steps of every
Acceptable*OrError quality-metric check: find the symbol the metric belongs
to (MetricSymbolOf, one null policy), squirrel the measured integer (RecordMetric, one encoding) and
raise the error when it is over the limit (this).THE single source of truth for EK9's enforced complexity / coupling / cohesion /
dependency-injection metric limits — the exact thresholds the phase-5
Acceptable*OrError checkers fire on.THE first step of every
Acceptable*OrError quality-metric check (with RecordMetric and
MetricLimitCheck): the symbol the metric is recorded against - one null policy, an assertion, because a
metric scope is pushed on entry for a construct that has a symbol (the node, not the symbol, is never null).Supplies the middle end phases for compilation..
THE mirror of a relational operator glyph, for re-expressing
a OP b as b OP' a: 5 > x is
x < 5.The mandatory properties this package block does not set: 'version' (E06262), then 'description' (E06261),
each reported as
MissingPackagePropertyMessage.The message for a missing mandatory package property (
MissingPackageProperties), after
In '<module>' package: .For a message: how a type for which
MayMixRuntimeTypes holds can have values of different run-time types -
"a trait", or "an abstract" / "an open" followed by "class", "record" or "component".Defines a module scope, the main concept for namespaces in EK9.
Tracks module-level cohesion by recording constructs and their intra-module type references.
Tracks module-level efferent coupling (Ce) - the number of distinct external modules
that a module depends on.
Goes through each module name and checks each of the parsedModules in that module name to check
there is only a single copy of that symbol in the whole module name space.
THE module-to-
ErrorListener lookup every module-level check takes (coupling, cohesion, size, data clumps,
magic literals), beside callgraph/CallableErrorListenerLookup, which does the same for a callable.THE validator for an EK9 module name — use this (or
IsValidModuleName), do not hand-roll a regex.THE module a type symbol belongs to, for the module-level quality trackers: the module the symbol was parsed
in (phase 1 already resolved and recorded it, so reading it back is immune to the name-shape assumptions a name
split makes), else - only for a symbol with no parsed module, such as a built-in reached through a synthesised
scope, where there is nothing else to read - the module part of its fully qualified name.
With EK9 it is possible to have multiple source files that are all in the same 'module'.
This is a very special scope, because the same 'module name' can be defined in
multiple files.
THE per-module
SymbolFactory cache of the end-of-phase-2 post-passes: one factory per source, made when the
pass first needs it, as when each module was walked in turn - rather than a new one for every aggregate (front-end
rationalisation A-7).THE Scenario-3 monomorphisation state of one IR generation context (IR tidy W3.9, INFRA-14) - the type-parameter
mapping in force, the dynamic-construct copies made for it, and THE resolution of a (possibly conceptual) type to
the concrete type a monomorphised body emits.
Detects which monomorphization scenario applies to a parameterized type.
The three monomorphization scenarios.
THE "whose code is running here?" - used when trying to locate the current class, dynamic class or dynamic function, to
be able to check if access to fields or methods should be allowed, or even resolve methods without 'this' prefix.
THE variables an operation body's ownership form moves out of (the value of a consuming
SLOT_ASSIGN).Detects multiple arrow usage and emits clear educational error messages.
THE answer to "does this code run every time its enclosing body runs?", read from its position in the parse tree.
How far the walk climbs: to the enclosing BODY (
MustExecutePosition.Scope.BODY, FE77), to the evaluation that owns the code in its
statement form (MustExecutePosition.Scope.STATEMENT), or to the nearest conditionally evaluated operand too (MustExecutePosition.Scope.EVALUATION).Checks if a symbol can be mutated, this is nothing to do with a pure context.
Item 5, step 1: the E08090 (NOT_REFERENCED) verdict FULL_RESOLUTION deferred, on a local initialised by a call and
afterwards only mutated in place, never read (
view <- config.get("server"); view :~: overrides).What PRE_IR_CHECKS needs, collected during Walk 1 (by
PreIRListener, every source in parallel), to decide
the E08090 verdicts FULL_RESOLUTION deferred (item 5):
every local marked NOT_REFERENCED_DEFERRED - initialised by a call, afterwards only mutated in
place, never read - with the expression it was initialised by (MutatedOnlyVariableOrError);
every user method, operator, function and dynamic function with a returning variable, with each expression
that variable is made to REFER to (its initialiser, every pointer assignment (pre-flows included), and through
an arm-shaped value the returning variable it yields), so ReceiverInteriorReturns can derive whether a
method returns (part of) its receiver and CloseableReturnOrError can require a closeable return to be
new - both reading ReturnSourceKind.
Shared across the parallel walk, so the queues are concurrent; the per-source state is in a MutatedOnlyVariables.Collector.A deferred local and the expression it was initialised by.
A user method, operator, function or dynamic function with a returning variable, and every expression that
variable is made to refer to.
True when the operator mutates, in place, the object its target refers to (
+=, :=:,
:~:, ...), rather than re-pointing the target (RepointsTarget).A
MutexKey dynamic-function body — the lambda passed as the argument to
enter(...) or tryEnter(...).Inbound-encapsulation check on
MutexLock(...) constructor calls.Restricts the construction of
MutexLock to field initialisers on classes or
components.Rejects parameterising any generic (other than
MutexLock itself) with
MutexLock (or a parameterised MutexLock of T) as a type argument.THE covariant return of a function: its super function's return type, when this function narrows it - the
function form of
NarrowedReturnTypes (N07, phase 7's covariant bridges).THE return types of the (non-private) parent declarations a method overrides (
OverriddenDeclarations) with
a NARROWER - covariant - return, one per distinct type (N07, phase 7's covariant bridges).THE rule that a
PriorityQueue ordered by its elements' natural order needs an orderable element type
(D63, Steve 2026-10-21, option B).THE nearest declaration above an aggregate that a level test finds - asked of each super class in turn, nearest
first (
SuperClassChain).THE ascent to the nearest strict ancestor that satisfies a test, with a boundary.
THE nearest strict ancestor of a given parse-rule type, with a boundary (
NearestAncestorMatching by
type).THE nearest operator ABOVE a type: the declaration a type would inherit, found by walking its super CLASS chain
(never its traits) and stopping at the first level that declares it.
THE sameness a type would inherit through its super CLASS chain (D24 follow-up Q5, Steve 2026-10-20): the nearest
concrete
<=> comparing its owner with itself (NearestSelfComparisonAbove) - the super is ORDERED -
else the nearest such == - the super is EQUATABLE only.THE nearest SAMENESS operator above an aggregate (D19, Steve 2026-10-20): the nearest
operatorName
(== or <=>) declared above it that compares the level declaring it with ITSELF
(IsSelfComparison) - matched by SIGNATURE, never by name, never Any's.THE sameness a type that declares none of its own gets from its super CLASS chain once PRE_IR_CHECKS has run
(D55):
NearestSamenessAbove, but a <=> that does not survive
(OrderingAvailability.orderingSurvives(MethodSymbol, ISymbol)) is passed over for the nearest == - the super is EQUATABLE
only.THE "does the owner get a
_copyAccepts?" (PolymorphicCopy).True when a
> would have to replace its target but the target cannot make a fresh value (E08278): it is
abstract or a trait, has no accessible no-argument constructor, or has no :=: to swap the fresh value in.THE test of whether a sameness comparison - the type's
== or <=>, hand-written or generated, or a
generated ==/<> answered by its <=> - needs the run-time-type check in front of it (D24 rule
3, Contract 22): values of different run-time types are never the same.THE operand a negation (
IsNegation) is applied to, looking through parentheses (Q8): in
not (not b) and -(-x) the operand of the outer negation is the inner one.THE negation that an expression is the operand of, looking through parentheses (
not b is the operand of
the ~ in ~((not b))); null when it is not the operand of a negation.Detects `throw` statements whose expression is a nested call (E11070).
Tracks nesting depth within functions/methods/operators.
The phase-5 pre-pass that marks iteration the compiler can PROVE never ends (decision 15(a), phase 1: the
infinite half).
THE index of the nearest line after
index with content, or -1 (was SourceLines.nextContent).THE no-argument constructor of a type, whatever its access -
Counter().THE check that a construct being defined in a user module does not take the name of a built-in construct
(E01090).
Checks that a name being defined at module scope does not differ ONLY by case from a name
already defined in that same module (across every construct kind - class, record, trait,
function, component, service, text, program, application and constant).
As it is possible to have a variable that is a delegate 'function',
it means that to call that function, the ek9 developer would use variable-name(parameters).
Just to enable viewing and printing of nodes.
THE check that an aggregate does not redeclare a property its super chain already declares - one rule
for records, classes, components and dynamic classes (traits cannot declare properties, E07075).
Examines all the service operations on a service and looks at the verbs used and the uri proto paths.
Checks for duplicated trait names on an aggregate (E02050).
Does a simple check (excluding any inheritance) for duplicated operations (methods, operators) on
any sort of Aggregate, i.e.
Every LOCAL variable of a module checked against the methods of the type it is declared in - its own, inherited and
from traits (see
NoNameCollisionOrError.errorsIfLocalNamedLikeAMethod(IAggregateSymbol, ISymbol)).Typically used for Constructors, but could be used in other contexts where a method
is not expected to return anything.
Designed to check if variable name and method names collide with Type/Function names.
Detects non-descriptive variable names (E11031).
THE single source of the variable names E11031 (NON_DESCRIPTIVE_VARIABLE_NAME) bans - and of everything published
about them.
One group of banned names with what is published about it.
Aimed at methods in services and a program (which is a method).
SINGLE THREADED, for the same reason as SymbolDefinition: the parallel machinery was removed
because definition serialises on the CompilableProgram lock.
A trait listed beside another listed trait that already has it -
with trait of LoudSpeaker, Speaker where
LoudSpeaker with trait of Speaker - is E02090 (Steve, 2026-10-11): the second name adds nothing, and it
used to surface in FULL_RESOLUTION as E06150 "method 'speak' on 'Speaker' and 'Speaker'", one trait named twice.THE normalisation of a relational operator glyph, shared by every analysis that reads one - the symbolic
engine's guards and constraints, require preconditions, and the flow analysis's symbolic path conditions.
THE check that a body which must return a value can do so: a scope whose every path ends in an exception has an
unreachable return (E07380).
Typically used in control expressions to check developer is not doing a while(true).
THE 'cannot call an abstract function or type' check (CANNOT_CALL_ABSTRACT_TYPE), with the located message.
Check not dispatcher methods.
THE note that the generic's body selects between values of its conceptual
T with <? or >?
(D24 Q4 REVISED).THE note that the generic's body uses this member of its conceptual
T
(ConceptualAccess), and - when the body is in a pure scope - that too: the
concrete member must then be pure (a conceptual constructor's own purity is meaningless - it is synthetic on
T).THE note of an operator the body used on
owner, but only when owner IS a conceptual type parameter -
a concrete type needs no deferred check.THE note of a natural-order
PriorityQueue of this element type, when it is built on a conceptual parameter
without being one (PriorityQueue of (OrderedBox of T)).Records, on each conceptual
T a resolved call carries, the ordering step the call is (D91 step 4), so a
generic's own <=> that compares its T values through a call is judged as one that compares them
directly (D89; read by TypeParameterOrderedInOwnComparison, judged by phase4/ParameterisedTypeOrError,
E07188):
a call of one of the generic's own methods - on itself or on another value of the same generic over the same
parameters (other.itemOrder(this)), an override it declares included - hands every T on to that
method's body;
a call of a generic function (rankOf(item), its type inferred) hands each T on to the type
parameter it is bound to, in the function's body;
a T value given to a function delegate (a variable or property holding ordering() of T, or a
function a call returned) is taken to be ordered there, whatever the delegate does: what it is cannot be known
here (strict, as E06070).
Only the steps from the generic's own <=> are followed, so recording a call anywhere else changes nothing.A resolved call: what it calls, whether that is a function delegate, and its arguments (needed only for a
delegate).
THE note, where a resolved ordering operator (
<=> < <= > >=) is used on a
type that is built on a conceptual parameter without being one (DictEntry of (K, Integer)).Generates synthetic IR for the _neq (<>) operator.
THE note of the copy constructor a
for range over T will use (NoteConceptualAccess, and
marked as the range's): which one runs, and whether it is pure, is only known at parameterisation.Records, on a conceptual
T, that the body being resolved compares its values with <=>
(item <=> other.item over item as T?) - one ordering step (D89, D91 step 4).Checks that the variable supplied (if not null and has a type), does not have a type that
is a genericTypeParameter.
THE single predicate for "does this super type need an EK9-style super-init call emitted by the IR?".
E08273 (Steve, 2026-10-07, P5; 2026-10-08, P6): word
not is never an UNPARENTHESISED operand of another
operator, except and, xor and or - so neither of any other binary operator (P5) nor of a
prefix operator (P6: ~not b, $ not b, #? not b, ...).Used where traits are implemented 'by' a variable.
To be used in EK9 source code to assert that a type can or cannot be resolved.
Checks if there are any directives that relate to @Resolved in the parsed module and checks the
non-resolution.
This is the second part of the method/function chaining resolution and can be recursive via objectAccess.
In the case of specific variables of type like 'Result' and 'Optional' it is important to check
if the method being called needs a previous call to isOk or isError or just '?' before accessing
specific methods.
THE final
.step of an objectAccessExpression chain - .name in getHolder().name - or
null when the chain has no steps.Creates IR instructions for object access expressions.
Result holder for each step in the chain processing.
Processes the Object Access start, this is the start of chained method/function calls.
Number of
.step accesses after the start of an object-access chain - this.code is 1,
this.sink.items is 2.Provability of the OBJECT that bears a field-rooted MutexLock at an enter
site — the answer to "can a single consistent global acquisition order be
proven for two locks sharing the same field declaration but reached through
this object?" (Stage-3 Phase 2/3b, deadlock detection).
THE reading of what one occurrence of a name does to the OBJECT the name refers to - for every analysis that
remembers what a variable holds (the phase-5 value tracker behind E08086,
CompileTimeKnownText behind
E08275).What an occurrence does to the object.
One occurrence's effect.
What
this or super - the object a method runs on, whose name is no identifier - does to that
object, read exactly as the occurrence of a variable is (ObjectSharing): kept where the whole expression is
kept (items += this, box <- Box(this), (this) is ...), or the start of a call chain that may
return a view of it (this.me()).An object cannot be used before it is fully constructed (E08061).
A single contract/partiality obligation found in a construct body, tagged with the analysis (if
any) that discharges it (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §2.1).
Layer 1 of the Symbolic/Contract Scanner — the every-build obligation census
(docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §2).
The taxonomy of contract/partiality obligations the census counts, from what already exists in the
language and analysis (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §2.2).
Compiler self-verification directive (NOT an end-user feature) asserting the obligation census
(docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §4) computed the expected tally for a
construct.
Checks any
@Obligations directives in the parsed module against the squirrelled obligation
census tally (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §4).What
occurrence - an identifier the compiler bound to a symbol - does to the object it names; empty when
it only reads it, or stores a new object in it.The digits of the octal escape whose backslash is at the given offset: one to three octal digits, limited to
\377 (255).Public facade for on-demand IR generation from the IDE.
THE rewrite of one line by a text rule, with its note
line N: 'was' -> 'now' - why.Record to group operand evaluation instructions with the resulting operand name.
THE operation-body locator (IR tidy plan DFN-1): where, in the parse tree, the body of one of a construct's methods
or operators is written.
THE operation-body skeleton (IR tidy W3.4, OPS-9): what a callable's body is made of, emitted by
OperationBodyPlan.generate(IRInstructionBuilder) in the one order every callable has - use it, never another hand-rolled body.A plan's parts; any part not given is empty, and there is no body scope unless
OperationBodyPlan.Builder.inBodyScope(DebugInfo) is called.One part of a body: adds its instructions through the builder.
Used for resolving operation calls on aggregates, which can include properties that are delegates to functions.
THE checks every method and operator declaration gets - call this, never the rules one by one
(front-end rationalisation F12/D5, Steve 2026-10-03).
THE search of an aggregate's method and operator declarations for the one whose recorded symbol matches - use this
(through
OperationBodyLocator, THE operation-body locator), never a
third copy of the two loops.A declaration that matched.
Deals with the generation of the IR for OperationDetails.
THE findings of a per-body ownership check over every operation of a construct, each as
"operation: problem", in operation order; an operation with no body has none.An operation on some sort on a Construct.
THE test of "is this assignment token a plain one" -
:=, =, : or :=?: a simple
object-pointer assignment, not a deep or mutating operator (+=, :~:, :^:, :=:).An operator declaration written in another order than the grammar's
[override|default] operator <symbol>
[as] [pure] [abstract] (operatorDeclaration).THE
OperatorMap-derived call metadata of a declared EK9 operator - the second honest source of
SynthesisedCallMetaData, used when the target type carries no resolvable member for the callee.THE honest metadata for a callee with NO target symbol available at all - the
OperatorMap declaration
(OperatorDeclarationMetaData) where the name is a declared EK9 operator, otherwise null: no clause.THE place a missing operator belongs when NOTHING above an aggregate declares it (Q4, Steve 2026-10-08): the
nearest super class that HAS fields of its own - the root of the data decides whether its fields are exposed (R4) -
or, when no super class has fields, the topmost one (the hierarchy's root below
Any).Holds some high level details about an operator.
Designed to gather aspect of operator population.
E08096: an in-place operator applied to a value the compiler is SURE is unset, where the operator is one that
keeps an unset value unset -
text <- String() then text += "more", or count <- Integer()
then count++.Detects variable names that shadow operator keywords (E11032).
Enhanced mapping of EK9 operators to their metadata and method names.
THE type that declares an operator - its OWNER, which a generated super call names (Contract 19,
NearestOperatorAbove).Maps EK9 operators to their syntactic position (prefix vs suffix/postfix).
THE correction of a custom operator's
as pure in source text the Oracle is about to
write - use this, do not re-derive the rule from a list of symbols.The corrected text plus one note per line changed;
notes empty means nothing moved.THE operator an in-place operator resolves to on a receiver type: the search phase 3 made when it resolved it
(
LhsAndRhsAssignmentOrError, StatementOrError) - the operator by its written name, with the
argument's type when it has one.THE move of a prefix or suffix operator to its own side of a simple operand -
names$ to
$names, ?stored to stored? - for every editing tool.The rewritten text and one note per rewrite;
notes empty means nothing moved.THE shared "resolve the callee method on its target type" step for phase-7 synthesised call sites.
Provides a common set of operations for checking operators.
Defines the optimization levels available in the EK9 compiler.
🛑 THE ONE question "can this
<=> (and the ordering built on it) be used?" (D55, D58, D62, D63, D71) -
OrderingAvailability.orderingSurvives(MethodSymbol, ISymbol), OrderingAvailability.bareOrderingRetracted(IAggregateSymbol, ISymbol), OrderingAvailability.withdrawnOrdering(IAggregateSymbol, ISymbol) and
OrderingAvailability.isUnavailableOrdering(MethodSymbol, ISymbol) with the readings built on them.THE body an ordering step is written in (D91 step 4): the named method or function around the code being resolved -
a dynamic function inside it is part of it - and whether it is its generic's own hand-written self-comparison
<=>, the only body whose steps are followed.The body, and whether it is its generic's own hand-written
<=>.The per-source half of
OrderingTotality (E07188): for every method, operator and function that returns an
Integer, finds where the returning variable can get its value and records the PARTIAL sources - an unset
Integer(), a <=> of a partial type, a call of another callable (decided later, once every source
has been walked).THE compile-time check that a hand-written
<=> orders every two SET values of its type (E07188; Steve,
2026-10-21, sameness stock-take 4.4: "This is a closed system and we already have code that detects the subtypes").A function used as an ordering where it is not declared one.
What makes one callable's Integer result partial, where the walk found it.
THE orderings of types built on any of these conceptual parameters that the generic's body uses, each once (a type
built on several parameters is recorded on each) - what
NoteOrderingUse and NoteNaturalOrderQueue
recorded, judged in phase4/ParameterisedTypeOrError where the parameters are replaced.THE position-independent identity for a dynamic construct: its index among the constructs of the
same KIND in the same source file, in document order.
Detects assertion statements that are not reachable from any @Test program.
Operating System support and generic stuff for directories and files.
THE first of several operators that is a different spelling of the same runtime operator as another (D59,
SameRuntimeOperator).Only use when code being checked prohibits use in outer generic context.
((base)) is base: climb the parentheses.Returns File Object in the appropriate location for jvm output.
Creates the File Object in the appropriate location for llvm output.
Given a TargetArchitecture from the configFlags, this function will provide a function that
NAMES the File for a Construct.
What a stream statement does to an output channel (
IsOutputChannel, e.g.THE decision of which
OutputStep a termination gives its sink: > into an output channel clears,
>> appends, anything that is not a channel (a collection, a fold, a user type) gets none.Enhanced visitor that uses specialized ASM generators to produce JVM bytecode for IR constructs.
The visitor that produces llvm IR text, requires further processing for creation of '.o' files for a Construct.
Locates the appropriate IR node visitor for the appropriate target architecture.
The declarations a call through which may run
callable: those it overrides, or its super function - THE
"what may a call through this declaration run" of the dispatch union, held by both RETAINS derivations (the
returns one, ReceiverInteriorReturns, and the callee-keep one, CloseableArgumentKeeping), so what an
override RETURNS and what it KEEPS are unioned over the same set.THE parent declarations a method overrides - hold one and apply it, do not re-derive it.
THE super's dispatcher entry point that a sub-type's entry point overrides: the super's effective dispatcher method
with exactly the same signature - what a synthesised
InheritedDispatcher entry point calls.THE inherited sameness signatures a type with its own sameness OVERRIDES (D24 rule 3; N07 - the object decides,
never the reference): for each of
== and <=> the type declares taking exactly itself, every
same-named comparison above it on its super CLASS chain (AllOperatorsAbove) that takes a type the owner is
assignable to and that the owner does not declare itself (OwnOperatorTaking).Checks for both abstract and override.
THE message prefix naming an own declaration and the other declaration it is paired with (an override and what
it overrides, a dispatcher handler and its entry point):
'own' and 'other' <location>:.The no-argument close operator in the type's own scope, whatever it is (abstract, proxy or written).
The captures a dynamic class owns: each one PRE_IR_CHECKS marked as a fresh closeable (R-E).
THE declaration of a variable that owns the temporaries its initialiser makes (OPS-6): a returning variable
(
<- rtn as String: String()) and a property (name as String: String()) are declared by no block
statement, so the declaration itself closes the closeable temporaries its initialiser creates
(StatementOwnedCloseables).THE borrow rule of the ownership form, V-I (EK9_IR_OWNERSHIP_MODEL.md §8, EK9_IR_OWNERSHIP_STAGE4_DESIGN.md §6):
no borrowed value is used after its source may have let it go.
The ownership form of the IR (EK9_IR_OWNERSHIP_MODEL.md §10):
OWN, DROP, DROP_AT_EXIT,
SLOT_DECLARE, SLOT_ASSIGN, FIELD_ASSIGN.How a slot or field assignment takes its value.
THE ownership lowering (EK9_IR_OWNERSHIP_MODEL.md §11.1): rewrites every ownership-form instruction into today's
opcodes, so both back ends keep consuming exactly what they consume now.
THE per-path rules of the ownership form (EK9_IR_OWNERSHIP_STAGE4_DESIGN.md): V-A - every OWNED value is consumed
exactly once on every path to a normal exit and to every exceptional exit - and V-J - a path that ends in a Panic
owes nothing.
THE value-ownership statements of IR generation (D-O11, EK9_IR_OWNERSHIP_STAGE1_DESIGN.md §11) - hold one and call
it, never build an
OwnershipInstr by hand: each method states ONE ownership fact where a value is made,
declared, stored or handed over, in the ownership form (OWN, DROP_AT_EXIT, SLOT_DECLARE,
SLOT_ASSIGN, FIELD_ASSIGN).THE local rules of the ownership form (EK9_IR_OWNERSHIP_MODEL.md §11.2; stage-1 design §7) - the ones that need
only the structured lists, not a per-path analysis:
V-C only an OWNED value is consumed, not twice in one straight list, and a value MOVED on a path (by
DROP or a [consume] assignment) is not used after it on that path - its count now belongs to
where it went, which may release it (Swift's use-after-move rule);
V-D a CAST forwards its operand's kind, and consumes an OWNED operand;
V-E the arms of a chain hand back values of one kind;
V-F DROP_AT_EXIT names a scope open in the current activation (the A11 rule);
V-G a slot's owner is open (or the CALLER or OBJECT) where the slot is first filled - its
declaration, or its first [init] assignment when it is declared before its owner is entered (Contract 3:
a try's resources and its region's first failure) - a slot is declared once per activation, and a slot is
never itself dropped;
V-H a consumed argument is consumed by its call; an unmanaged result carries no count;
V-M the IR is in the ownership form ONLY: RETAIN, RELEASE, RELEASE_FIELD and
SCOPE_REGISTER are OwnershipLowering's output, never phase 7's, and REFERENCE /
TYPED_REFERENCE declares only a compiler temporary that holds no count of its own - every named variable
is a SLOT_DECLARE with its owner (stage 3).
THE error listener that owns a symbol: the listener of the source file that DECLARES it.
The owner's own non-abstract operator of one name taking exactly that one type, if any - what
OverriddenSamenessSignatures asks of each inherited signature.THE "is this a property of the object whose code is running?" - use it, never re-derive it.
The property of this object an assignment statement assigns (
me: ... or this.me: ...), if any.Extracts capability data from a package block and stores as squirrelled data on the Package symbol.
An immutable snapshot of EK9 main package directives.
THE rule for what a 'defines package' block may hold (E06260 PACKAGE_PROPERTY_INVALID): which property NAMES a
package defines, and the SHAPE each one's value must have; which properties it MUST have ('version' E06262,
'description' E06261 - D16, Steve 2026-10-19); and that each is set once (E50050, in the package's own words).
Reports what is wrong with a 'defines package' block, using the same rule (
PackageProperties) and message
as the CLI's package pre-pass - which only the CLI runs, so without this the LSP and MCP tools accepted
name <- "myLib" and tags <- "x", and a package with no description or version:
a property a package does not define, or a value not of the shape it requires (E06260);
a property set twice (E50050, in the package's own words - reported before the property is defined, so the
generic duplicate-variable error on the same line is not the one kept);
no 'version' (E06262) or no 'description' (E06261) - D16, Steve 2026-10-19.
Where a package property's problem (
PackageProperties) is reported: an unusable NAME on the name, a value
of the wrong shape on its value (or on the name when the value is not an expression).Focus on the responsibility of packaging.
SINGLE THREADED
Take the final optimised generated code and package it in to some type of release vessel.
SINGLE THREADED
Complete any post-processing required.
THE "
at file:line:col" suffix appended to a Panic message (PanicThrowInstrs), or "" when
the location is unknown - hold one and use it.THE single-source-of-truth for emitting the "construct and throw an
org.ek9.lang::Panic"
IR sequence - EK9's one representation of an uncatchable fatal invariant breach.Represents details about a program parameter for the PROGRAM_ENTRY_POINT_BLOCK.
The
HttpAccess kind of this parameter: what was stored (StoredHttpAccess), else PATH - the kind an
unqualified service parameter is assumed to be (see HttpAccessDefaulting), so a check that runs without
having asked for the default first still gets the answer the default would have given.THE index of the parameter a RETAINS rule names (
parameterName) in callee's declared parameters;
-1 when it declares none of that name.THE strict test:
target is a parameterisation of EXACTLY this generic - not a sub type or a super type
of it - and so the parameterisation itself (List of String for the generic List), else empty.Every parameterisation of a generic that exists in the program, so FE77 can apply a generic's construction steps
to each concrete parameterisation and find the concrete type a substituted one names.
THE E06210 repair for a generic constructed with its parentheses AFTER the type arguments -
List of
String(), Dict of (String, Integer)(), echo of Integer() - which has ONE reading,
List() of String (Steve, 2026-10-08, GENERIC CONSTRUCTION b).The rewritten text and one note per rewrite;
notes empty means nothing moved.Create a new parameterised symbol from a generic type and a set of type arguments.
To be used when trying to define/resolve a parameterised type.
Does the detailed for of checking a specific possible generic symbol.
Given a parent and a dependent generic type, check that all parameters have been provided with suitable
arguments, so that the Parameterized type can be used.
This will just create an Aggregate/Function 'parameterized type' of the 'generic type' with the 'type arguments'
But note it will have not - repeat NOT have - traversed the 'generic type' and cloned over the methods and
altered all the 'T', 'K', 'V' - 'type parameters' for each of the 'type arguments'
There is a separate function (TypeSubstitution) that does that.
Processes all parameterized types in a module to detect their monomorphization scenario
and generate appropriate IR.
Processes method call parameters to determine if promotion is required.
Used for checking parameter list types match.
Parameters declared the way other languages declare them (was
ParameterDeclarations.inParentheses):
add(name as String) / label(first: String, last: String) - Java's parameter list on a DECLARATION
line.Checks the number and types of the two sets of parameter list match exactly.
While we don't add these in the scoped structures when compiling.
The close of the nearest super CLASS that has one, when it is not abstract.
Gets the immediate parent directory of the file.
Once we have parsed a module (source file) we need to keep track of the results.
Used to hold just the transient data that will be used by listeners and visitors and
SymbolsAndScopes.
Creates the lexer and parser and plugs in the listners.
To be used to construct a parser, with a lexer.
The parse failures that have MORE than one reading - so no rule rewrites them, but the caller is told the readings
(the SUGGEST tier of
docs/tooling/EK9_TOOLING_IMPROVEMENT_METHOD.md):
a % b - EK9 has mod (the result takes the divisor's sign) and rem (Java's %,
the dividend's sign); which one is meant is the writer's to say;
assert x, "message" - EK9's assert takes no message; dropping it loses what it said;
$name in a backtick String - ${name} interpolates, \$ is a literal dollar;
a misspelt keyword (esle, defins) - correcting it changes which code runs, and a word one edit
from a keyword is just as often a name (heads, sorts);
a block header with nothing indented under it - how far its body extends is a choice.
Find the ISymbol at a given token position by traversing the parse tree.
Can be MULTI THREADED.
Parses a bit of EK9 source as an
instructionBlock — a contiguous run
of block statements (the body of a method / function / loop / branch).The parse outcome: the block context (may be partial when there are errors)
and the error listener so callers can gate on a clean parse.
Just processes a bit of some EK9 source for a simple or generic type def, to return the context.
THE answer to "is this type's
<=> PARTIAL?" - unset for some pair of SET values of the type - given as the
wording of why, to follow "'X' ...", or empty when it is total (so "is partial" is apply(...).isPresent()).The relational path condition accumulated along a control-flow path — an orthogonal structure that
sits beside
ConstraintState and records facts between symbolic term names
(e.g.A single relational fact between two term names, e.g.
THE encoder, the inverse of
SourceFileUriToPath: a filesystem path as the compiler's general
source identifier, the file: URI every CompilableSource, ErrorListener and
source token carries, and the key under which LSP diagnostics are published.When searching for methods, this will be a percentage result of how well a method matched.
Checks, mechanically, that the compiler's phase boundaries mean what they say.
Abstract concept of a supplier of phases for a compilation.
Process the stream pipeline part, ensuring that it can be resolved.
What runs inside a pipeline scope (
StreamPipelineMachinery.withPipelineScope(List, boolean, String, DebugInfo, List, PipelineScopeBody)): given the scope, the
element slot declared in it and the stages' pre-loop state (already emitted), it emits the pipeline's loop or
drain.Per-stage-boundary item variable plan.
Symbolic identity for a
MutexLock parameter whose underlying object
is unknown until resolved at a specific call site.A golden stores what varies from run to run as a
{{Placeholder}}; a reader of plain text sees it as a
variable (<n>ms, <date>).Where EK9 needs a String it can read at compile time - a constant, a constraint, a text's language, a service
parameter's name - only a plain
"..." literal will do (E07902).THE value of a plain
"..." String literal - the only String form EK9 reads at compile time: a constant, a
constraint, a text's language, a service parameter's name.SINGLE THREADED
If the developer has employed any sort of 'native' plugin, then it will have been referenced
and trusted at earlier phases.
SINGLE THREADED
No-op at this stage.
THE rule for a copy (
:=:) through a super-typed reference (Steve, Q5b, 2026-10-08) - its names here, its
parts in support.copy: SelfCopy, IsCopyOwner, HasGeneratedSelfCopy,
IsGeneratedCopy, CopyNeedsRuntimeCheck, NeedsCopyAccepts and InheritedCopySignatures.Creates the DETACHED method symbols a copy owner's IR carries for a copy through a super-typed reference
(
PolymorphicCopy, Q5b): the generated _copyAccepts(target as Any) <- Boolean and one
:=: override per inherited :=:(Super) signature.Links a supertype method to the overrides that can actually run, so a call made through an
abstract/base declaration reaches the implementing body.
For Constrained Types, focus on checking it is possible to constrain the type and if so then
clones the appropriate methods/operators over and alters the types as appropriate.
THE text of a path with
/ between its names on every platform - hold one and use it; never
path.toString() (the platform's separator, \ on Windows) nor a private
.replace('\\', '/') for a path that is shown or compared as text.You may think why this mapping.
Just holds a simple set of lists with the appropriate type arguments and their corresponding parameterizing
parameters.
Used as a base for a range of constructs that can be expressions.
Added as a common symbol type for both Functions and Aggregates that could possibly be
generic in nature and also be a parameterised type.
Just uses the name of a method in the search, to get a list of all possible method name.
What the bare-default and sameness post-passes at the end of EXPLICIT_TYPE_SYMBOL_DEFINITION act on, gathered in
ONE walk per source rather than one walk each.
A bare 'default operator' and the class, record, component or dynamic class that declares it.
SINGLE THREADED
Once full resolution has completed, additional checks need to be made.
Detects string concatenation chains with 3 or more parts and recommends
string interpolation instead (E11068).
THE single operand of a prefix expression (
IsPrefixExpression) or of word not
(IsWordNot), as written - parentheses included (NegatedOperandOf looks through them).THE single definition of "can this control-flow pre-flow skip the construct body?".
THE operator token of a pre-flow (
<-, :=?, := ...): what PreFlowCanSkipBody
classifies, and the error location of a check on the guard itself.Checks that the pre-flow expressions are valid.
At this point all templates should be present and all symbols resolved.
Designed to do additional logic checks once everything has been resolved.
THE handling of a composite's nested list that may be absent (null): an absent list is not listed
(
PresentNestedLists.add(List, String, List, CompositeInstr.Activation), for CompositeInstr.nestedLists()) and stays absent when the lists are rewritten
(PresentNestedLists.rewritten(List, UnaryOperator), for CompositeInstr.withNestedLists(UnaryOperator)).THE index of the nearest line before
index with content, or -1 (was SourceLines.previousContent).Ensures that 'primary' is now resolved and 'typed' or a not resolved error.
Generates IR instructions for primary references (THIS and SUPER keywords).
Processing details for primary reference generation (THIS and SUPER keywords).
CONCERN: Boolean primitive extraction from EK9 Boolean objects.
Specialized ASM generator for PrimitiveLiteralInstr processing.
IR instruction for loading primitive literal values (int, boolean, java.lang.String).
THE single builder for the "wrap a primitive/Java value into its EK9 object via a static
_of factory" IR sequence — Integer._of(int), String._of(java.lang.String),
Boolean._of(boolean) and the like.Checks that reveal() on Sensitive is only called from within a class or trait that is Privileged.
To be used in EK9 source code to assert that the Oracle query at a specific line
produces the expected JSON output.
Identifies which Oracle extractor a @Probe directive should validate against.
If any of its OWN methods is marked as 'dispatcher' then mark this class as a 'dispatcher'.
Checks what only a METHOD declaration can get wrong, in every method context: 'default' on a method that is not a
constructor, the access modifier, and the constructor rules.
Configures a dynamic class in terms of settings its super and configured traits.
Deals with handling any returning values in a dynamic function.
Configures the dynamic function with it's 'super', but also checks that the super can be used in the
way the EK9 source code has been defined.
Configures a function's 'super' in the most appropriate way.
Checks in the context to see if a returning variableDeclaration or a body is defined.
Designed to enable a developer to wrap lots of different type of
processing and expose any exceptions.
Constructs like methods and functions may or may not always return a value.
Configures the trait declaration and completes a number of checks on that trait once configured.
Check trait specifics on constructors/methods/operators, Allowing missing body but marking as abstract.
Adds various synthetic methods to type defined by the EK9 developer.
Checks for inferred declarations of variables in various contexts.
Checks on whether the '?' can be used as a modifier
then check the parent of this context.
Deals with variable only declarations.
Processes a variable declaration - attempts to resolve the variable type.
Deals with checking the 'while' or 'do/while control variable in the statement/expression.
Detects assertion statements that are reachable from non-test program entry points.
Specialized ASM generator for ProfilingEntryInstr processing.
Specialized IR instruction for profiling function entry (PROFILING_ENTRY).
Specialized ASM generator for ProfilingExitInstr processing.
Specialized IR instruction for profiling function exit (PROFILING_EXIT).
Check if this type being supplied to the test can be used as a program argument.
A program can only accept specific types of arguments to it.
THE places in source where code of the program's own may run (D66) - what is not
pure and not a concrete
built-in - and what each can reach (Reach).One place where code of the program's own may run: what it reaches, and whether it changes the names it is given
in place (an in-place write, an iteration) rather than handing them to a call.
Represents details about an EK9 program for the PROGRAM_ENTRY_POINT_BLOCK.
Creates the appropriate IR Construct for an Aggregate of type 'program'.
IR instruction containing all discovered programs and their metadata.
Visitor interface for specialized handling of ProgramEntryPointInstr.
Validates that program HTTP wiring is consistent with application service registrations.
THE reader of the licence files a program carries, in either form: a program jar's
ProgramLicences.JAR_DIRECTORY entries or a native executable's embedded copy
(EmbeddedLicenceFiles).THE licence files every program EK9 compiles carries with it (licence decision D-L1, docs/legal): the runtime's
Apache-2.0 licence, the runtime's NOTICE, and the notices of the third-party code the program contains.
One licence file: its name (one of
ProgramLicences.FILE_NAMES) and its bytes.Extracts metadata from EK9 program symbols to create ProgramDetails objects
for the PROGRAM_ENTRY_POINT_BLOCK.
THE reading of a program's body - use it, never a private
"_main" test.Checks if there is any application associated with the program.
THE
PublishedValues of a whole program (S2b): the registered-type fact by name - every aggregate the program
knows, core ones included (a List of String a registered component holds is registered; one nothing
published reaches is not), and every construct in its IR, read through IsRegisteredType - failing closed for
a name it does not know; and CalleeOfCall over the program's constructs and module-level symbols (a
parameterisation such as _List_<digest> is found there, not by a search for its name), then a fully
qualified search.A program can only return an Integer (exit code).
Represents a variable that has been promoted using the #^ operator.
CONCERN: Type promotion call generation using the #^ operator.
The
#^ operator itself that this 'from' type promotes through, or empty if it has none - for a caller that
must read the operator, not only its type (what its RETAINS say it does with the object it is called on: the
closeable ownership decision, where an argument reaching a callee as its promotion is not the argument itself).Parameters for type promotion invocation using the #^ operator.
Result of parameter promotion processing.
The single type this 'from' type promotes to via its
#^ operator (PromotionOperator's return type),
or empty if it has none.THE reading of a constructor's
CommonValues.LEAVES_PROPERTIES_UNSET mark: the
names of the properties (declared without a value) it leaves unset, following its this(...) chain, as a message
shows them; empty when it sets them all.The names of the properties a constructor leaves unset, as a set; empty when it sets them all.
The properties a constructor body stores 'this' into - directly (
me: this, StoredProperty) or in a
dynamic function or class it gives them (child :=? (owner: this) ..., CapturedInto) - not counting
code that runs later (a dynamic function's body, a dynamic class's methods), where 'this' is a different object or
the construction is over.THE parse half of "is this a property of the object whose code is running?" (
OwnProperty is the symbol
half): the form this.prop (or alias.prop when the caller's receiver test accepts the start), one
step from the receiver, never through a further property or a call, which reach another object.Marks the types whose objects can reach themselves through their properties, so phase 7 guards only THEIR
generated operators against a cyclic object graph (Steve, 2026-10-05: the hybrid - a compile error on a
potentially cyclic type would reject every legitimate tree, a runtime guard on every type would tax the hottest
operator in the language).
Used for resolving and recoding of fields on specific types.
An aggregate's own property fields, in declaration order, as an unmodifiable list.
THE answer to "is this node inside a property's initialiser, and which properties of that type are set by then?"
Use this wherever a check depends on a property initialiser - do not re-walk the tree for it.
THE instance initialisation of a type's properties, in declaration order - the body of its
_i_init.THE property-type graph: which types an object of a given type can reach through its properties.
The three kinds of node - see the class javadoc.
One node, keyed by kind and fully qualified type name (value equality, as the shared Tarjan requires).
The size of the part of the graph that was reached - what the linearity test asserts on.
The two whole-program facts the graph needs: the concrete subtypes of a type, and every aggregate.
The variable an
if block's pre-flow declares, when that block is skipped ONLY because the variable is unset
(E08270): a <- guard that is the whole condition, and not a Boolean truth guard (BooleanTruthGuard,
which also skips a set false).THE reading of whether something may change the OBJECT an Optional / Result / Iterator variable refers to, so that
a proof that its
get(), ok(), error() or next() is safe (E08030) no longer holds:
D66 ("a call that is not pure forgets what it can reach", Steve 2026-10-21) applied to the safe-access proofs.THE rule of which values an instruction publishes (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S2 and S2b) - what
PublishPlacement places and PublishVerifier (V-P) demands exactly:
a STATIC_FIELD_ASSIGN into _Application - an application's _prepare storing a
registration runtime threads can reach, a [registered] type (REGISTRY; S2c - one only the program's own
thread uses stays mortal); any other static store - an enumeration's values, a cycle-guard owner, all in a
_c_init (CONSTANT);
a call that hands values to runtime threads (HandsValuesToRuntimeThreads, HANDLER);
the store barrier (STORE, naming the holder the value goes into): a FIELD_ASSIGN into a field declared
by a type a published value may reach, or a SLOT_ASSIGN this.<property> in an operation of a
[registered] construct - except into this while it is being constructed (a constructor,
_i_init, _c_init: E08250 keeps this from escaping, so nothing published holds it yet); and
an argument a call may KEEP in its receiver or in another argument (KeptArgumentHolders, from the callee's
RETAINS) when that holder's type is one a published value may reach - items += line on a registered
component's List (review 2026-11-02, M2) - as well as the operand of a :=:, :~: or :^: into
such a receiver, which shares the operand's contents.
"A type a published value may reach" is the [registered] fact by name, failing closed: a type the program
does not know to be unreached is reached.Where an instruction is: in an operation of a registered construct or not, and while its object is still being
constructed or not (a constructor,
_i_init, _c_init).PUBLISH value, reason[, holder]: from here on the value, and everything it reaches, is shared with runtime
threads for as long as the program runs (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S2 and S2b; re-investigation
F1).Why a value is published - which fact allows it.
THE placement of
PUBLISH (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S2): an IR_OPTIMISATION pass after
SafePointPlacement, over the ownership form, before the lowering.V-P (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S2 and S2b), two checks over every operation:
exact: each instruction is immediately preceded by exactly the
PUBLISHes
PublishedValues says, in order, holders included; and every PUBLISH is one of those.THE heads that bound the pull of a loop over
stages (StreamDemand, decision 10 rule B): every
head before the first stage that ends the demand segment (EndsDemandSegment), in pipeline order.For doing pure checks on method and functions.
Checks if the pure modifier has been used correctly on methods and functions.
Just check that with in the current 'context' - if pure that the processing call is pure.
THE push of an int constant onto the operand stack using the most compact instruction: ICONST_M1..ICONST_5 for
-1..5, BIPUSH for a byte, SIPUSH for a short, otherwise LDC - the ladder several generators had duplicated.
THE hint for a QUALIFIED name 'M::X' that did not resolve, when the X the user probably meant is only IMPORTED
with 'references' - by module M, or by the module the name is used in.
Central home for the code-quality metric limits that are SHARED across more than one check in this
phase.
Generates IR instructions for question operator (?) using unified SWITCH_CHAIN_BLOCK.
The two
? spellings beside QuestionMarkWithValue's Type?: value that never parse:
<- rtn as String?? - a declaration's ? written twice (a tool rendering '<- rtn as
T?' around a T? it was given, or a model doing the same): one ? is meant.THE repair of a declaration written with a
? AND a value - <- rtn as String?: String()
becomes <- rtn as String: String() - for every editing tool.The rewritten text and one note per rewrite;
notes empty means nothing moved.Specialized generator for EK9 question operator (?).
THE detection of a construction that needs a natural order (
NaturalOrderQueue, D63): the element type of
the queue a written call constructs, when the call resolved to a constructor of a parameterisation of
PriorityQueue (QueueElementType) and it is not directly the receiver of .withComparator(...).THE element type of a queue type, when it is a parameterisation of
PriorityQueue - recognised through the
symbol (Ek9Types.ek9PriorityQueue()), never by name (NaturalOrderQueue).Single source of truth for "Did you mean?" / quick-fix suggestions across the
EK9 compiler, IDE, and AI tooling.
THE inline "Did you mean: X, Y, Z?" text of an error's suggestions, used by
ErrorListener.ErrorDetails.toString() (CLI classic mode): the QuickFixSuggestionExtractor list,
each as its display text, joined.THE quoting of a line for a repair's note: stripped, in single quotes (was
SourceLines.quoted).Shared helper for range iteration logic used by both for-range loops and stream for-range sources.
Parameters for case constructor (AscendingCase or DescendingCase).
Helper record to pass initialization data between methods.
A for-range whose start, end and step are all KNOWN when the program is compiled, and whose step can never take
the counter from the start to the end, is an error - E08276 (Steve, D49 compile-time half, 2026-10-21).
Checks the Range and ensures that there a Symbol recorded against that context.
THE decision of which for-range counter types get a run-time PROGRESS CHECK (Steve, 2026-10-21): after each step
the counter must have moved toward the end - ascending
new <=> previous > 0, descending < 0 - and
when it did not (it wrapped, stayed equal, or the comparison is unset) the range ends.D66 gap (verifier, 2026-10-21): does a
for range over values of this type run code of the program's own?
The range builds its counter and each loop value with the type's copy constructor and moves the counter with
++/-- (or +=/-= by a step), comparing with <=>: a program type with any
of those not pure runs that code, which may change what it can reach (a copy shares its fields).Represents a variable known to be within a numeric range [lo, hi].
THE RAW
javap -c -p -l -v output for some class bytes, with no normalization at all.What a call can REACH (D66, Steve 2026-10-21): the objects it is given.
THE "what does running this callable construct, and what does that construction run with no edge of its own" for
the dependency-injection checks that walk
CallGraph.getReachableIncludingReferences(Set, Function): DI completeness
(ReachableInjectionsOrError, E08210/E08220) and DI ordering (TransitiveInjectionOrderingOrError,
E08200).THE injections that can run when the given callables run - transitively, through the phase-5 call graph: an
injection (
name as T!) in a body the roots reach, or a property injection of a type they construct (a
property's injection belongs to its type and runs wherever the type is constructed).THE dependency-injection completeness check for programs (E08220, E08210): every injection that can run when a
program runs must be satisfiable - the program needs an application, and that application must register every
injected abstract component the program can reach.
The objects an expression given to a call (or written into an object, or iterated) gives it: a name,
this,
what a call that makes one, a list, a Dict, a coalescing operator or a ternary holds; any other expression builds a
new value from its operands.True when the receiver of the final step of an object-access chain (
ObjectAccessFinalStep) is only reached
by CALLING something - the chain starts with a call (getHolder().name, Holder().name) or a step
before the last is a call (keeper.holder().name, this.holder().name).THE reading of what a call that may run the program's own code can change:
everything reachable from
Reach, which the value tracker turns into what it forgets
(ValueTrackingAnalyzer.recordCallThatMayChange).THE reading of an in-place write as a call (D66, Steve 2026-10-21): when the operator that makes it is the
program's own code (
InPlaceWriteRunsProgramCode), it is a call that is not pure, given the object written
and whatever the right-hand side gives it (other -= amount), or - for a stream target - every element of
the stream.What a
for loop over iterated can reach (D66, the same reading as ReachOfCall gives a call):
the value iterated - a name, this, or something no name is given to - and what it is made from.The
Reach being gathered over one call, loop or in-place write, with the recorded-symbol lookup of the
phase asking: the walk of ReachedByExpression adds to it.THE incremental readability (ARI) scorer - feed it every token exactly once, in order,
then ask for the score.
The friendly name of a type as the symbol gives it, with a compiler-made name made readable (D65): the form a
generated refusal message uses for the types it names -
cls for a dynamic class, never its digest.THE name a GENERATED operator shows for a type in its text (D65, Contract 21 rule 5): a parameterised type by its
friendly name (
Holder of String), every other type by its simple name, and in either case a compiler-made
name by what FriendlyInternalName gives it - a dynamic class is cls, never its
_Class_<digest>.Item 5, step 2: DERIVE, for user methods and operators, the RETAINS marker the built-ins declare - so a user
method that hands back one of its own properties follows the same rule as
JSON.get.The parameters
callee stores its receiver INTO by an explicit rule (items <- receiver, declared or
derived): the names of the arguments that end up holding the object it is called on.The OBJECT that bears a field-rooted MutexLock at an enter site — i.e.
F1 (Steve, 2026-10-07): a record exists only to carry data, so a CONCRETE record with no fields, counting inherited
ones, is an error (E07237).
Creates the appropriate IR Construct for a record declaration.
THE declarations in a fragment of the COMPILED tree, by the symbols the compiler recorded - the declaration half
of
RecordedSymbols' identity walk.THE symbol-identity walk over a parse-tree fragment for the compiler and the
mcp.oracle tools - use
this (moved down from compiler-services with SymbolWrites, 2026-10-04), never a
by-NAME walk (a regex over body text, getText().equals(name) on identifier nodes, a set of names).One identifier occurrence the compiler bound to a symbol.
Triggers the expression processing with the given details.
Record the components on a circular injection chain (E08190) on the application, for the ordering checks that run
after the E08190 check - the write half of
InjectionCycles, whose of reads them back (never a second
cycle detector).THE encoding of a measured quality metric (with
MetricSymbolOf and MetricLimitCheck, the steps of
every Acceptable*OrError check): squirrel the integer on the symbol, under the one key this instance is
made for, as decimal text through SmallIntStrings.Records an ordering use on each conceptual parameter the type is built on (
TypeParametersUnder) - the
shared step of NoteOrderingUse and NoteNaturalOrderQueue; read back by OrderingUsesOf.THE E50050 repair - a name declared a second time with
<- - where the second <- has ONE
reading, for every editing tool.A second declaration as the E50050 message names it - THE reading of that message for this repair and
for the MCP
RedeclarationHint: the name, the line declaring it again, the line that declared it first.The rewritten text and one note per rewrite;
notes empty means nothing moved.Detects comparisons of a Boolean expression with a Boolean literal (E08084).
THE matrix of the redundant-condition checks - the set check (
x?, E08088/E08089) and the empty check
(x empty, E08092/E08093) - deciding which error a provable answer earns (F29, 2026-10-20: it was written
out twice).Detects empty checks that are always true or always false based on data flow analysis (E08092/E08093).
Detects isSet checks that are always true or always false based on data flow analysis (E08088/E08089).
Detects when an override method/operator body is textually identical to the super (E11044).
THE E02090 repair - a trait listed beside another listed trait that already has it (
with trait of
LoudSpeaker, Speaker where LoudSpeaker with trait of Speaker) - which has ONE reading: delete the
redundant name (Steve, 2026-10-11).The rewritten text and one note per rewrite;
notes empty means nothing moved.THE reading of a statement that makes a local variable (never a property) refer to the SAME
object an expression evaluates to - a reference copy (an alias), never a value copy.
THE reading of the
ReferenceAssignment (an alias of a LOCAL, never a property) a declaration or an
assignment statement makes, if it makes one.SINGLE THREADED - because we only want one reference shorthand for an item.
THE void-returning constructor descriptor over reference-type parameters, given their JVM internal names:
(LfirstParam;LrestParam0;...)V.Every reference an instruction stores INTO an object - the edges a published object could gain - classified by
OPCODE, for V-P's audit (
PublishVerifier, review 2026-11-02 M4).Checks that references within a references block are in alphabetical order.
Antlr listener for the references phase.
Which pass this walk performs.
Utility to determine if an ISymbol represents a reference-counted type
that should be included in the traceableFields list during initial IR generation.
Rather than just check if the actual ISymbols are the same, this code checks if two
symbols actually refer to the same source token from the same source file.
THE check of what a 'register' statement registers (decision 10, 2026-10-07).
THE view of what an application registers for dependency injection: the fully-qualified interface names of every
component registration in the list.
THE registered-type fact (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S2; re-investigation F2): a user type is
REGISTERED when a value of it can be reached from what is published for the life of the program - the
registrations runtime threads can reach (S2c: every service, and every component code a runtime thread runs can
inject -
ReachableInjections from the concurrent entry points; with the type it is registered as and its
aspects - the proxy holds each aspect and runs its advice on whichever thread calls the component; review
2026-11-02 H1) and
every handler handed to runtime threads by TCP.accept, acceptUntilComplete,
HTTP.serveUntilComplete or Signals.register (the handler itself and what it captures) - through
SharedTypeClosure, which here never enters a MutexLock's payload: the payload is its own domain
(T11), never published.Holds the data from a 'register' statement within an application block.
Stores registration data on the application symbol for both component and service registrations.
E01095 (Steve, 2026-10-21, sameness wave 2, section 4.9 b1): the comparison coalescing operators
<=? and
>=? were removed.THE question "has every path through the body given this returning variable a NEW value, so the value it was
declared with can never be the one returned?" - asked of a returning variable that HAS an initialiser
(
<- rtn as Integer: Integer()).True when a stream statement's
> REPLACES its target when the pipeline completes (Steve, 2026-10-21:
"> 'clobbers' and >> 'appends'", the Unix shell meaning; made ALL-OR-NOTHING the same day, and
extended to a PriorityQueue and a JSON: "> always means REPLACE"; to a scalar 2026-10-26; and finally to
EVERY target, no type list, 2026-10-27: "let's make > consistent"): the termination is > (never
>>) and the target is anything but an output channel (IsOutputChannel).True when the assignment statement RE-POINTS its target at the object the right-hand side evaluates to
(a pointer assignment:
:=, =, :, :=?, as OperationIsAssignment defines it),
rather than handing that object to an operator of the object the target already refers to
(MutatesInPlace).Designed to ensure consistent reporting as part of the command line
commands and executions.
To be used with operators on aggregates (except for the is-set ? operator, that has to deal with functions).
THE reader of
require preconditions — use this, do not re-derive one.Checks that the require statement actually has a boolean result from the expression.
IR Generation for the require statement.
Detects when a reserved keyword is used as an identifier and emits a clear error.
THE rule for when a write to a local resets its 'referenced' flag (E08090): a write is not a use.
To be used in EK9 source code to assert that a type can or cannot be resolved.
Checks for resolutions directives.
Program-wide state for the per-phase symbol-resolution memo.
Used where traits are implemented 'by' a variable.
What a call node resolved to, or null when nothing was recorded; a recorded symbol that is not a call (a delegate,
a stage operand) is answered as itself.
To be used in EK9 source code to assert that a type can or cannot be resolved.
Checks if there are any directives that relate to @Resolved in the parsed module and checks the
resolution.
A bit of a long-winded name, but this is really the second pass of the second phase of compilation.
This is a really critical point, because this attempts to ensure that ANY expression
results in a symbol that has been 'typed'.
THE return type of the operator a unary or binary expression resolved to (IR tidy W3.9, OPS-11 - it was
AbstractGenerator.extractReturnType): read off the CallSymbol phase 3 recorded on the expression,
the returning type of the method or function it calls, else the fallback (the operand).Mainly used in the CompilableProgram for resolving or defining a new Parameterized type.
Used for resolving a function (by just name) or a variable that is a function delegate.
Check for valid function parameters.
Locate a possible call to an identifierReference, so some sort of call.
Resolves a method (by name and call arguments) within a given scope, emitting an error if it
cannot be resolved or is ambiguous.
Given a search for a method from an aggregate - and include supers/traits etc.,
this function will try and locate the method.
The bulk of the processing is in the abstract base.
The bulk of the processing is in the abstract base.
The bulk of the processing is in the abstract base.
This is a sort of hybrid resolver or definer function.
Used as an abstract base for parameterised types.
THE compiler-generated
close: the one place IR for closing a resource is built, so every route that
closes something names the same owner, the same method, the same metadata and the same failure rule.A value to close.
The region's first-failure variable, declared (null) BEFORE the region by
ResourceCloser.declareFirstFailure(ResourceCloser.FirstFailure, DebugInfo) - it must be definitely assigned where the region's handlers start.THE measurement of a window of compilation - a phase or a stage of one - used by the verbose
PHASE_METRICS
and *_STAGE lines so every window is measured the same way.THE retention walk of
ObjectSharing (D61): the object an expression evaluates to (or contains) - what keeps
it? The variable it is stored in, a container it is added to or put in a literal of, a call or constructor that may
keep its argument, a for loop's variable, a stream's holders, or the returning variable of a construct
whose value is assigned - ObjectSharing.Kind.SHARED with a nameable holder, else
ObjectSharing.Kind.ESCAPES.THE backend-independent verifier of the ARC RETAIN/RELEASE/SCOPE balance invariant for the +1
ownership-transfer convention, over the LOWERED form - model rule V-L, run by
OwnershipLowering on every
construct it lowers (EK9_IR_OWNERSHIP_MODEL.md §11.2, stage 3).A single balance finding for one construct/operation.
May
callee keep (a reference to) the argument it is given at parameterIndex - into its
receiver, another argument, its result or anywhere else (receiver <- item, return <- other,
or unknown)? An argument the callee keeps is no longer the caller's alone.The RETAINS text of the callee itself and of the generic it is a parameterisation, or member, of.
PRE_IR_CHECKS use-site check for a RETRACTED bare default comparison operator.
THE retraction step (D55/D58/D62): when
OrderingAvailability.bareOrderingRetracted(IAggregateSymbol, ISymbol) says the type's bare
ordering is withdrawn, mark each of its bare ordering operators (<=>, <, <=, >,
>=) DEFAULT_OPERATOR_RETRACTED, which the type's method set then filters out, so none is generated.Accesses the aggregate and gets just the 'default' operators defined on that aggregate (not any hierarchy).
Helper class for generating return block IR patterns.
Processes returningParam context from expression forms of control flow constructs.
THE check that a for, while, switch or try is used correctly in or out of an expression: as a statement it must
NOT have a returning section (it makes no sense), as an expression it MUST have one.
Checks if return variables are initialised.
Enforces guard-first return ordering (E08055; docs/language-design/EK9_REQUIRE_RETURN_ORDERING_SPEC.md).
THE test that an operation's returning variable is initialised in its declaration (
<- rtn as Integer: 0),
which on its own is an implementation: such an operation may have no statements at all.THE reading of
CommonValues.RETAINS - what a call's RESULT may share with what it was called on, and which
arguments (or receiver) a callee may keep.THE rules saying what
callee RETURNS (every return <- source it declares or has derived, the
generic's own for a parameterisation or a member of one) - for a caller that must map each source back onto the
receiver or the argument it names (phase5/ReturnSourceKind.origins).THE return-source classifier: which
ReturnSourceKind one source of a callable's returning variable is
(with IsFreshValueExpression, which decides ReturnSourceKind.NEW).THE kinds of what a callable's returning variable is made to refer to - one of the
MutatedOnlyVariables.ReturningCallable.sources() collected in Walk 1.What a source of a callable's returning variable may BE, in terms of the callable's own inputs - THE transitive
reading of D61 (Steve, 2026-10-21: follow the inner call back): the names of the incoming parameters it may be (or
a view of) and
ReturnSourceOrigins.RECEIVER_ORIGIN when it may be the receiver's interior.THE question whether a call hands back an owned (+1) result - whether or not the IR names it.
Does what
callee returns possibly share an object with its RECEIVER.get the appropriate return type from functions, methods and function delegates and constructors.
Record containing return variable management information for CONTROL_FLOW_CHAIN constructs.
Loads rich error messages from individual .txt resource files listed in a manifest.
Provides rich error messages for AI-assisted development.
The rich message for an error code followed by its
[EXAMPLE] section: the error catalogue's compiled
failing source and its compiled fixes (ErrorExamples.plainText(String) of ErrorExamples.CATALOGUE), as
plain text.Every rule the callee declares or has derived, the generic's own included; none for
unknown.Designed to be extended by rules and checkers.
THE reader of the runs-beside-signal-handlers fact (phase5 SignalHandlerNeighbourMarker; design §13.11 S2c,
option A): can this callable run on the program's own thread while a signal handler can run on the dispatcher? Then
E08251 holds it to the same rule as concurrent code for what a signal handler can reach.
THE calls that run NO EK9 code and release nothing - so none can reassign a field or let go of a value a caller
merely borrows (V-I, EK9_IR_OWNERSHIP_STAGE4_DESIGN.md §6): the boundary primitives (a primitive wrapper's
_true, _of, ...; IsBoundaryPrimitive) and the property-cycle guard's enter/exit, which
records identities in its own frames (ek9_cycle_guard.c: no vtable call, no retain or release).Extracts EK9 runtime classes (org.ek9.lang and ek9 packages) from the running JVM
and packages them into a versioned JAR file with SHA-256 checksum.
THE content hash of the runtime this JVM would package: computed ONCE per process (lazily, on first use) by
ContentHashOf over every class that RuntimeClassExtractor.extractRuntimeJar(FileHandling, String, String) could take.THE reader of the licence texts the compiler packages with the runtime: the third-party notices
(
RuntimeClassExtractor.NOTICES_RESOURCE), the runtime's Apache-2.0 licence and its NOTICE.THE conjunct walk for Optional/Result/Iterator safe access (Steve, 2026-10-07, decision Q3) - use it, never
re-derive a variant.
One fact a conjunct proves:
access (ok/error/get/next) on symbol is safe.THE E08040 rule: an Optional/Result/Iterator that is proven safe to unwrap in the current scope must not be
re-pointed there, by ANY store - an assignment statement (
o: other, o :=? other) or a
construct's assignment pre-flow (if o := other then o?).THE withdrawal of safe-access proofs (E08030) as the walk passes code that may change a proven Optional / Result /
Iterator (
ProvenContainerChange decides what may): from that point on, in the current scope and every
scope enclosing it, get() / ok() / error() / next() needs a new check.THE single defence-in-depth chokepoint that makes a zero-length JVM exception-table entry impossible to
emit.
Marks specific types of variable of specific types (generic Result/Option) in a manner
that enables the compiler to check if access to certain methods is safe.
Tests specific types of variable of specific types (generic Result/Option) in a manner
that enables the compiler to check if access to certain methods is safe.
THE shared "which of Result, Optional or Iterator is this symbol" (the containers whose unwrapping method
ok()/error(), get() or next() must be preceded by a check, E08030), and the three-way
dispatch onto SymbolsAndScopes' record, is-safe and mark operations.The container a symbol's type is a parameterisation of.
SAFE_POINT: a point where the native cycle collector may run (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §14).Which safe point.
THE placement of
SAFE_POINT (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §14.4, S2): the first IR_OPTIMISATION
pass, over the ownership form, before the lowering.V-S (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §14.5): a
SAFE_POINT only in an operation that is not
callback-reachable - a collection under a runtime frame could free what that frame holds uncounted.It may be that before calling this you have determined that 'isSet' has been called or you 'know' that
the value of the variable is present and set.
Checks to see if the type parameters are the same as the generic arguments.
THE vocabulary of B18 - "a type defines sameness once" - hold its parts, do not re-derive them.
THE walk behind
InheritedSameness, SealedSameness and SortOwnerAbove: the first sameness
above a type (its supers and traits, breadth first, each once) whose declaring type passes an owner test.One sameness found above a type: the level of the walk it was found at (a parameterised type stays itself, so
its display name can be rendered) and the operator, read from that level's declaring type.
Completes every type's SAMENESS once types are known, after every source has been through
EXPLICIT_TYPE_SYMBOL_DEFINITION (B18 - a type defines sameness once).
B18 - a type defines SAMENESS once (Steve, 2026-09-30).
Generates the body of an override of an inherited
==(Super) or <=>(Super) on a type with its own
sameness (D24 rule 3, OverriddenSamenessSignatures, Contract 22): the OBJECT decides which comparison
runs, never the reference (N07).Creates the DETACHED method symbols a type with its own sameness carries for a comparison through a super-typed
reference (D24 rule 3,
OverriddenSamenessSignatures): one == or <=> override per inherited
signature taking a super.THE run-time-type check in front of a concrete type's sameness (D24 rule 3, Contract 22): values of different
run-time types are never the same, so the comparison goes to its "different type" answer -
== false,
<> true, <=> unset - before anything else in it runs.THE test that two DIFFERENTLY SPELT operators are one runtime operator - hold one and ask it, do not re-derive it.
Checks for inappropriate use of 'sanitized' at function/method call sites.
Data holder for checking that an overriding declaration keeps every 'sanitized' parameter of the declaration it
overrides.
Checks for inappropriate use of 'sanitized' in expression parameters.
Checks for inappropriate use of 'sanitized' in variable declarations.
Checks that an overriding method or function keeps every 'sanitized' parameter of the declaration it overrides
(E07940).
THE single source of 'sanitized' parameter cleaning in IR generation - hold one and call it, do not re-derive it,
and never clean at a call site.
Validates that the 'sanitized' keyword is used correctly:
1.
THE reading and marking of
SANITIZED_REQUIRED: the as sanitized modifier on a parameter (and, by
propagation, on an expression that is one of them).THE marking of
SANITIZED_REQUIRED: the symbol is a parameter declared as sanitized (or an
expression derived from one), so the RECEIVER must clean it.IR instruction for sanitizing string values to prevent injection attacks.
Specialized ASM generator for SanitizeInstr processing.
Generates IR for Scenario 2 aggregate wrapper constructors, delegation, and function-accepting methods.
Generates IR for Scenario 2 wrapper equality operations.
Generates IR operations for Scenario 2 function type wrappers.
Shared utilities for Scenario 2 wrapper IR generation.
THE choice of the two calls a wrapper makes on its delegate to reach the contained value: the presence check
and the accessor, which differ between Optional (
_isSet / get) and Result (isOk /
ok, or isError / error for whenError).Generates IR for Scenario 2 delegation wrappers.
Generates IR for Scenario 3 (USER_DEFINED_SOURCE) parameterized types.
CONCERN: Temporary scope lifecycle management.
A scoped body and the id of the scope it ran in (for sites that name that scope afterwards,
for example as a case scope id).
Represents a symbol that also has a scope.
Scope boundary information for tracking variable lifetimes.
Specialized IR instruction for scope management (SCOPE_ENTER, SCOPE_EXIT, SCOPE_REGISTER).
Specialized ASM generator for ScopeInstr processing.
Memory management for CONSUMING a value that was already RETAIN'd by a producer.
This stack object is only designed to be used when first parsing.
Just focussed on ensuring that scopes are correct push on to the scope stack.
Walks a callable's parse tree to collect the variable symbols accessible within it - the local
variables declared in its (possibly nested) instruction blocks, and the property fields of its
enclosing aggregate.
THE SEALED sameness a type inherits (D24 rule 1) - one written by hand on an abstract base or a trait above it
(
IsHierarchyWideSameness) - if any.Detects hardcoded secrets in string literals at compile time (E11080-E11086).
THE walk of a type and its supers for the dependency-injection checks - constructing it constructs the parts its
supers declare (D-10:
UnsatisfiedInjectionReporter once had a second, recursive copy of it).Detects self-comparison expressions where both sides resolve to the same symbol (E08081).
THE self copy of an aggregate: the
:=: it declares in its OWN scope that takes the aggregate itself
(PolymorphicCopy).The narrow 'produce a semantic diagnostic' surface of
ErrorListener.Can be a normal version number like 6.8.2-9 i.e 9 is the build number
Or can be for a feature like 6.1.6-specialFeature12-19 i.e.
Serializes a compilable program to a byte array, so it can be saved/reused as required.
Alters an 'Application' from being a general application to a service application when it registers a service.
THE service-form repair (Steve, 2026-10-11: one form each) - for every editing tool.
The rewritten text and one note per rewrite;
notes empty means nothing moved.Creates the appropriate IR Construct for a service declaration.
Deals with the creation of the service parts for the EK9 language.
Extracts HTTP metadata from an EK9 service
AggregateSymbol to produce
a fully materialised ServiceRouteDetails.Generates one
public static __op_<methodName> method per service route on the
service class.Scope for callable methods (operations) that are part of a Service.
A single service registration within an application.
Links the escaping-return-value contract of service operations into the call graph.
Complete route table for a single EK9 service.
Binding for a single parameter to its HTTP source.
A single service operation's HTTP route metadata.
THE normalisation of a service route's URI-template parameters for route-identity comparison — use
this, do not re-derive the
\{.*?} regex.Validates that every service declaration has a security posture: either 'open'
or 'constrain by X [and Y]'.
Represents a variable known to be either SET (has a meaningful value) or UNSET (declared but no value).
Looks at the returning param (if not null) and sets the symbol type as appropriate.
Shared IR-text rendering for the nested setup block of composite instructions
(LIST_LITERAL / DICT_LITERAL / STRING_INTERPOLATION).
The Generic T used in parametric types will exist but won't have any methods on yet.
The principal data-race check (slice 1, step 7): every mutation of shared state
inside a function/method marked
CONCURRENT_ENTRY_POINT must occur inside
a MutexLock.enter(...) callback.Concept here is to be able to protect raw java objects from multiple threaded access.
THE closure of the types a value of the root types can reach (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11): through
properties (inherited ones included), supers and traits (for what they give it), subtypes of a type a value is
declared as (a reference of a base type may hold any of them - never a super's other subtypes),
type arguments (
List of T), what a method or constructor may KEEP (RetainsArgument - a built-in's
fields are not EK9 properties, so a PriorityQueue reaches its comparator this way), and the captures of
every function or dynamic class a reached value can be.Generates IR instructions for Boolean AND operations using LOGICAL_AND_BLOCK pattern.
THE short-circuit Boolean block: a LOGICAL_AND_BLOCK or LOGICAL_OR_BLOCK built from an already evaluated LEFT
operand (with its primitive), a RIGHT operand evaluated only when LEFT does not decide, and the result computation
left._and(right) / left._or(right).The parts of one block.
Generates IR instructions for Boolean OR operations using LOGICAL_OR_BLOCK pattern.
THE shared short display name of a fully qualified name, for the dependency-injection and HTTP wiring diagnostics
and the
-di report: some.module::Type reads as Type - the text after the last . or
: of the name, or the whole name when it has neither.THE short text of an instruction named in an ownership finding: a composite by its opcode, anything else by its IR
text without the debug comment and the purity annotation, cut at 110 characters - so a finding shows the
instruction's shape without the operation's IR.
Determine if a variable should be registered in scope for cleanup.
Who runs beside a signal handler, and what it reaches (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S2c - option A,
Steve 2026-11-02).
Just a wrapper around java public private key processing.
THE type of a method's single parameter, when it has exactly one - e.g.
Where the fresh sink of a
> that replaces comes from.THE decision of
SinkBuffer for a target type (asked beside ReplacesTargetOnCompletion, which is
defined by it).THE "may this slot already hold a value here?" test for a slot that may be assigned AT MOST ONCE ON ANY PATH: a
closeable property in its own constructor, and a closeable returning variable declared unset (D3 extended to every
closeable slot, 2026-10-06).
THE walk every string-expression finder shares: the smallest
EK9Parser.ExpressionContext under a root that
passes a test, or null.THE shared cache of small non-negative int-to-String conversions — use this instead of
String.valueOf(int) / Integer.toString(int) when the result is squirrelled or
otherwise retained per symbol.Generates JSR-45 SMAP (Source Map) for debugging non-Java languages on the JVM.
THE sort owner of a type (D52 residual, Steve 2026-10-21, option a): the type a stream
sort groups its
values by before comparing any two with <=>.Result of sort transformation: the new iterator setup and the sort index.
Defines the concept of an EK9 source file.
THE decoder turning a compiler source-token identifier into a filesystem path — hold one and use it, do
not hand-roll the scheme strip.
Provides source line content for error display formatting.
Determines whether a
CompilableSource corresponds to a given source file name.What a page shows of a
SourceRegions body: the named region (the whole body when the region is null), with
every marker line removed, each elided run replaced by ONE // ... <name> comment at the run's indentation,
leading and trailing blank lines dropped, and the result dedented to its least-indented line.The "full source" view of a
SourceRegions body: every source line with the marker lines removed, and for
each region the (zero-based) line of that text it starts on.The
SourceRegions marker on this line, or null when the line is source.The
SourceRegions region names declared in a body, in source order.Every structural problem in the
SourceRegions markers of a body - unbalanced or mismatched markers, a
duplicate or malformed region name, an elide inside an elide.THE reader of the region and elide markers in a compiled example source (site-examples spec §3.4, decision D5) -
every page fragment is cut from a whole, compiled source through here; never parse the markers anywhere else.
A source with its markers removed, and the line each region starts on.
The kind of a marker line.
One marker line: whether it opens or closes, its kind, its name and its indentation.
THE source repair engine - the one place an EK9 source is repaired automatically, for every door:
ek9 -ff
and ek9_format (the TEXT layer), and the MCP editors, ek9_write_file, ek9_edit_file and
ek9_compile (the DIAGNOSTIC layer).One diagnostic-layer pass: the repaired text and one note per repair; notes empty means nothing moved.
The text layer's outcome.
THE slice of a source text a rule spans, by its tokens' start and stop character indices into that text; null
when the rule has no tokens or the indices fall outside the text (was
StringConcatRewriter.sliceSource,
shared by the rewrite and ConcatChainRenderer).THE source of a parse rule as the developer wrote it: the characters it spans in the char stream, spaces kept.
THE source text of an expression as a run-time message shows it (an
assert or require failure):
SourceTextOnOneLine, cut to SourceText.MESSAGE_LENGTH characters with a ... suffix when
longer.THE source of a parse rule as written (
SourceText), on one line: every run of whitespace, line breaks and
indentation included, is one space.To be used in EK9 source code to assert that a specific squirrelled-data key is set
(to any non-null value) on a resolved symbol at the given compilation phase.
Processes
SquirrelledDirective directives.Used when duplicate symbols are found, where we need to add a placeholder.
Support for stack-oriented code generation.
A stage operand that is a function, or a delegate holding one, that may change what it is given.
A run of pipeline stages together with their pre-loop state - the two always travel as a pair,
positionally aligned, and are meaningless apart.
Result of stage initialization: pre-loop instructions and per-stage state.
The pre-loop state of one stateful pipeline stage - one shape per kind of stage, made by
StreamPipelineMachinery.generateStageSetup(List, String, DebugInfo) and read by that stage's wrapper.async: the
Ek9Async executor.head / skip: the alloca-backed counter, the limit and the constant one it is incremented by.
group: the
Ek9Group tracker.join: the tracker, the accumulator and the fold function instance and result, pre-allocated.
split: the
Ek9Split tracker.tail: the bounded
Ek9Tail circular buffer.tee whose side target is an expression (
tee in h.sink(), tee in outputs.err): the variable holding
that target, evaluated once before the loop (a bare identifier target needs no state - it is the local).uniq: the
Ek9Uniq tracker.The three things EVERY stream stage needs, whatever its shape: which stage it is, what runs
downstream of it, and the debug info to stamp on what it emits.
Result of wrapping stages: the per-iteration body and any post-loop instructions.
THE calls that start runtime threads and finish only once every one of them has stopped
(EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, T10): a server's
accept, acceptUntilComplete,
serve and serveUntilComplete return after shutting down the scheduler they started, and an async
pipeline's Ek9Async.create() begins the statement whose close() drains its workers and does the
same.THE calls that start runtime threads (EK9_NATIVE_CYCLE_COLLECTOR_DESIGN.md §13.11, S0b): every call
StartsAndStopsRuntimeThreads names - an async pipeline's Ek9Async.create(), a server's accept and
serve, each of which starts the carrier scheduler - and Signals.register, which starts the signal dispatcher
that never stops.THE per-construct statement budget - the maximum number of statements permitted for the construct the symbol
represents, keyed off the symbol kind (the limits live in
QualityMetricLimits).Tracks statement counts within functions/methods/operators.
Validates that the statement is OK and emits errors if this is not the case.
THE decision of which calls make a closeable value that the block statement making it OWNS - the unnamed half of
the closeable ownership rule (Steve, 2026-10-05): "A closeable value you never NAME is owned by the statement that
created it and closed when that statement finishes." The named half is
CloseableLocalOrError (E81056).The UNNAMED half of the closeable ownership rule (Steve, 2026-10-05): "A closeable value you never NAME is
owned by the statement that created it and closed when that statement finishes; a closeable value you NAME
must be declared as a try-with-resources resource." The named half is phase 5's E81056
(
CloseableLocalOrError).What
StatementOwnedCloseables.own(List, DebugInfo) found.THE F.3 step-filter decision core: turns a method's
MethodDebugPolicy bitset (from
MethodKindIndex.policyFor(String, String)) into the yes/no answers a JVM debugger needs while stepping and
building the call stack.Classifies a single step in a
DeadlockChain's rationale trace.Creates IR instructions for statements.
The
HttpAccess kind stored on this parameter, or empty if none has been stored yet.The property of this object that the assignment statement re-points at 'this', if it does.
THE JVM local-variable STORE opcode for a type (ASTORE for object/reference types) - single-sources the per-type
opcode switch the generators had duplicated.
THE phase-5 reading of a STORE: a statement that makes a variable, property or returning variable refer to the
value an expression evaluates to.
The
StoreSite a pointer assignment to an existing variable or property makes, if it makes one
(:=, =, :, :=?, as RepointsTarget reads it, to a name or through an object
access).The
StoreSite a declaration with an initialiser makes, if it makes one (<-, :=, =,
:; never :~:, which merges into a new object).The variable a declaration or a plain store gives the value of
assigned to, or null.Used in Stream assembly processing to check aggregate use validity.
THE check that a stream statement never appends to the very variable it is reading (E08277, Steve 2026-10-21, D82;
widened to EVERY type 2026-10-26, Q6/Q8 - one rule, no type list):
cat items >> items appends to
items while cat is still pulling from it - the pull never reaches the end, and at run time the
List's iterator says so.The construct for a Stream statement/expression.
Processes/updates and checks that a stream assembly is actually viable in terms of types.
A stage that cannot stream: it must see the whole source before it can emit anything, so instead of
wrapping the loop body it REPLACES the pipeline - draining the source into a buffer pre-loop, then
emitting from that buffer through the remaining stages.
Just re-uses the bulk of method symbol.
Deals with working out what the type being 'catted' is.
THE demand rule of a stream pipeline:
head N bounds the PULL (decision 10, rule B) - use this, never
re-derive which heads gate a loop or how the gate is folded into a loop condition.THE rule that a stream's element type is never closeable (E81073, Steve 2026-10-26, decision (a) of the closeables
lane) - the stream analogue of E81061, which says a closeable is never a type argument.
A stream stage that inspects the flowing element WITHOUT changing it -
filter,
reject.The buffered-emission engine: the stages that cannot stream, and the pipeline bodies they emit.
Now does the check/processing of the whole stream pipeline.
Process and ensure that the stream termination can function correctly.
Just deals with the creation of Streams parts.
Deals with working out what the type being "for'd" is.
Checks that the arguments in the function are compatible with the current pipeline type.
Used in Stream assembly processing to check function validity.
Checks a stream pipeline whose source is a
for carrying a pre-flow guard.THE call shapes for the compiler-to-runtime helper types stream pipelines lower onto (
Ek9Async,
Ek9Group, Ek9Split, Ek9Join, Ek9Uniq, the tail buffer, Ek9Sort) - use
these (hold one), do not hand-roll another; the sibling of ListBufferCalls, which owns the List buffer.Produces the loop body-tail after the iterator item is bound: stages + sink.
THE record of stream stage function operands that were EVALUATED once, before the pipeline, rather
than named - use it, do not re-derive which operands need evaluating.
The pipeline machinery shared by the orchestrator and the buffered-emission engine: draining a
source to an iterator, planning the per-stage item variables, building the stream loop, and
setting up per-stage pre-loop state.
Intended to model the pipeline flow in a streaming of cat or for loop though | and map etc.
A stream stage that CANNOT emit during the loop -
join, tail.THE check that a stream statement's
> (which REPLACES its target, Steve 2026-10-27: "let's make >
consistent") is only written where the target can give the fresh value it is built on (E08278): a concrete type
with an accessible no-argument constructor and a :=:.What a pipeline is reading from: the iterator, the type of element it yields, and whether that
source can go on forever.
Discriminates a pipeline stage to its generator and nests the wraps.
A stream stage that TRANSFORMS the flowing element -
map, call, flatten.Generates IR for stream statement pipelines: source | stages | > terminal.
Now does the check/processing of the whole stream pipeline.
Process and ensure that the stream termination can function correctly.
A stream statement's termination as the replace decision reads it.
THE compile-time half of strict-absent mode (Steve, decision 5, 2026-10-07: "a residual absence PANICS, always").
What observed an absent value, and where: the operator, and the source location named in the Panic message.
Outcome of a
StringConcatRewriter call.One refusal condition.
Editor primitive that rewrites a string-concatenation expression
(
"a" + var + "b") into the equivalent backtick interpolation
(`a${var}b`).Generates JVM bytecode for STRING_INTERPOLATION IR instructions.
IR instruction for string interpolation.
Represents a single part of an interpolated string.
Type of interpolation part.
THE smallest expression that both contains the cursor and is a single string literal (
IsSingleStringLiteral;
was StringExpressionClassifier.findEnclosingStringLiteralExpression).THE
stringLit of an expression that is a single string literal (double-quoted or backtick), or null when
the expression is not one (was StringExpressionClassifier.extractStringLit).THE strongly connected components of a directed graph (Tarjan, 1972) - use this wherever a phase needs the cycles
of a graph, never a private copy.
One strongly connected component.
Pass 2 of the EK9 source formatter: Structural Reordering.
Canonical ordering for module block types.
THE place a sub-type (a class, record or component that 'extends'/'is' a super) gets its generated public
no-argument constructor - after every source has been through EXPLICIT_TYPE_SYMBOL_DEFINITION, supers first.
A single ranked suggestion that the compiler can offer the user as a possible
replacement for an offending token.
Where the suggestion came from.
Checks for a type is resolved and is suitable genus and category.
Used with aggregates to check that if they have any properties that are not initialised at declaration
the developer has taken appropriate steps to ensure initialisation.
Checks for a type is resolved and is suitable to be extended from (in basic terms).
The super CLASS chain above an aggregate, nearest first - the walk every "operator above" question shares
(
NearestOperatorAbove).Every EK9 constructor chains to a super constructor: an explicit
super(...), an explicit
this(...) delegation, or - when neither is written - a hidden IMPLICIT super() to the
super's no-arg constructor.Resolves the JVM superclass of an EK9 construct and injects the
super(...) constructor call
when the IR does not already contain one.THE supers-first walk: act on every node of a set of sites AFTER everything it depends on, each node once.
Only types of a specific genus can be used as constraints on the generic type 'T'.
Specialized generator for EK9 switch statements.
Generates short-circuit OR chains for multiple switch case expressions.
Result of comparison generation.
Specialized generator for EK9 switch expression form.
Deals with checking if the switch can be used as an expression and whether
the variable being switched on has the appropriate operators to meet the case criteria.
Generates IR for switch statements and expressions using CONTROL_FLOW_CHAIN.
Record to hold evaluation variable information.
Deals with checking if all paths through switch/case/default (return) result in variables meeting criteria.
EK9 switch statement - this can effectively return a value if it is configured with returning
part.
A bit of a beast.
Models information used in code analysis for various variable states.
Used when checking access to fields/properties and methods.
Typically used on symbols; so we know their broad use and type.
General utility class that searches in a scope for a symbol to check for duplicates.
SINGLE THREADED.
Just a factory for all types of EK9 symbol.
Returns the appropriate symbol from the symbol and scope management component.
Typically, used on aggregates because we might use a AggregateSymbol.
Only triggers the call the retrieve the appropriate symbol for the node.
SINGLE THREADED
The Layer-2 symbolic/contract verification pass
(docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §4.4).
The Layer-2 symbolic engine of the Symbolic/Contract Scanner (M3/M4) — it turns "this construct
carries undischarged obligations" (the M1 census verdict) into "here is the exact input that panics",
or proves no such input exists within the bounded model
(docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §3/§11.2/§12).
The M3 symbolic dead-branch analyzer: seeds a function's parameters as
SymbolicTermValue
terms, reads the relational facts off its require/if nodes into a PathCondition,
and reports a branch dead when its accumulated facts are unsatisfiable.The base (pre-branch) path condition and the verdict for the function's
if branch.Whether a branch is dead (unreachable for every input), and why.
A symbolic (named) term in the flow lattice — a fresh, unconstrained parameter or local carried as
itself instead of collapsing to
TopValue.Given some search criteria and a List of Symbols, this class will find the best match.
Checks if a symbol has been referenced or not (can be null - no error).
MULTI THREADED
Now try and check that all symbols used have a type.
THE re-typing of a single symbol, in place, when it has a type: its type becomes the replacement's answer for it.
Used as external helper to record symbols and scopes across the parser.
To be used to search for symbols in a Symbol table.
Can be used for a single Simple named search.
Just extracts the ISymbols from the expression contexts and issues not resolved errors if any are not present.
Function that extracts signature-qualified-name from a symbol.
We need to support simple things like classes which are unique per symbol table
Or the fully qualified class names like 'com.some.A and com.other.A' so they won't collide.
Given a list of arguments (ISymbols), go through and extract the types out.
Provides the PossibleGenericSymbol type of the symbol if it has been typed, or empty.
Just gets the type from a symbol, or throws a compiler exception if missing.
THE uses of ONE symbol instance in a fragment of the COMPILED tree, through the identifiers the compiler bound
(
RecordedSymbols) and the copies dynamic functions and classes captured (CaptureAliases) - never
by name.THE "where is this symbol written?" for the compiler's own analyses and the
mcp.oracle tools - use this,
never a by-name test such as body.contains("this." + name) or a set of assigned NAMES.One write.
THE parse-only check of a piece of EK9 text, for every repair: the syntax errors the ANTLR parser reports, no
symbol phase run.
A parse tree and the token stream it came from (HIDDEN-channel comments included).
One syntax error.
THE way a phase-7 SYNTHESISED call site obtains its
CallMetaDataDetails.Bundles the scope parameters that flow through synthetic operator generation methods.
Looks at the function and if it has no super function, attempts to work out what would be the
best super function generic type it could implement.
Some aggregates like classes, components, etc.
THE C.1
ACC_SYNTHETIC gate: the extra access bit a generated method carries iff its kind is
hide-always.Fluent builder for generating method and constructor call IR instructions.
Main coordinator for synthetic operator generation.
THE names the compiler gives the parameters of constructors it SYNTHESISES - a constrained
type's, an enumeration's, a text's, a generic's required pair and its type parameters'.
Generate tail wrapper using an Ek9Tail circular buffer.
True when
method takes exactly the types of variables (VariableTypes), in order
(ExactParameterTypes); false when any of the variables has no type.Is this the named method with exactly one parameter, of a type the aggregate is assignable to? The generated
comparisons' reading (
HasOwnComparator, HasHandWrittenEquality).The target platform/technology for the compiler output.
Possible supported target output architectures.
Given a TargetArchitecture, this function will provide the Target for it.
THE rule for target-typed generic construction - use it, never add a second inference route
(Steve, 2026-10-08, GENERIC CONSTRUCTION a).
Records that this call was completed from its declared target (
TargetTypedConstruction, phase 3); read
only by IsTargetTypedConstruction.The generic function parameterisation a target-typed call (
TargetTypedConstruction) constructs (a
function VALUE, never an invocation), or empty when the call is not a target-typed construction of a generic
function.The target's own KIND half of
CompoundTargetMayKeep: may a compound assignment to a value of this type keep
its operand at all? A container (a parameterised type, a bare T) and a type of the program's own may; a
built-in value, a constrained type over one and an enumeration copy.Generate tee side-pipe and continuation for a tee stage.
A Search for a TEMPLATE of a FUNCTION.
A Search for a TEMPLATE of a TYPE like a CLASS.
Represents the source of a temp variable for stack-oriented code generation.
The type of source for a temp variable.
The colour, Unicode and emoji capabilities of the terminal this process writes to, detected once (and again by
TerminalCapabilities.resetTestMode()) - see TerminalColors, THE formatting functions that read it.Terminal color and symbol support with automatic capability detection.
Helper record for terminal sink setup results.
Specialized generator for EK9 ternary operator.
Test directive for marking programs as tests, optionally anchoring one to a requirement and
declaring the exit code its program must end with.
The sequential execution group a test belongs to (
IsTestProgram has the encoding contract).Creates the IR Construct for the abstract base text class.
Locates the textBodyDeclaration parse context for a given text method symbol.
Generates IR for text body methods with implicit String return.
Creates the appropriate IR Construct for a text declaration.
Deals with the creation of Text parts from the EK9 language.
THE single decision point for lowering a
text constructor call.A text made with a plain String literal naming a language that has no
defines text for block is an error
(E07157, Steve 2026-11-02).Extract the valid language value from the String literal or null and error.
THE text method round the cursor: the smallest
EK9Parser.TextBodyDeclarationContext containing it, with the
name of its enclosing EK9Parser.TextDeclarationContext (was
StringExpressionClassifier.findEnclosingTextMethodDeclaration).The resolved text-type and method names, ready to feed straight into
ek9_edit_localized_text as
textTypeName / methodName.One text rule of
SourceRepairs: given a source's lines and the parse failure the parser stopped on, the
rewrite that answers it - or null when this rule does not recognise the failure.A rule's rewrite: the new lines, and the note that says what was written and why.
Emits the bytecode for EK9 TEXT constructs: the abstract base type's no-arg constructor, its
static
_textFactory locale dispatcher, and the _isSet override on both the base
(unset fallback) and the locale variants (always set).THE name of a text's generated locale variant:
_Base_lang, from the base name and the language.THE locale variants of a text base - one per
defines text for "<lang>" block of that text, read across ALL
the source files of its module (ModuleScope.getSymbolsAcrossModule(); front-end audit FE31: one file's
scope missed the languages declared in the others).The locale variants of a text, carried on the IR construct of the text's abstract base: THE list a back end lowers
the base's
_textFactory(language) dispatch from - JVM and LLVM alike.One locale of the text.
Check an assignment again 'super' use and some operators against 'this' use.
Just focus on resolving 'this' or 'super' in respect to a 'call'.
Checks and assigns type a 'this' or 'super' symbol, but only if it valid.
Every user implementation of a handler type a thread-spawning call takes (
TCPHandler, the ready handlers,
SignalHandler - IsThreadSpawningCall.handlerTypes()) is a concurrent entry point and a published
handler, wherever it is written and however it reaches the call (review 2026-11-02, H2).A PrintStream that delegates to thread-local outputs.
THE test that a block statement cannot throw: it only stores a literal, or the value a variable already holds,
into a variable of exactly the same type (
size := limit, count <- 0, total as Integer?).Specialized IR instruction for throwing exceptions (THROW).
Specialized ASM generator for ThrowInstr processing.
Generates IR for throw statements.
Checks that the throw statement actually throws and Exception type.
THE reading of a Time literal (
07:30); throws DateTimeParseException.Converts a list of symbol using their friendly names in to a comma separated list.
Generates synthetic IR for the _json ($$) operator.
Listen as Tokens are consumed as they are pulled from the Lexer into the parser.
THE "does this token index lie within that parse rule?" - inclusive of the rule's first and last tokens, by token
INDEX (so by position in the one token stream, never by line or by text).
THE token-range bounds of an expression as 1-based (line, col) coordinates,
[startLine, startCol, endLine,
endCol], inclusive on both ends - the shape MCP-tool selection parameters expect; null when the expression has
missing token data (was StringExpressionClassifier.tokenRange).Typically used for locating the nearest token to some position in a source code file.
Pass 3 of the EK9 source formatter: Token Spacing.
Drives
ReadabilityAssessor over a whole lexer, for standalone and debug use - and to
list out tokens so that when building grammars out of tokens it is possible to see what is
being produced.THE parts of a text between its top-level commas - a comma inside brackets or a literal does not split - each
stripped; one part when there is no such comma (was
SourceLines.topLevelParts).Represents an unknown value — no information available about the variable.
Generates synthetic IR for the _string ($) operator.
THE answer to "what value does this expression hold here?" for the phase-5 flow checks: a written literal
first, else what the
ValueTrackingAnalyzer tracks for the expression's symbol.THE unbalanced trailing bracket -
stdout.println(x)], stdout.println("few")} - for every
caller: the statements[] pre-pass, the MCP diagnostic repairs and ek9 -ff.Checks that a trait access like T1.xyz() - is allowed i.e.
THE single source of truth for "does a call on this target need INVOKEINTERFACE?".
Creates the appropriate IR Construct for a trait declaration.
Analyzes how traits are implemented in an aggregate to detect E11023 pattern
(missing 'by' delegation).
Result of analyzing trait implementation for potential missing 'by' delegation.
Check trait specifics on methods/operators.
Detects when multiple traits implemented by an aggregate have methods with the same signature.
Checks that traits do not have properties/fields.
Single element of a function's
mayEnter summary — an enter() site reachable
from this function via some call path, with the lock identities after parameter
substitution and the composed edge-kind of the reaching path.Post-parallel detector for transitive injection ordering validation (E08200), run once the call graph is built.
Gets the abstract methods and then resolves each to see what the resulting method would be.
Record representing the try block within a TRY_CATCH_FINALLY control flow chain.
Specialized generator for EK9 try/catch/finally statements.
Generates IR for try/catch/finally constructs using CONTROL_FLOW_CHAIN.
Deals with checking the try statement/expression.
Checks the try/catch/finally structure via the code analysers.
EK9 try statement - this can effectively return a value if it is configured with returning part.
THE leaf walk of a type's arguments: descend through every parameterisation (
List of (Dict of (K, V)))
and collect the leaves isLeaf accepts, in order.Given a Symbol that is some form of type, check that it could receive some piped data.
A type's metric-side model for the input-variation denominator: its ordered set of distinct
ValueClassIds and how trustworthy that set is (ClassConfidence).Map a shared
InputVarietyModel.TypeModel into the compiler-side denominator
model - string confidence and class names to their ClassConfidence / ValueClassId
enums.Can the 'from' type be coerced to the 'to' type.
TO be used when checking the left hand side and the right hand side with specific operators.
Checks that any recursive type constraints on a type are valid.
Checks the covariance compatibility of two variables, this will traverse them to get their types.
Pass a string of an ek9 typeDef in and use the
EK9 parser to just handle the breaking up of a String of a TypeDef into
a structure and names.
THE typed read of a stage's state (
StageState): state as kind, or a
CompilerException naming both - never a cast that turns a wrong or missing state into a null variable
name.Designed to be used in phase3 or after - FULL_RESOLUTION.
SINGLE THREADED - Run across sources to check for types, functions and traits for 'super loops'.
THE name-keyed form of "is the type this CALL names externally linked?" - the value of
CallDetails.isExternTarget for a site that holds a type NAME and not the type's symbol (IR lane F, Steve
2026-10-28).Checks that the symbols in list one and list two are each the same for the corresponding position in the list.o
THE test of whether a holder - a container variable, a stream's target, a call's result - can keep an object of a
given type at all (D80 follow-up, 2026-10-21): the walk behind
BorrowedViewReturn (rule B), asked about an
object of one of heldTypes instead of about a closeable.Extracts the fully qualified type name from the symbol.
Is
target the built-in generic itself or a parameterisation of it.THE constraint of a generic's type parameter: the 'X' of
T constrain by X, or empty for an unconstrained
'T' - use this, never "does T have a super?".A generic's type parameter name must not resolve to ANYTHING (E01091) - not a built-in, not a construct of this
module (even one declared later), not a function, not a constant.
THE reading of "a generic's own hand-written
<=> compares values of this conceptual T with
<=>" (D89), however it reaches them (D91 step 4): directly, through the generic's own methods, through the
generic functions it gives them to (and on through theirs), or by giving them to a function delegate - which is
taken to order them, whatever it does (strict, as E06070).The single level of type parameters (for a template) or type arguments (for a parameterisation) exactly as
declared - for display/inspection.
THE conceptual parameters a (non-bare) parameterisation is built on, each once; for a generic template (named in its
own body) its own type parameters.
Final formatter pass that strips the implicit module-name prefix from
EK9 type references.
Check that the types of two symbol ar compatible with each other.
Accepts an aggregate or a function that has been parameterized with 'type arguments'.
A Search for a concrete actual TYPE like a RECORD or a CLASS for example.
The denominator input for a single parameter type: how many distinct value-classes it admits and
how trustworthy that count is.
Generates IR instructions for unary operations (e.g., unary minus, increment, decrement, etc.).
CONCERN: Unary operator invocation with memory management.
Parameters for unary operator invocation.
THE E01093 repair - a backtick String closed with a double quote,
`${count} items" - for every
editing tool.The rewritten text and one note per rewrite;
notes empty means nothing moved.A backslash-u in a String literal must be followed by exactly four hex digits (E07903).
THE reading of "was this variable, property or returning variable declared with NO value" - the
UNINITIALISED_AT_DECLARATION squirrel that phase 1 sets on name as Type? (and phase 3 on a
synthesised returning variable).THE test that a symbol is a PROPERTY declared with no value, so every access to it is questionable until a
constructor (or a guard) has set it: a
VariableSymbol that is a property field and
UninitialisedAtDeclaration.THE E08180 repair on a RETURN declaration -
<- rtn as String with neither a value nor
? - for every editing tool.The rewritten text and one note per rewrite;
notes empty means nothing moved.Used to check if variables within code blocks when declared without being initialised, actually
get initialised before they are used.
Checks if a variable should be processed as a possible uninitialised variable.
Record on each dispatcher entry what its handlers return and keep (
MarkOverriddenBy, over the pairs
DispatchedHandlerPairs found); true when an entry gained a rule - one step of a RETAINS derivation's
fixpoint.THE Union-Find (Disjoint Set Union) - use this for "which things are connected", never hand-roll parent arrays.
Generate tracker call and conditional wrapper for a uniq stage.
A field whose type cannot be ordered, found on a type, and the type that declares it
(
OrderingAvailability.unorderedPropertyBehind(MethodSymbol, ISymbol)).Checks to see if a variable has a specific generic type.
Checks to see if a property on an aggregate is safe to access.
Reports dependency-injection fields that cannot be satisfied at a given point, walking an
aggregate's own injection fields plus those of any aggregate types reachable through its property
field types and supers.
🔑 THE question "does this in-place operator keep an UNSET receiver unset?" - asked of the RESOLVED operator symbol,
never of its spelling or the receiver's type name.
Detects unused captured variables in dynamic functions and classes (E11018).
Detects unused parameters in functions, methods, constructors, and service operations (E08091).
E08275:
Networking().urlOf(text) given text the compiler can know - decision U3 of
docs/architecture/EK9_URL_TYPE_DESIGN.md §0.True when the constructor relies on the hidden implicit
super(): it neither delegates with
this(...) (DelegatesWithThis) nor calls super(...) (CallsSuperExplicitly).Checks that if the aggregate is a generic class that the appropriate public constructors are in place.
Check if any dispatcher methods on the aggregate and ensure that they are valid.
Checks if a function extends another function and if it is abstract.
Validates literal values at compile time to catch semantically invalid literals
that the ANTLR lexer accepts structurally but that can never represent valid values.
Checks methods from various contexts, typically this is delegated to other functions.
If the Ek9 developer has used named parameters, then they must be validated.
Checks each operator: first its operator SEMANTICS - arguments, return type and purity, which need resolved types,
so this runs in phase 2 - then what every method and operator declaration is checked for
(
OperationDeclarationChecks, D5).Error when use of ParameterisedType has additional expression parameters in wrong context.
Checks the PATH value (if this is a path parameter) and ensures that the name appears in the path itself
on the operation.
Does a few checks on a PossibleGenericSymbol in terms of checking types and the generic type it is configured with.
Check that a service operation complies with EK9 rules and return types etc.
Error when a reference is attempted by the syntax is incorrect.
THE shared value-class vocabulary for the input-variation metric — one taxonomy, three consumers
(
docs/implementation/EK9_INPUT_VARIATION_CLASS_TAXONOMY.md):
the denominator counter (EquivalenceClassModel) — counts distinct ids per
type for the static opportunity space;
the runtime classifier (INPUT_CLASS_PROBE recorder) — places an actual runtime
value into one of these ids for the dynamic numerator (design §5);
the generator (EdgeValuePool, compiler-services) — holds representative
literals per id for ek9_generate_edge_case_tests.
A value's ownership kind (EK9_IR_OWNERSHIP_MODEL.md §3), and THE rule for the kind of the value an instruction
makes.
The variables of one source that a signal handler captures, by IDENTITY (design §13.11 S2c, option A): the outer
symbol each argument of a
SignalHandler implementation's capture list names.Tracks variable values through control flow for tautological condition detection.
Generates JVM bytecode for variable load and store operations.
Checks on the assignment during a declaration and emits an error if not valid.
Checks that variable declarations is acceptable.
Creates IR instructions for variable declarations.
Just holds details for retaining and registering a target for memory management.
Calls a supplier of main processing instructions and then adds in the memory management.
Get the name of the variable suitable for use in the IR.
Creates IR instructions for variable only declarations.
Focus on checking a variable only declaration, now that types are all known.
Accepts a variable only declaration and ensures the variable is recorded if appropriate, for transient flow checks.
Models a variable.
The types of some variables (or parameters), in order; empty when any of them has no type (an earlier error).
THE lines of a source that the formatter leaves as written - every pass asks this, never a private copy.
The lines to leave alone.
Compiler self-verification directive (NOT an end-user feature) asserting the Layer-2 symbolic
verdict for a construct (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §4).
Checks any
@Verified directives in the parsed module against the squirrelled Layer-2
verdict (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §4).Decides whether a member's visibility may legally be changed to a proposed access modifier -
the "declaration viability" of a
change_visibility refactoring.Outcome of asking whether a member's visibility (access modifier) may be changed to a proposed
value - the "declaration viability" layer used to gate the
change_visibility tooling and
to decide whether the IDE should even offer the refactor.Does a simple check (excluding any inheritance) for visibility rules on methods/operators on
aggregates.
Groups all the data needed to format a visual error display.
Formats compiler errors in a visual style similar to Rust/Elm compilers.
THE rule that
Void is never the type of a value (E10011, the formal specification's
WF-VOID-RESTRICTION).Checks if a symbol's type is Void and emits E10010 if so.
True for a stage that emits nothing until its whole input has ended: every stage that ends the demand segment
(
EndsDemandSegment) except async, which emits each result as its task completes.THE distance E11030 reports (
ConfusinglySimilarNamesOrError) - the weighted edit distance its rich message
describes, and nothing else: a character inserted, removed or changed costs 2 wherever it is (the first and last
positions included), two ADJACENT characters swapped cost 2 (one edit, as Damerau counts it -
title/titel) except at the FIRST letter (positions 0-1), where a swap is two changes
(latitude/altitude, 4 - Steve, 2026-10-12), and a change of case alone costs 1.Specialized generator for EK9 while loops.
Deals with checking the 'while' or 'do/while statement/expression.
Generates IR for while and do-while loops and expressions using CONTROL_FLOW_CHAIN.
Checks the while statement via the code analysers.
EK9 'while' or 'do/while' type symbol - we need a scope because we can declare new variables as part of the
pre-flow semantics.
THE whole
+ chain a + expression is part of - use it, never a private climb: + groups left
to right, so "Hello " + name + "!" is ("Hello " + name) + "!", and the chain is the outermost
+ reached by climbing while the parent is still one.THE wording of why a type has no
<=> although it asked for one with the bare default operator
(D58): the field whose type cannot be ordered, the type declaring it and - only where that is a super - that a
sub-type follows its super.THE removal of the terminal colour codes (SGR sequences,
ESC [ ... m) the pretty renderer emits from a
diagnostic handed to a program - an MCP tool result, an LSP publish, the IDE (harness issue I-03, 2026-09-17: a
30B model was shown [31m[1merror inside JSON).The source with every
@Error directive line removed - what a reader would type (ErrorDirectiveText).A stderr capture without the JVM's leading launcher lines and with a leading
Ek9FailureMarker line removed
(the rest unchanged); null is the empty string.A child JVM's stderr from its first line that is not a JVM launcher line (
IsJvmLauncherLine, which says
why); null stays null.THE expression inside any number of enclosing parentheses:
base for ((base)).A numeric literal's text with its
_ separators removed (1_000.5 reads as 1000.5).The bounded-model witness materialiser for the Symbolic/Contract scanner (M3): given an obligation
expressed as a predicate over a candidate input, enumerate the representative value-classes of a
type and return the first input that violates it — a concrete counterexample.
A concrete counterexample: which value-class it came from, its EK9-source literal, and its value.
Designed to represent one or more source files that are part of a workspace.
THE step for an operand declared
Any that may be a WRAPPER over a base value - a parameterised generic's
wrapper (D60: DictEntry <=> Any) or a constrained type (D74: Age <=> Any).THE grammar's write positions: which operator, if any, writes the thing an identifier occurrence names
(
SymbolWrites collects these over a symbol's uses).THE parameters an operation writes as
-> name as T (IR tidy W3.4, OPS-8): their declarations - slots the
caller owns, each with its coverage statement probe - and their symbols, the same ones.Very simple wrapper for binary contents.
Just a common base directory and a list of files with that common base.