ECS for Control: Review Guide
The review of an ECS program, check-point by check-point: every module before its kind, each module against its kind, the pairs of kinds, and the program as a whole; what each check reads, what must hold, and what a program without it is.
Overview
A review reads a program against the architecture's definitions and the discipline's constructs, and decides compliance. Every check-point here states a property of a program, says where it is read and what must hold, and says what a program without the property is. No check-point decides whether the program runs; the compiler and the kernel hold that.
The review is a walk in five parts:
- Part A, every module before its kind: the program is built, its module list is the linker's map, every module declares its kind. These are the tools' preconditions; a review by hand can pass over them.
- Part B, each module against its kind: one section per kind, self-contained, with the kind's declaration, its placement, its imports and its check-points.
- Part C, pairs of kinds: the interactions, one section per pair, read once both kinds are done.
- Part D, the program as a whole: check-points over all modules of one kind, or over the program.
- Part E, read by a person only: the facts not in the code or not decidable from it.
Part B is walked per partition: the program's skeleton and vocabulary first, then one partition at a time through its kinds in the order of the sections, then the kinds that gather over all partitions, then Parts C, D and E once. The order of the sections is the order of reading: each section presumes the ones before it.
Two files are open during the review: this guide, and the allow-lists file that applies to the program, the library's or the project's own copy. The allow-lists file holds every kind's import list in the notation of the ECS file and defines its own reading rules in its header; the import check-point of every kind reads against it, and the guide does not restate the lists.
Preparation
-
The sources at a named state. A commit or a tag; the review's subject is the sources as of that state.
-
The allow-lists file. The library's file for its version, or the project's copy. When the tools have run, the ECS file's allow-lists line names the file used.
-
The ECS file and the map file, when the tools have run. The ECS file records the facts the review looks at and the tools do not judge: every module's library imports, the constants a System takes from its
VALUESmodule, the deployment calls. The ECS map file states the evaluated values. Neither is required: every fact is in the sources, and the guide says where. -
The example program. A current example program of this document set is the worked instance of every construct, which can complement the guide where a construct's listing is not enough.
Terminology
Kinds. Every module of a program is of one kind, declared in a comment before its MODULE line, (* ECSKIND: SYSTEM Manifest Name Run *). The kind names are the vocabulary of this guide; a module name is the programmer's choice.
Roles and slots. A kind's roles are the exported items a module of the kind provides, written as slots in angle brackets: <storevar>, <buildproc>. The identifier that fills a slot is the module's own, declared as a parameter of the kind declaration in the order the kind section gives. A slot's suffix is its sort: var a variable, proc a procedure.
The import lists. The allow-lists file lists, per kind, the kinds a module may import and the framework modules it may import by name, each entry with a qualifier where the kind's placement restricts it: own partition, any partition, schedule 0 only, same level. The file's header defines the qualifiers and the inheritance between its groups. A program module of any other kind is a finding; a library module is never a finding and is recorded in the ECS file for the reviewer. One library module is checked: the transport an ADAPTER declares, read for its kind declaration, counts as a module of that kind for every importer, with no qualifier, since it lies in no directory of the program.
Check-points and readings. A check-point is named by its kind and a number, SYSTEM.7; a pair of kinds by both, SCHEDULE/PARTITION.1; a check-point over the program PROGRAM.1; a check-point on the build MODULE.2, on the kind declaration ECSKIND.1. A letter in place of the number names a check-point every kind has: SYSTEM.R for the roles, .X for the exports, .I for the imports, .P for the placement. A check-point's readings are lettered, and a reading is cited with its letter: SYSTEM.7-a.
Severity. Each check-point says what a program without its property is:
-
violation: not compliant in any case; the property is one of the architecture's fundamentals, or a form the discipline makes mandatory;
-
observation: not compliant by the constructs alone, but possibly compliant with sufficient understanding of the architecture; the fact is pointed out and the programmer assesses, or a stated reason is called for;
-
fact: nothing is decided; the reading records what the reviewer wants to look at;
-
unread: the construct may achieve what the architecture requires, but the tools cannot read it; the reviewer reads the source, and the ECS file carries the gap;
-
precondition: a condition of the tools' reading, not of the program's compliance; the tools refuse a program without it.
A violation the kernel also stops at start-up carries stops, and names the station: the static finding and the run-time stop are one fact seen twice.
Tool-checked, tool-recorded. A check-point's status line says Tool-checked when the tools decide it, and Tool-recorded when the tools write its fact into the ECS file, by reading letter where they hold a part; no mention means the check-point is read by the reviewer alone. The tools are described at the end.
Status line. Under every check-point heading, in italics: the severity, by reading where the readings differ, then the tool mark. Violation (a, b), fact (c). Tool-checked (a), tool-recorded (c). reads: readings a and b are violations, c is a fact, the tools check a and record c, and b is the reviewer's reading.
Admitted. The last line of every check-point names what a program may do against the property and still pass, with the reason stated; "none" means the property holds without exception.
Part A. Every Module, Before Its Kind
These check-points read the program's files without knowing any kind. The first five read the linker's map file and the build products, and hold for any Astrobe program: the program is linked, its module list is the map, every module is compiled as it stands and against current interfaces, the link products are built from everything. The last two read the kind declaration's syntax and vocabulary, before the kind it declares is known. All are preconditions of the tools; a review by hand, which reads the sources and knows each module's kind without a declaration, passes over them.
MODULE.1 The program is linked
Precondition. Tool-checked.
- a the program directory: exactly one linker map file lies in it
Admitted: none.
MODULE.2 The module list is the map
Observation. Tool-checked.
The map's file table is the program. A linked module whose code file lies inside the program directory and has its source is a program module, read for its declaration. A linked module without source is a library module by its mode of existence: it declares no kind, it is recorded by name, and every role demanded of it is checked at the use site against a declaration it does not have. A source in the tree the map does not list is not part of the built program: pointed out, then ignored.
- a the map's file table against the tree: every source in the tree is listed in the map
- b the map's file table: every linked module whose code file lies inside the program directory has its source
Admitted: a module parked in the tree for a later build; the reason is stated.
MODULE.3 Every module is compiled as it stands
Precondition. Tool-checked.
- a the source and code file timestamps: each module's code file is newer than its source; a module without source has nothing to compare
Admitted: none.
MODULE.4 Every module is compiled against current interfaces
Precondition. Tool-checked.
- a the code file and the imports' symbol file timestamps: an importer's code file is newer than the symbol files of the program modules it imports
Admitted: none.
MODULE.5 The link products are built from everything
Precondition. Tool-checked.
- a the binary against all build products: the binary is newer than every source, code and symbol file of the program
- b the map against all code files: the map is newer than every code file
Admitted: none.
ECSKIND.1 Exactly one kind declaration
Precondition. Tool-checked.
The declaration is a comment before the MODULE line whose text, with whitespace and asterisks stripped from both ends, starts with ECSKIND; its formatting inside the comment is free. Nothing after the MODULE line is read.
- a the comments before the
MODULEline: exactly one is a declaration - b that comment: it is the tag, an optional space, the colon, the kind and the parameters, separated by whitespace, newlines admitted, and nothing else
Admitted: none.
ECSKIND.2 The kind is in the vocabulary
Precondition. Tool-checked.
- a the declaration: the declared kind is one of the reference's kinds, spelt exactly
Admitted: none.
Part B. Each Module Against Its Kind
One section per kind, in the order of reading. Each section opens with the kind's purpose, its declaration with the roles, its placement, its import group and its construct in the Implementation, and then lists its check-points: the four every kind has, roles, exports, imports and placement, instantiated for the kind, and the kind's own. Where a kind restricts nothing on exports or placement, the check-point says so: the export list is read without a rule, the level is read from the directory.
SCHEDULE
Purpose: a schedule's module: creates its partitions, sets the boundary, registers their Systems, plans, commits and runs; schedule 0's module is the program's main module, its <gateproc> called from the module body; every other schedule's <gateproc> is started by a deployment call.
Declaration: <gateproc>, the gate
(* ECSKIND: SCHEDULE Run *)
Placement: the program directory.
Imports: the SCHEDULE group of the allow-lists file.
Construct: Implementation, § Schedules and the Boundary, The Schedule Modules.
SCHEDULE.R The declaration's parameter is <gateproc>, and it exists as a procedure
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: one parameter
- b the parameter: an Oberon identifier
- c the module against the declaration: the parameter names a procedure of the module; exported in every started schedule's module, local in schedule 0's module
Admitted: none.
SCHEDULE.X Nothing beyond <gateproc> is exported
Violation. Tool-checked.
- a the export list: a started schedule's module exports
<gateproc>and nothing else; schedule 0's module exports nothing
Admitted: none.
SCHEDULE.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
SCHEDULEgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the bring-up modules, the start-up anchor, the cores module, the error console, the clocks, and the diagnostic modules are expected here and in no other kind. Check that <gateproc>'s deployment stations configure this core's infrastructure only.
Admitted: none.
SCHEDULE.P The module lies in the program directory
Violation. Tool-checked.
- a the module's directory: the program directory itself
Admitted: none.
SCHEDULE.1 Every <gateproc> is parameterless; schedule 0's is local and called from the module body, every other schedule's is exported and started by its deployment call alone
Violation (a), observation (b, c). Tool-checked.
A core starts at a code address and takes nothing with it: a <gateproc> with parameters is no schedule's gate. Schedule 0's module brings the whole program up, and nothing calls into it; the local procedure guarantees that. For a started schedule the deployment call pins the gate as parameterless and exported.
- a the procedure heading, every schedule's module:
<gateproc>takes no parameters - b the procedure heading and the module body, schedule 0's module:
<gateproc>is a local procedure and is called from the module body - c the module body, every other schedule's module:
<gateproc>is not called from the module body
Admitted: none.
SCHEDULE.2 <gateproc> runs the station sequence in order
Violation.
The kernel's stations are Install, the partitions' <createproc> calls, Begin, the partitions' <addsystemsproc> calls, Plan, Commit, Run, each once and in this order; SetBoundary stands between Begin and Plan, once. Relax is optional and belongs between Begin and Plan; Begin clears the relaxed set, so a Relax before it is void, and a second Relax replaces the first. The kernel asserts a part of this at start-up and voids the rest silently, so the reviewer reads the whole sequence.
- a
<gateproc>'s statements:Kernel.Runis called, last - b
<gateproc>'s statements: the stations in order, each kernel station once;SetBoundaryafterBeginand beforePlan - c
<gateproc>'s statements:Kernel.Relax, when called, stands afterBeginand beforePlan, at most once
Admitted: none.
SCHEDULE.3 A deployment call starts a <gateproc>
Violation.
A deployment is read as the passing of a program procedure as a procedure actual. The deployment procedure itself comes from a library or from a module of the programmer's own, and the reviewer knows which it is.
- a the deployment calls in the module body and in
<gateproc>, every call that passes a program procedure as an actual: the actual is aSCHEDULE's<gateproc>
Admitted: none.
SCHEDULE.4 No waiver is in force
Observation.
A Kernel.Relax call is legitimate; whether the program is meant to ship with it is the reviewer's question. The plan check-points of Part D report their gaps whatever the waiver, and the reviewer matches them to the relaxed set.
- a
<gateproc>: noKernel.Relaxcall
Admitted: a development build with a stated waiver.
PERIODS
Purpose: the periods: one tick period per schedule, and the Systems' periods in ticks of their schedule.
Declaration: no roles
(* ECSKIND: PERIODS *)
Placement: the program directory.
Imports: the PERIODS group of the allow-lists file, which is empty.
Construct: Implementation, § The Definition Modules, Constructs.
PERIODS.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
PERIODS.X Nothing beyond constants and the variables the module body assigns is exported
Violation. Tool-checked.
A value the language cannot write as a constant, a record, is exported as a variable, and the module body assigns it; the body does nothing else, which is read by hand. A private variable, type or procedure reaches no constant and is nobody's concern. A private constant, the intermediate of a computed one, is the author's choice.
- a the export list: constants, and variables the module body assigns
Admitted: none.
PERIODS.I Nothing is imported
Violation. Tool-checked.
- a the import list: empty; a
PERIODSmodule declares constants and needs no module
Admitted: none.
PERIODS.P The module lies in the program directory
Violation. Tool-checked.
- a the module's directory: the program directory itself
Admitted: none.
A schedule's tick period is a millisecond count and a System's period a count of its schedule's ticks; that the denominations are right is read by the reviewer, Part E.
RESOURCES
Purpose: the resource choices: library handles, chip units and pins, exception priorities, each an authored choice in the owning module's vocabulary.
Declaration: no roles
(* ECSKIND: RESOURCES *)
Placement: the program directory.
Imports: the RESOURCES group of the allow-lists file, which names no kind.
Construct: Implementation, § The Definition Modules, Constructs.
RESOURCES.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
RESOURCES.X Nothing beyond constants is exported
Violation. Tool-checked.
- a the export list: constants only
Admitted: none.
RESOURCES.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds: no program module of any kind
- b the import list: every imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the owning modules, imported for their vocabulary, a driver's unit, pin or priority constants. Check that each import serves a constant's vocabulary and that nothing is called.
Admitted: none.
RESOURCES.P The module lies in the program directory
Violation. Tool-checked.
- a the module's directory: the program directory itself
Admitted: none.
PARTITION
Purpose: the partition module: creates the partition's world and registers its Systems.
Declaration: <createproc> <addsystemsproc>
(* ECSKIND: PARTITION Create AddSystems *)
Placement: its own partition directory, named as the module by convention.
Imports: the PARTITION group of the allow-lists file.
Construct: Implementation, § The Main Program and the Partitions, Constructs.
PARTITION.R The declaration's parameters are <createproc> and <addsystemsproc>, and both exist as exported procedures
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: two parameters
- b each parameter: an Oberon identifier
- c the export list against the declaration: each parameter names an exported procedure of the module
Admitted: none.
PARTITION.X Nothing beyond the two procedures is exported
Violation. Tool-checked.
- a the export list:
<createproc>and<addsystemsproc>, nothing else
Admitted: none.
PARTITION.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
PARTITIONgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: device modules and the error code catalogue are expected at creation, for handles and pins. Check that each is used at creation and not after.
Admitted: none.
PARTITION.P The module lies in its own partition directory
Violation (a, b), observation (c). Tool-checked.
A partition directory is a first-level directory of the program directory holding exactly one PARTITION module. Its name equals the module's by convention, and the generator writes it so.
- a the module's directory: a first-level directory of the program directory
- b that directory: it holds no second
PARTITIONmodule - c that directory's name: it equals the module's
Admitted: none.
PARTITION.1 Both procedures are parameterless
Observation. Tool-checked.
A parameter would let a fact into the creation that the architecture does not control. One may be a deliberate choice, a world-creation fact passed down from the schedule; the reason is stated.
- a the procedure headings:
<createproc>and<addsystemsproc>take no parameters
Admitted: a stated reason for the parameter.
PARTITION.2 The registration procedure registers each System once, with its declared roles
Violation (a, b), observation (b, registered nowhere). Tool-checked.
Each Kernel.AddSystem call names a System's run procedure, manifest and name; the SYSTEM module's declaration is the authority for the names. A System registered twice produces its tokens twice and stops at Plan; a System registered nowhere may be parked for a build, and the reason is stated.
- a each
Kernel.AddSystemcall in<addsystemsproc>against theSYSTEMmodules' declarations: run, manifest and name are one module's declared<runproc>,<manifestvar>and<namevar>, and the module is aSYSTEMof this partition's directory - b the calls against the directory listing: every
SYSTEMof the directory is registered exactly once
Admitted: a System present and unregistered, with the reason stated.
<createproc> creates the partition's world in phases of its own organisation and allocates the devices and writers the partition owns. What it must show is read as pairs: the call of its STATE's <buildproc> and an initialisation site for every store leaf, Part C. Which leaf is a handle, and whether the right device lands in it, is read by the reviewer, Part E. VALUES.1 is read here: no VALUES constant is an array dimension in the module.
WIRING
Purpose: the partition's structure: cardinalities and role-binding indices.
Declaration: no roles
(* ECSKIND: WIRING *)
Placement: its partition's directory.
Imports: the WIRING group of the allow-lists file.
Construct: Implementation, § The Definition Modules, Constructs.
WIRING.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
WIRING.X Nothing beyond constants is exported
Violation. Tool-checked.
A private variable, type or procedure reaches no constant and is nobody's concern; a module body here is the one line a reviewer cannot miss in a screen of constants. A private constant, the intermediate of a computed one, is the author's choice.
- a the export list: constants only
Admitted: none.
WIRING.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
WIRINGgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: PERIODS serves the tick conversion; a module imported for a type and the error code catalogue are expected; anything else, check what it serves.
Admitted: none.
WIRING.P The module lies in its partition's directory
Violation. Tool-checked.
- a the module's directory: a partition directory, flat
Admitted: none.
The store's array lengths name these constants, STATE.4. A structural fact two partitions share, a size or a protocol value across a crossing or a transport, is declared in each partition's WIRING and held equal by CONS.
VALUES
Purpose: the partition's tuning values: rates, thresholds, baudrates, anything changeable without touching structure.
Declaration: no roles
(* ECSKIND: VALUES *)
Placement: its partition's directory.
Imports: the VALUES group of the allow-lists file.
Construct: Implementation, § The Definition Modules, Constructs.
VALUES.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
VALUES.X Nothing beyond constants and the variables the module body assigns is exported
Violation. Tool-checked.
A value the language cannot write as a constant, a record, is exported as a variable, and the module body assigns it; the body does nothing else, which is read by hand. A private variable, type or procedure reaches no constant and is nobody's concern. A private constant, the intermediate of a computed one, is the author's choice.
- a the export list: constants, and variables the module body assigns
Admitted: none.
VALUES.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
VALUESgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: PERIODS serves the tick conversion; a module imported for a type and the error code catalogue are expected; anything else, check what it serves.
Admitted: none.
VALUES.P The module lies in its partition's directory
Violation. Tool-checked.
- a the module's directory: a partition directory, flat
Admitted: none.
VALUES.1 A VALUES constant is never an array dimension
Violation. Tool-checked.
This check-point is read in every module whose import group names VALUES: CONS, PARTITION, SYSTEM and LOCKED. A count is what a structure is: how many of something exists is consulted where the world is created and lives with the partition's WIRING, apart from the tuning values it parameterises, so that structure changes loudly. A size behind a module whose definition is "changeable without touching structure" is the silent extension the architecture holds hazardous. A VALUES constant may index an array: a protocol code is a position in a table by its nature, a System must be able to name it, and a code outside the table is caught where the table is filled. STATE never imports VALUES, so the store's dimensions are STATE.I's reading.
- a every array type declared in the importing module: no dimension names a
VALUESconstant
Admitted: none.
What a VALUES constant is, how it is written and who reads it is the programmer's decision. A System may read VALUES; what it reads is recorded, SYSTEM.9.
STATE
Purpose: the partition's variable Component state: the store record and its build procedure.
Declaration: <storevar> <buildproc>
(* ECSKIND: STATE S Build *)
Placement: its partition's directory.
Imports: the STATE group of the allow-lists file.
Construct: Implementation, § Components State, Constructs.
STATE.R The declaration's parameters are <storevar> and <buildproc>, and each exists with its sort
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: two parameters
- b each parameter: an Oberon identifier
- c the export list against the declaration:
<storevar>names an exported variable,<buildproc>an exported procedure
Admitted: none.
STATE.X Nothing beyond the two roles and the module's types is exported
Violation. Tool-checked.
The store types and the named array types are exported for the System signatures, which bind to them.
- a the export list:
<storevar>,<buildproc>and the module's types; no constant, no other variable or procedure
Admitted: none.
STATE.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
STATEgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: a module imported for a type, the port and buffer protocol modules, and the error code catalogue are expected. A STATE module calls nothing; check that each import serves a type.
Admitted: none.
STATE.P The module lies in its partition's directory
Violation. Tool-checked.
- a the module's directory: a partition directory, flat
Admitted: none.
STATE.1 The store variable points to a store record declared here; the build procedure is parameterless
Violation (a), observation (b). Tool-checked.
A parameter on <buildproc> would let a fact into the build that the architecture does not control; one may have its reason, which is stated.
- a the TYPE and VAR sections:
<storevar>is an exported variable of a pointer type declared in the module, pointing to a record declared in the module - b the procedure heading:
<buildproc>takes no parameters
Admitted: a stated reason for the parameter.
STATE.2 The store holds values and handles only
Violation. Tool-checked (a).
A device handle and an address are the same INTEGER to the compiler; the declaration tells them apart from nothing, the initialisation site does. The framework uses addresses everywhere, never through address arithmetic, each looked up in its device module, so no construct marks one.
- a the leaves' declared types: no pointer type, no procedure type
- b the leaves' initialisation sites in
<createproc>, which PARTITION/STATE.2 lists: no INTEGER leaf receives an address
Admitted: none.
STATE.3 The build procedure allocates the store and nothing else
Violation. Tool-checked.
The values are given by the partition in <createproc>, PARTITION/STATE.2. An allocation after creation is the run-time heap lock's stop, not a static reading.
- a
<buildproc>: it contains theNEWof<storevar>and its assertion - b
<buildproc>: it assigns no leaf of<storevar>
Admitted: none.
STATE.4 The store's array lengths are WIRING constants
Observation. Tool-checked.
A literal length is a judgement call like a parameter on a role procedure; the reason is stated. A VALUES constant cannot reach a store dimension, since STATE never imports VALUES, STATE.I.
- a the record against the partition's
WIRING: every array's cardinality is aWIRINGconstant
Admitted: a stated reason for the literal.
STATE.5 Nothing runs or is declared beside the store type, the store variable and the build procedure
Violation. Tool-checked.
With <buildproc> the only exported procedure and the module body empty, nothing else runs at load, and no NEW has a caller but <buildproc>.
- a the module body: empty
- b the procedures:
<buildproc>alone
Admitted: none.
The leaves' initialisation is read as a pair, PARTITION/STATE.2; the tokens that mirror the leaves, STATE/TOKENS.1.
LOCKED
Purpose: the partition's locked Component state: written once at load, read-only thereafter, with its interface record for other partitions.
Declaration: <lockedvar> <interfacevar>, both optional: the declaration names both, and a module may declare one or neither
(* ECSKIND: LOCKED L I *)
Placement: its partition's directory.
Imports: the LOCKED group of the allow-lists file.
Construct: Implementation, § Components Locked, Constructs.
LOCKED.R The declaration's parameters are <lockedvar> and <interfacevar>, and each present one is an exported variable
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: two parameters, the optional roles included
- b each parameter: an Oberon identifier
- c the export list against the declaration: each parameter that names an item of the module names an exported variable; an optional role may be absent from the module
Admitted: none.
LOCKED.X Nothing beyond the two variables and the module's types is exported
Violation. Tool-checked.
The roles are variables; an exported procedure plays no declared role. The named types are exported for the System signatures, which bind to them.
- a the export list:
<lockedvar>and<interfacevar>, when present, and the module's types; no procedure, no other variable, no constant
Admitted: none.
LOCKED.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
LOCKEDgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: device modules for device handles and types, and the error code catalogue, are expected; check that each serves a locked value or a type. VALUES.1 is read here: no VALUES constant is an array dimension in the module.
Admitted: none.
LOCKED.P The module lies in its partition's directory
Violation. Tool-checked.
- a the module's directory: a partition directory, flat
Admitted: none.
LOCKED.1 Both are record variables, not pointers
Violation. Tool-checked.
An exported variable is read-only for every importer by the language, and a record variable keeps it so; an exported pointer would let an importer write through a local alias, the store's own idiom, and defeat LOCKED.2.
- a the VAR section:
<lockedvar>and<interfacevar>, when declared, are each an exported variable of a record type
Admitted: none.
LOCKED.2 Written in the module body only
Violation. Tool-checked.
- a the module: every assignment to
<lockedvar>or<interfacevar>is in the module body or in a local procedure the module body reaches
Admitted: none.
LOCKED.3 Every locked leaf has an initialisation site
Violation. Tool-checked.
A necessary condition: nothing is zeroed at load, so a leaf without a site is uninitialised. A leaf with a site may still miss its value at run time, the loop that stops short, the branch around the assignment, the VAR parameter the callee never writes; that is read by the reviewer, Part E. The parameter mode is read from the callee's procedure heading, through the import alias; for a library procedure without source the mode is unknowable and the actual counts as a site, a miss rather than a false finding. A local procedure that takes the record or a part of it as a VAR parameter is followed with the actual's path in place of the formal's path.
- a the record types against the module body and the local procedures it reaches: every leaf of
<lockedvar>and<interfacevar>, through nested records and arrays, appears at least once in a position that can write it: the left side of:=, the actual of a VAR parameter, or the operand ofCLEAR, the leaf itself or an enclosing record or array; array indices are abstracted,L.a[i].xcovers the patha[].x
Admitted: none.
TOKENS
Purpose: the partition's tokens, one per store variable; its surfaces; its token names.
Declaration: <tokensvar> <surfacesvar> <namesvar>, the latter two optional: the declaration names all three, and a module may lack the surfaces or the names
(* ECSKIND: TOKENS L I Names *)
Placement: its partition's directory.
Imports: the TOKENS group of the allow-lists file.
Construct: Implementation, § Tokens, Constructs.
TOKENS.R The declaration's parameters are the three roles, and each present one is an exported variable
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: three parameters, the optional roles included
- b each parameter: an Oberon identifier
- c the export list against the declaration:
<tokensvar>names an exported variable;<surfacesvar>and<namesvar>, when present in the module, name exported variables
Admitted: none.
TOKENS.X Nothing beyond the three variables is exported
Violation. Tool-checked.
- a the export list:
<tokensvar>,<surfacesvar>and<namesvar>, when present, nothing else
Admitted: none.
TOKENS.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
TOKENSgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the error code catalogue is expected and nothing else.
Admitted: none.
TOKENS.P The module lies in its partition's directory
Violation. Tool-checked.
- a the module's directory: a partition directory, flat
Admitted: none.
TOKENS.1 The tokens variable is a record of INTEGER leaves
Violation. Tool-checked.
- a the type:
<tokensvar>is an exported record variable - b the type: every leaf, through nested records, is an INTEGER; no arrays
Admitted: none.
TOKENS.2 Every token is assigned once, a constant expression
Violation. Tool-checked.
- a the module body: each leaf of
<tokensvar>is assigned exactly once - b the module body: each right side is an expression over the program's constants and literals; no loop, no procedure, no variable
Admitted: none.
TOKENS.3 The ordinals are dense from the base
Violation. Tool-checked.
The base is the one TOKENBASES constant the expressions reach, TOKENBASES/TOKENS.1.
- a the evaluated leaves: the values minus the base are exactly 0 to n-1, no repeat
Admitted: none.
TOKENS.4 A surface is a braced set of the module's own tokens
Violation. Tool-checked.
- a the module body: every leaf of
<surfacesvar>is a SET assigned once from a braced set - b the module body: the braced set's members are leaves of
<tokensvar>
Admitted: none.
TOKENS.5 Every token has a name
Violation. Tool-checked.
- a the module body:
<namesvar>has one entry per token, at the token's ordinal, and no more
Admitted: none.
TOKENS.6 The back-assert holds
Observation (a), violation (b). Tool-checked.
The back-assert is the module's own check that its count agrees with TOKENBASES, the program's own start-up assertion run early. The invariant behind it, one authority for the allocation, is proven on the evaluated ranges whether or not the module asserts, PROGRAM.3; a module without the assertion departs from the proposed form and loses nothing structural, and the programmer assesses.
- a the module body: an assertion referencing a
TOKENBASESconstant is present - b the module body and
TOKENBASES: both sides of that assertion are constant expressions, and the assertion, evaluated as written, is true
Admitted: the absence of the assertion, with the reason stated.
The tokens are read against the store, STATE/TOKENS.1; against their base, TOKENBASES/TOKENS.1; against the names table, TOKENNAMES/TOKENS.1; and against the manifests, SYSTEM/TOKENS.1.
SYSTEM
Purpose: one System: its manifest, its name, its run procedure.
Declaration: <manifestvar> <namevar> <runproc>
(* ECSKIND: SYSTEM Manifest Name Run *)
Placement: a partition directory.
Imports: the SYSTEM group of the allow-lists file.
Construct: Implementation, § System Modules, The Module.
SYSTEM.R The declaration's parameters are the three roles, and each exists with its sort
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: three parameters
- b each parameter: an Oberon identifier
- c the export list against the declaration:
<manifestvar>and<namevar>name exported variables,<runproc>an exported procedure
Admitted: none.
SYSTEM.X Nothing beyond the roles is exported
Violation. Tool-checked.
- a the export list:
<manifestvar>,<namevar>and<runproc>, nothing else
Admitted: none.
SYSTEM.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
SYSTEMgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: device modules read by the System and the error code catalogue are expected; the kernel beyond its access procedures, the plan report or a bring-up module among them means a System or a bring-up module in disguise. No System configures the infrastructure.
Admitted: none.
SYSTEM.P The module lies in a partition directory
Violation. Tool-checked.
- a the module's directory: a partition directory, flat
Admitted: none.
SYSTEM.1 The name is assigned
Observation. Tool-checked.
The name serves the plan report alone; nothing is zeroed at load, so a System without a name prints garbage there, bounded by the name's length. A corrupt review instrument, not a wrong program.
- a the module body:
<namevar>is assigned at least once, in the module body itself
Admitted: none.
SYSTEM.2 The module body assigns the name and the manifest, and nothing else
Violation. Tool-checked.
A System's module body declares, it does not run: a System runs over its state in <runproc>, whose helpers are its own. Nothing is zeroed at load, so a set of the manifest that is neither assigned nor cleared is garbage, and the ECS file would record it empty.
- a the module body's statements: each is the
<namevar>assignment,CLEAR(<manifestvar>), or an assignment to one of the six sets of<manifestvar> - b each set assignment's right side: a set expression of braced tokens and bare surfaces, nothing computed
- c every set of
<manifestvar>: assigned in the module body, orCLEAR(<manifestvar>)precedes the first set assignment
Admitted: none.
SYSTEM.3 A System holds no state
Violation (a), observation (b). Tool-checked.
A module-level type is neither state nor a fact with an authority: it carries no value and fixes nothing program-wide. Three readings of one: the shape of a scratch record <runproc> uses, which concerns no check-point; a shape that mirrors part of the store, which belongs to STATE; a pointer type, which points at an allocation in <runproc>, the run-time heap lock's stop.
- a the VAR section: no variable beyond
<manifestvar>and<namevar> - b the TYPE section: every module-level type, pointed out
Admitted: none.
SYSTEM.4 No local constants beyond the name string
Violation. Tool-checked.
A constant in a System is a fact without an authority module: a tuning value belongs to VALUES, a structural fact to LOCKED or TOKENS, a name to TOKENNAMES. Every fact has one authority.
- a the CONST section: no constant beyond the name string
Admitted: none.
SYSTEM.5 The run procedure runs to completion
Violation.
- a
<runproc>'s control flow and the procedures it reaches: no waiting loop on a store value or a transport predicate; no call that yields
Admitted: none.
SYSTEM.6 The kernel's station procedures are off limits
Violation. Tool-checked.
A System reaches the kernel for its types and its run-time access procedures. The check-point names the forbidden procedures, not the permitted ones: the access procedures grow with the kernel, the stations do not.
- a a search for
Kernel.in the module: no call of a station procedure,Install,Begin,Relax,AddSystem,SetBoundary,Plan,Commit,Run, nor of the run-context procedureGetRunCtx
Admitted: none.
SYSTEM.7 A foreign TOKENS or LOCKED module is used through its interface record only
Violation. Tool-checked.
The import of a foreign partition's TOKENS or LOCKED module is admitted by the SYSTEM group; this check-point is the usage side. What a partition publishes for others is its surfaces and its interface record, never its tokens or its locked values one by one.
- a the references into other partitions' modules, the
<manifestvar>assignment included: into aTOKENSmodule, its<surfacesvar>only; into aLOCKEDmodule, its<interfacevar>only
Admitted: none.
SYSTEM.8 No self-loop: no token is in C or Cx and also in O, P or Px; Cp is free
Violation, stops at Plan. Tool-checked.
The kernel's self-loop check at Plan evaluates the same set per System. Cp is excluded by design: a System may consume its own previous-pass value, since the consumer runs before the producer.
- a
<manifestvar>: the set(C + Cx) * (O + P + Px)is empty
Admitted: none.
SYSTEM.9 The VALUES constants a System names are recorded
Fact. Tool-recorded.
What a System reads from its VALUES module is the programmer's decision; the list is recorded for the reviewer to look at.
- a the import list and a search for the
VALUESmodule's name: everyVALUESconstant the System names, recorded in the ECS file with the System
Admitted: none.
VALUES.1 is read here: no VALUES constant is an array dimension in the module. A System is read against its store and its tokens as pairs, SYSTEM/STATE.1 to 4 and SYSTEM/TOKENS.1.
ADAPTER
Purpose: the store access procedures over one transport, store-handle-indexed where the store path is an array, and the procedure types that carry their direction.
Declaration: <transport>, the module name of its transport; no role
(* ECSKIND: ADAPTER PeriodPort *)
Placement: its partition's directory.
Imports: the ADAPTER group of the allow-lists file.
Construct: Implementation, § Ports and Adapters, Adapters.
ADAPTER.R The declaration's parameter names its transport
Precondition. Tool-checked.
That the named module exists and is a transport is the pair's reading, TRANSPORT/ADAPTER.1.
- a the declaration: one parameter
- b the parameter: an identifier of a module name's form
Admitted: none.
ADAPTER.X Procedure types, procedures and the transport's value type only are exported
Violation. Tool-checked.
The transport's value type is re-exported so that a System imports the adapter and nothing of the transport.
- a the export list: procedure types, procedures and the transport's value type; nothing else
Admitted: none.
ADAPTER.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
ADAPTERgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: service modules and the error code catalogue are expected; a device module is not. An adapter moves values and a BINDING operates hardware; check the source.
Admitted: none.
ADAPTER.P The module lies in its partition's directory
Violation. Tool-checked.
- a the module's directory: a partition directory, flat
Admitted: none.
ADAPTER.1 One STATE import, the store reached through it
Violation. Tool-checked.
- a the import list: exactly one
STATEmodule - b the exported procedures: every store reference is
<storevar>.<path>or a local assigned from<storevar>, and<path>is a store variable
Admitted: none.
ADAPTER.2 The store handle is taken iff a reached store path is an array, uniformly
Violation. Tool-checked.
A Component of one instance is addressed by the procedure alone, the module having selected the transport and the path; an index into a one-element array selects nothing. Several array paths under one handle are co-indexed; a module with an array path and a single path takes the handle, and one path selects by it. An array is one leaf and one token, as a single instance is.
- a the procedure headings against the
STATEdeclarations: the exported procedures take the store handle as their first parameter iff a store path the module reaches is an array; all of them or none - b the procedure bodies: every array path reached is indexed by the store handle; one argument per Component
Admitted: none.
ADAPTER.3 The procedure type carries the direction
Fact. Tool-recorded.
That a procedure type's modes are the modes of its procedure is checked by the compiler: wherever a System's procedure-typed formal receives the adapter's procedure, procedure-type compatibility includes the parameter modes, which are the direction.
- a the procedures: the direction, read from the parameter modes: a VAR parameter beyond the store handle is a get, a result a read, else a put; recorded in the ECS file
Admitted: none.
ADAPTER.4 The adapter's policy is intended
Violation.
- a each procedure: what it does when the transport's precondition fails, and what it records; a recorded observation goes to a store variable the calling System's manifest covers
Admitted: none.
ADAPTER.5 Nothing is declared beside the procedures and their types
Violation. Tool-checked.
An adapter is a route, not a party: stateless.
- a the module: no module variable; no constant, no type beyond the procedure types and the transport's value type
- b the module body: empty
Admitted: none.
What an adapter exports over its transport is the programmer's decision, within ADAPTER.X and ADAPTER.1 to 3. Its transport and the agreement of their modes are read as the pair, TRANSPORT/ADAPTER.1 and 2; its paths against the store and the tokens, STATE/ADAPTER.1 and TOKENS/ADAPTER.1.
The Transports: SPORT, QPORT, RBUFFER, BUFFER
Purpose: a transport: SPORT the sampling port, QPORT the queueing port, RBUFFER the ring buffer, each identical in interface to the framework's reference implementation of its kind; BUFFER a transport of unstated organisation with a hand-written adapter.
Declaration: no roles; the canonical interface is the kind
(* ECSKIND: SPORT *)
Placement: a partition's directory or a sub-directory of it when one partition's store holds its instances; the program directory or a helper directory when several do; or a library. Either level is admitted; the directory decides which partition, if any, the module belongs to.
Imports: the group of the declared kind in the allow-lists file, which names no kind.
Construct: Implementation, § Ports and Adapters, Per-Seam Port Modules.
The four kinds share the check-points of this section, identified TRANSPORT.
TRANSPORT.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
TRANSPORT.X The export list is the canonical interface
Observation.
The kinds restrict nothing on exports of their own: a canonical kind's export list is read against the reference implementation, TRANSPORT.1; a BUFFER exports what its adapter needs.
- a the export list: for
SPORT,QPORTandRBUFFER, read by TRANSPORT.1; forBUFFER, the module's own, each item serving its adapter
Admitted: any export of a BUFFER.
TRANSPORT.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds: no program module of any kind
- b the import list: every imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the protocol module of the kind and the error code catalogue are expected; anything else, check what it serves.
Admitted: none.
TRANSPORT.P The module's directory decides its partition
Fact. Tool-recorded.
- a the module's directory: a partition directory or a sub-directory of one places the module in that partition, the program directory or a helper directory at the program level; recorded in the ECS file with the module
Admitted: either level.
TRANSPORT.1 A canonical kind has the canonical interface
Observation. Tool-checked.
A port extended for a purpose may have its reason, which is stated. BUFFER has no canonical interface. By hand: the module against the reference implementation of its kind in the library's ref/ directory for the library version.
- a the export list against the reference implementation of the declared kind:
SPORTandQPORTexport exactly its procedures with its signatures, the value or message type aside;RBUFFERexports a subset of its access procedures, element and multiple put and get, Empty, Full, Free and Count, each with its signature
Admitted: an extension with its reason stated.
TRANSPORT.2 A canonical transport's procedure bodies follow the reference implementation
Violation.
Each algorithm module's protocol is one correct order: the sampling port's index, write and publish; the ring buffer's precondition assertion, index with write or read, publish or release with the count. A statement that differs is a correctness fault, not a style choice, so the comparison is exact. The adjust region is the reference implementation's own: for SPORT the value type; for QPORT the message type and the message count; for RBUFFER the value type and the chosen access subset. By hand: a diff of the module against its reference implementation, with every difference inside the adjust region.
- a every exported procedure's body against its body in the reference implementation, outside the adjust region: the statement sequences are identical, the algorithm module's calls in the reference implementation's order
Admitted: none.
BINDING
Purpose: a partition's device seam: a module that operates interface hardware for the partition's Systems, configured at the partition's creation and called by its Systems at run time.
Declaration: no roles
(* ECSKIND: BINDING *)
Placement: its partition's directory or a sub-directory of it.
Imports: the BINDING group of the allow-lists file.
Construct: Implementation, § Bindings and Handles, Constructs.
A BINDING module is configured, never informed by import: a fact it needs from the definition arrives as a parameter, at the partition's <createproc> or at the System's call. It is imported by its own partition's PARTITION and SYSTEM modules alone; a foreign System importing it is cross-partition device sharing. Neither an ADAPTER nor a transport imports one, both being software-to-software bridges with no business with a device. No tool verifies that the module operates hardware, a device module being a library module like any other; the declaration asserts it.
BINDING.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
BINDING.X The export list is the module's own
Observation.
The kind restricts nothing on exports: the interface is what the partition's <createproc> configures and its Systems call.
- a the export list: procedures that operate the partition's device, with the handles and types they take; what each serves is read with BINDING.I-b, against the device modules imported
Admitted: any export.
BINDING.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
BINDINGgroup of the allow-lists file: every imported program module is of a kind the group names, with the group's qualifier, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the device modules are what the kind is for; check that the hardware operated is the partition's own, RESOURCES naming the owner.
Admitted: none.
BINDING.P The module lies in its partition's directory or below it
Violation. Tool-checked.
- a the module's directory: a partition directory, or a sub-directory of one
Admitted: none.
BINDING.1 A module variable is pointed out
Observation. Tool-checked.
What the variable holds is read by the reviewer, Part E, "No caching below the store": on the synchronous control path nothing is held between calls beyond a device's technical state behind its handle; an asynchronous binding holds transfer state only.
- a the VAR section: every module variable, pointed out
Admitted: a device's technical state; the transfer state of an asynchronous binding.
OTHER
Purpose: a module the definition places but says nothing about, tracked by existence only; the kind of every module that is of no other kind.
Declaration: no roles
(* ECSKIND: OTHER *)
Placement: the program level, in the program directory or a helper directory, or a partition's directory or a sub-directory of it. Either level is admitted; the directory decides the module's level.
Imports: the OTHER group of the allow-lists file.
Construct: Implementation, § Bindings and Handles, Constructs.
An OTHER module is configured, never informed by import: a fact it needs from the definition arrives as a parameter, at the partition's <createproc> or at the System's call. This is the library module's stance applied inside the tree, and it makes the helper portable between programs. A parameter carries a value, a handle or a procedure at run time, never an array length or a type; a helper that would need a WIRING cardinality for a declaration is playing a role that belongs in STATE or LOCKED.
OTHER.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
OTHER.X The export list is the module's own
Observation.
The kind restricts nothing on exports.
- a the export list: what each item serves is read with OTHER.I-b; an exported variable is read by OTHER.1
Admitted: any export.
OTHER.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
OTHERgroup of the allow-lists file: every imported program module is anOTHERmodule of the importer's level, a partition's helper importing its partition's helpers, a program-level helper importing program-level helpers - b the import list: every imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the kernel, the plan report or a bring-up module among them means a System or a bring-up module in disguise; check what each import serves.
Admitted: none.
OTHER.P The module's directory decides its level
Fact. Tool-recorded.
- a the module's directory: the program directory or a helper directory places the module at the program level, a partition directory or a sub-directory of one in that partition; recorded in the ECS file with the module
Admitted: either level.
OTHER.1 A module variable is pointed out
Observation. Tool-checked.
What the variable is for is read by the reviewer, Part E, "No caching below the store": a synchronous helper holds nothing between calls beyond a device's technical state; a stateful helper imported by two Systems is a channel beside the store.
- a the VAR section: every module variable, pointed out
Admitted: a device's technical state.
TOKENBASES
Purpose: the program-wide token allocation: each partition's count, its base, the total against the kernel's capacity.
Declaration: no roles
(* ECSKIND: TOKENBASES *)
Placement: the program directory.
Imports: the TOKENBASES group of the allow-lists file.
Construct: Implementation, § Tokens, Constructs.
TOKENBASES.R The declaration has no parameters
Precondition. Tool-checked.
- a the declaration: no parameter
Admitted: none.
TOKENBASES.X Nothing beyond constants and the token name type is exported
Violation. Tool-checked.
The token name type lives here because a TOKENS module imports nothing but TOKENBASES, so the plan report module stays out of its reach and free of any kind dependency.
- a the export list: constants, and at most one type, the token name type
Admitted: none.
TOKENBASES.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
TOKENBASESgroup of the allow-lists file: no program module of any kind; the kernel, for its capacity constant, is the one framework module named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the error code catalogue is expected and nothing else.
Admitted: none.
TOKENBASES.P The module lies in the program directory
Violation. Tool-checked.
- a the module's directory: the program directory itself
Admitted: none.
TOKENBASES.1 Constants, the token name type, an asserting body
Violation.
Which constant is a partition's count, which its base and which the total is not readable without a naming rule the architecture does not impose; the allocation is checked on the evaluated token values instead, TOKENS.3, TOKENS.6 and PROGRAM.3. That the constants are the counts and the running sum they read as, and that the body asserts the total against the kernel's capacity, is read by the reviewer, Part E.
- a the declarations: exported constants; at most one exported type, the token name type; no variable, no procedure
- b the module body: every statement is an assertion over the module's own constants and the kernel's
Admitted: none.
TOKENNAMES
Purpose: the program-wide token name table, gathered from the partitions' TOKENS modules, for the plan report.
Declaration: <namesvar>
(* ECSKIND: TOKENNAMES Names *)
Placement: the program directory.
Imports: the TOKENNAMES group of the allow-lists file.
Construct: Implementation, § Tokens, Constructs.
TOKENNAMES.R The declaration's parameter is <namesvar>, and it exists as an exported variable
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: one parameter
- b the parameter: an Oberon identifier
- c the export list against the declaration: the parameter names an exported variable of the module
Admitted: none.
TOKENNAMES.X Nothing beyond <namesvar> is exported
Violation. Tool-checked.
- a the export list:
<namesvar>, nothing else
Admitted: none.
TOKENNAMES.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
TOKENNAMESgroup of the allow-lists file: every imported program module is of a kind the group names, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the plan report module is expected, the table being for it; anything else, check what it serves.
Admitted: none.
TOKENNAMES.P The module lies in the program directory
Violation. Tool-checked.
- a the module's directory: the program directory itself
Admitted: none.
TOKENNAMES.1 Every partition's names are collected
Observation.
The gathering is form-free, loops, a local procedure, index arithmetic, so it can copy a table over incompletely and leave a valid token without a name. The table serves the plan report alone: a corrupt review instrument, not a wrong program. The plan report prints a cleared entry as the token's number and an undefined one as garbage, so a clearing of the table before the gathering makes a missed token visible at the first run; the clearing is a programming choice. The decidable part is the pair, TOKENNAMES/TOKENS.1.
- a the module body and the local procedures it reaches, against the
TOKENSmodules andTOKENBASES: each partition's whole names table lands at that partition's base, entry by entry; by hand, the gathering statements against each<namesvar>'s length and each base constant
Admitted: none.
CONS
Purpose: the consistency module: the assertions that hold across partitions' definitions, one station of schedule 0's sequence, run before any partition is created in any schedule, so that a failed assertion halts the program before anything exists. One per program.
Declaration: <assertproc>
(* ECSKIND: CONS Assert *)
Placement: the program directory.
Imports: the CONS group of the allow-lists file.
Construct: Implementation, § The Main Program and the Partitions, The Consistency Module.
Assertions between partitions of different schedules are the normal case: two partitions that share a size or a protocol value each declare it, neither importing the other's WIRING or VALUES, and the shared values are those a crossing or a transport connects. With WIRING and VALUES the only program imports and both exporting definition values alone, constants and the variables their bodies assign, every imported operand is a definition value; an assertion over literals or private constants is the programmer's business.
CONS.R The declaration's parameter is <assertproc>, and it exists as an exported procedure
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: one parameter
- b the parameter: an Oberon identifier
- c the export list against the declaration: the parameter names an exported procedure of the module
Admitted: none.
CONS.X Nothing beyond <assertproc> is exported
Violation. Tool-checked.
- a the export list:
<assertproc>, nothing else
Admitted: none.
CONS.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
CONSgroup of the allow-lists file: every imported program module is of a kind the group names, from any partition, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: the error code catalogue is expected and nothing else. VALUES.1 is read here: no VALUES constant is an array dimension in the module.
Admitted: none.
CONS.P The module lies in the program directory
Violation. Tool-checked.
- a the module's directory: the program directory itself
Admitted: none.
CONS.1 The assert procedure is parameterless
Observation. Tool-checked.
A parameter would let a fact into the consistency check from outside the definitions; one may have its reason, which is stated.
- a the procedure heading:
<assertproc>takes no parameters
Admitted: a stated reason for the parameter.
That <assertproc> runs at schedule 0's gate, and in no other module, is the pair, SCHEDULE/CONS.1.
BOUNDARY
Purpose: the schedule boundary: the crossings between schedules, declared once for the program.
Declaration: <crossingsvar>
(* ECSKIND: BOUNDARY Crossings *)
Placement: the program directory.
Imports: the BOUNDARY group of the allow-lists file.
Construct: Implementation, § Schedules and the Boundary, The Boundary Module.
BOUNDARY.R The declaration's parameter is <crossingsvar>, and it exists as an exported variable
Precondition (a, b), violation (c). Tool-checked.
- a the declaration: one parameter
- b the parameter: an Oberon identifier
- c the export list against the declaration: the parameter names an exported variable of the module
Admitted: none.
BOUNDARY.X Nothing beyond <crossingsvar> is exported
Violation. Tool-checked.
- a the export list:
<crossingsvar>, nothing else
Admitted: none.
BOUNDARY.I Imports are within the allow-list
Violation (a), fact (b). Tool-checked (a), tool-recorded (b).
- a the import list against the declared kinds and the
BOUNDARYgroup of the allow-lists file: every imported program module is of a kind the group names, from any partition, and every imported framework module is named there - b the import list: every other imported library module, recorded in the ECS file with the module
For the reviewer, reading b: none is expected; check what it serves.
Admitted: none.
BOUNDARY.P The module lies in the program directory
Violation. Tool-checked.
- a the module's directory: the program directory itself
Admitted: none.
BOUNDARY.1 The module body assigns the crossings with constant indices, and every entry is determinate
Violation (a, c), observation (b). Tool-checked.
A loop or a variable index leaves the entry outside the ECS file. The kernel reads every entry of both arrays at SetBoundary and asserts the calling core's diagonal empty; nothing is zeroed at load, so an entry never assigned is a phantom crossing or a failed assertion. The ECS file records the assigned entries and writes the rest empty, so without determinacy the file states a boundary the program does not have. No CLEAR is mandated: every entry assigned satisfies c.
- a the module body: every assignment to
<crossingsvar>is<crossingsvar>.flow[i, j] := ...or<crossingsvar>.deposit[i, j] := ...with constanti,j - b the module body: every other statement, pointed out
- c every entry of both arrays: assigned in the module body, or
CLEAR(<crossingsvar>)precedes the first assignment
Admitted: a CLEAR or an assertion among the statements b points out.
BOUNDARY.2 A crossing names surfaces only
Violation. Tool-checked.
- a the right sides: every term is a bare surface, a leaf of a
TOKENSmodule's<surfacesvar>; no token in braces
Admitted: none.
BOUNDARY.3 No schedule crosses to itself
Violation, stops at SetBoundary. Tool-checked.
- a the indices:
idiffers fromjin every entry
Admitted: none.
Which index is which schedule is the programmer's statement, read by the reviewer against the deployment calls, SCHEDULE/BOUNDARY.1; that each surface exists is the pair, BOUNDARY/TOKENS.1.
Part C. Pairs of Kinds
One section per pair, named by both kinds, the one whose declaration is taken as given first. A pair is read once both kinds are done; the sections stand in the order of the later kind.
SCHEDULE/PERIODS
SCHEDULE/PERIODS.1 The tick is a PERIODS constant
Observation. Tool-checked.
PERIODS is the proposed construct; a tick named otherwise undermines no invariant, and the reason is stated.
- a each
<gateproc>'sKernel.Install: the tick argument is aPERIODSconstant, one tick constant per schedule
Admitted: a stated reason for the tick's place.
SCHEDULE/PARTITION
SCHEDULE/PARTITION.1 Each partition is created by one schedule and registered by the same
Violation. Tool-checked.
- a every
<gateproc>:PARTITION.<createproc>is called by exactly one of them, before itsKernel.Begin - b every
<gateproc>:<addsystemsproc>is called by the same one, between itsKernel.BeginandKernel.Plan, once
Admitted: none.
SCHEDULE/PARTITION.2 Only PARTITION modules are created
Violation. Tool-checked.
- a every
<gateproc>against the declarations: every<createproc>and<addsystemsproc>call targets a module declaredPARTITIONwhose declaration names those procedures
Admitted: none.
PERIODS/PARTITION
PERIODS/PARTITION.1 A registration's period is a PERIODS constant
Observation. Tool-checked.
- a
PARTITION.<addsystemsproc>: the period argument of everyKernel.AddSystemis aPERIODSconstant
Admitted: a stated reason for the period's place.
PARTITION/STATE
PARTITION/STATE.1 The build procedure is called from its own partition's create procedure only
Violation. Tool-checked.
- a all call sites of
STATE.<buildproc>: exactly one in the program, in itsPARTITION's<createproc>
Admitted: none.
PARTITION/STATE.2 Every store leaf has an initialisation site in the create procedure
Violation. Tool-checked.
The STATE module assigns nothing, STATE.3; the sites lie in the partition's <createproc>. A necessary condition, as LOCKED.3: a leaf without a site is uninitialised, since nothing is zeroed at load; a leaf with a site is read by the reviewer, Part E. The parameter mode is read from the callee's procedure heading, through the import alias; for a library procedure without source the mode is unknowable and the actual counts as a site, a miss rather than a false finding. A local procedure that takes the record or a part of it as a VAR parameter is followed with the actual's path in place of the formal's path.
- a the record types against
<createproc>and the local procedures it reaches: every leaf of the store record, through nested records and arrays, appears at least once in a position that can write it, through<storevar>or a local assigned from it: the left side of:=, the actual of a VAR parameter, a device's read into the store included, or the operand ofCLEAR, the leaf itself or an enclosing record or array; array indices are abstracted,S.a[i].xcovers the patha[].x
Admitted: none.
STATE/TOKENS
STATE/TOKENS.1 The tokens mirror the store
Violation. Tool-checked.
- a both leaf lists: the leaves of
TOKENS.<tokensvar>and the leaves ofSTATE.<storevar>'s record correspond one to one, names verbatim, structure verbatim
Admitted: none.
PARTITION/SYSTEM
PARTITION/SYSTEM.1 The registration names the declared roles
Violation. Tool-checked.
The pair side of PARTITION.2-a: the SYSTEM module's declaration is the authority for the names the registration passes.
- a each
Kernel.AddSystemcall against the named module's declaration: run, manifest and name are its declared<runproc>,<manifestvar>and<namevar>
Admitted: none.
SYSTEM/TOKENS
SYSTEM/TOKENS.1 Manifest references resolve
Violation. Tool-checked.
That a foreign module's tokens appear through its surfaces only is SYSTEM.7, which reads the manifest assignment with every other reference.
- a the manifests against the
TOKENSmodules: every braced token is a declared token of aTOKENSmodule; every bare surface a declared surface
Admitted: none.
SYSTEM/STATE
SYSTEM/STATE.1 Every store variable the code touches is in the manifest
Violation. Tool-checked.
- a
<runproc>, the procedures it reaches and the adapter procedures it calls, against the manifest: each<storevar>.<path>reference maps to a token of the manifest, through the mirror, STATE/TOKENS.1
Admitted: none.
SYSTEM/STATE.2 Access direction matches the manifest set
Violation. Tool-checked.
- a
<runproc>against the manifest: a written store variable is in O, P or Px; a read one in C, Cp or Cx - b
<runproc>against the manifest: a Cp token is never written
Admitted: none.
SYSTEM/STATE.3 Every manifest token is touched
Observation. Tool-checked.
- a
<runproc>against the manifest: each token of the manifest is reached in the code, directly or through an adapter, or through a declared library callback
Admitted: a token reached through a library callback, the callback named.
SYSTEM/STATE.4 Transport access flows through the adapter
Violation. Tool-checked.
- a
<runproc>: a store variable of a transport's type is reached through the adapter procedure of its direction, never by direct store access, in whatever manifest set it is declared
Admitted: none.
The storage kind decides the route, not the manifest set: a transport is reached through its adapter under produced and consumed as under deposited and collected, and a plain Component is reached directly under either. The tally an adapter records beside a transport access is a plain Component: the adapter's write is a direct write on the calling System's behalf, ADAPTER.4, and the collector's read is a direct read. A store variable is of a transport's type when its type, resolved through the STATE module's own type declarations, names a type of a transport module, a declared library transport included.
A procedure-typed formal that receives an adapter's procedure of the wrong direction does not compile: procedure-type compatibility includes the parameter modes, which are the direction, ADAPTER.3. The pair SYSTEM/ADAPTER has no check-point.
STATE/ADAPTER
STATE/ADAPTER.1 The adapter's store paths are store variables
Violation. Tool-checked.
The pair side of ADAPTER.1-b: the STATE's record is the authority for the paths.
- a the adapter's store references against the store record: every
<path>reached is a store variable
Admitted: none.
TOKENS/ADAPTER
TOKENS/ADAPTER.1 Every reached store path has a token
Violation. Tool-checked.
- a the adapter's procedures against
TOKENS: each store variable an adapter procedure reaches translates to a token of the partition'sTOKENSmodule
Admitted: none.
TRANSPORT/ADAPTER
TRANSPORT/ADAPTER.1 The adapter's transport is declared and imported
Violation. Tool-checked.
- a the
ADAPTER's declaration against the named module's declaration: the parameter names a module declared under a transport kind, in the tree or the library - b the import list: the adapter imports it
Admitted: none.
TRANSPORT/ADAPTER.2 Procedure modes agree with the transport's
Violation. Tool-checked.
- a both modules, for a transport in the tree: the adapter's put calls the transport's put with the same modes, and so on for every procedure
Admitted: none.
TOKENBASES/TOKENS
TOKENBASES/TOKENS.1 The partition's tokens are allocated from its base
Violation. Tool-checked.
Which constant is the partition's count is not readable without a naming rule; the count is asserted by the TOKENS body, TOKENS.6, and proven by the ranges, PROGRAM.3.
- a the leaves' expressions against
TOKENBASES: each reaches exactly oneTOKENBASESconstant, the same for all leaves
Admitted: none.
TOKENNAMES/TOKENS
TOKENNAMES/TOKENS.1 Every partition's names are referenced
Violation. Tool-checked.
A necessary condition: a table referenced nowhere is not gathered. How the body gathers is its own, and where each name lands is TOKENNAMES.1.
- a
TOKENNAMES' body and the local procedures it reaches, against theTOKENSdeclarations: every declared<namesvar>is referenced
Admitted: none.
SCHEDULE/CONS
SCHEDULE/CONS.1 <assertproc> runs at schedule 0's <gateproc>
Violation. Tool-checked.
The consistency station comes first: a program whose definitions disagree has no business starting another core or creating anything. That no other module imports CONS is the schedule 0 only qualifier of the SCHEDULE group, SCHEDULE.I.
- a schedule 0's
<gateproc>: it callsCONS.<assertproc>once, as its first statement, before the deployment calls and beforeKernel.Install
Admitted: none.
SCHEDULE/BOUNDARY
SCHEDULE/BOUNDARY.1 The boundary is set and its indices are schedules
Violation. Tool-checked.
Which index is which schedule is the programmer's statement, read by the reviewer against the deployment calls.
- a every
<gateproc>of a program of two or more schedules: it passesBOUNDARY.<crossingsvar>toKernel.SetBoundary; a program of one schedule crosses nothing and sets no boundary, PROGRAM.2-a - b
BOUNDARY's indices against the program's schedule count: every crossing index lies in 0 to n-1, n the number of schedules, PROGRAM.1-c
Admitted: none.
BOUNDARY/TOKENS
BOUNDARY/TOKENS.1 Every crossing surface exists
Violation. Tool-checked.
- a
BOUNDARY's body against theTOKENSmodules: each surface term of a crossing resolves to a leaf of aTOKENSmodule's<surfacesvar>
Admitted: none.
Part D. The Program as a Whole
Check-points over all modules of one kind, or over the program, read once after Parts B and C. Several are the kernel's own plan checks seen statically; each of these carries its stop.
PROGRAM.1 Schedules are dense, one per core, started once
Violation (a, b), fact (c). Tool-checked (a), tool-recorded (c).
A deployment is read as the passing of a SCHEDULE's exported <gateproc> as a procedure actual, without knowing the callee. The core lives in the deployment procedure's name or arguments, which the reviewer knows and the tools do not; the kernel equates schedule and core.
- a all
SCHEDULEmodules: schedule 0 is the main module; every otherSCHEDULEmodule's<gateproc>is passed as a procedure actual exactly once, in anotherSCHEDULEmodule - b the deployment calls: the cores so used are distinct
- c the schedules: the main module and the started ones, n in all, listed in the ECS file, schedule 0 numbered, the others by module with their deployment call as written; the crossing indices range over 0 to n-1, SCHEDULE/BOUNDARY.1-b
Admitted: none.
PROGRAM.2 The singletons are single
Violation. Tool-checked.
The PARTITION module's count is PARTITION.P-b: a directory is a partition directory because it holds exactly one, so counting it here would be circular.
- a the declared kinds by directory: at most one
PERIODS,RESOURCES,TOKENBASES,TOKENNAMESandCONSmodule in the program, and exactly oneBOUNDARYmodule in a program of two or more schedules; a program of one schedule crosses nothing and declares none - b the declared kinds by directory: exactly one
STATEandTOKENSmodule per partition directory; at most oneLOCKED,WIRINGandVALUES
Admitted: none.
PROGRAM.3 Token ranges are disjoint and gapless over the program, and the total fits the kernel
Violation. Tool-checked.
- a all
TOKENSmodules' evaluated ranges, base to base plus count less one: they do not overlap and leave no gap from 0 to the total - b the total against the kernel's constant: not above
Kernel.MaxTokens
Admitted: none.
PROGRAM.4 Single writer
Violation, stops at Plan. Tool-checked.
- a all manifests: no token is in O or P of two Systems
Admitted: none.
PROGRAM.5 A token is dataflow or deposit, never both
Violation, stops at Plan. Tool-checked.
- a all manifests: a token is a dataflow token, in O, P, C or Cp, or a deposit token, in Px or Cx, never both
Admitted: none.
PROGRAM.6 Owned is private
Violation, stops at Plan. Tool-checked.
- a all manifests: no token in a System's O appears in any other System's C or Cp
Admitted: none.
PROGRAM.7 Produced is consumed, consumed is produced
Violation, stops at Plan. Tool-checked.
The kernel's check is relaxable; the tools report each gap whatever the waiver, and the reviewer matches the gaps to the relaxed set read from <gateproc>, SCHEDULE.4.
- a all manifests: every P token is in some C or Cp
- b all manifests: every C or Cp token is in some P
Admitted: a gap covered by a waiver, SCHEDULE.4.
PROGRAM.8 Deposits are collected
Violation, stops at Plan. Tool-checked.
Relaxable, as PROGRAM.7.
- a all manifests: every Px token is in some Cx
Admitted: a gap covered by a waiver, SCHEDULE.4.
PROGRAM.9 Acyclic
Violation, stops at Plan. Tool-checked.
- a the dependency graph over P and C edges, with Cp edges reversed: no cycle
Admitted: none.
PROGRAM.10 No token written in two schedules
Violation, a stops at Commit. Tool-checked.
- a all manifests with their schedules: no O or P token in Systems of two schedules
- b all manifests with their schedules: no Px token deposited from two schedules
Admitted: none.
PROGRAM.11 Every crossing is real and oriented
Violation, b stops at Commit. Tool-checked.
- a
BOUNDARYagainst the manifests and the registrations: for every crossing[i, j]surface, its producers' Systems run in schedule i and its consumers' in schedule j - b every crossing token: a counterpart System exists in another schedule
- c every crossing token: it is reached through an adapter
Admitted: none.
PROGRAM.12 Every token appears in a manifest
Observation.
A token in no manifest is a store variable no System reads or writes.
- a each token of each
TOKENSmodule against all manifests: in at least one manifest of the program
Admitted: a store variable kept for a System not yet written, with the reason stated.
The role names are not a check-point: the ECS file's role names section shows the majority name of each role and the overrides, and a module with its own line is visible there.
Part E. Read by a Person Only
Facts not in the code or not decidable from it. The review reads them; no tool does.
-
Previous-value consumption. A Cp declaration says the System reads the last pass's value and runs before the producer. Whether the logic is correct under a one-pass-old value, and what the value is at the first pass, is the control question.
-
Initial values. PARTITION/STATE.2 and LOCKED.3 see an assignment site per leaf, not that it executes nor what it writes. The loop that stops one short, the branch around the assignment, the device procedure that leaves a field untouched, and the value itself are read here, with the first-pass question above.
-
The periods and the rate test. Every System period is counted in the ticks of the schedule it runs on; every tick-denominated value crossing the boundary is denominated in the consumer's tick. The rate test: change one schedule's tick and nothing else; every period re-derives to the same milliseconds, and the plant behaviour does not change.
-
The adapter's policy. What an adapter does when the precondition fails, and what it records, ADAPTER.4.
-
The boundary's preflight. That the crossings are the whole set, and that a value crossing by sampling tolerates the delay, is read from the manifests before the boundary is written.
-
The authored facts against reality. Units, pins, priorities, the memory map, the console unit: against the reference manual and the schematic.
-
The token allocation's arithmetic. That the
TOKENBASESconstants are the counts and the running sum they read as, and that the module body asserts the total against the kernel's capacity. The tools prove the allocation on the values, TOKENS.3, TOKENS.6 and PROGRAM.3, not on the constants' meaning. -
The names table. TOKENNAMES.1: the plan report prints the names beside the token numbers, so a misplacement shows at the first run, and a missed name shows as the bare number where the table is cleared first.
-
Run to completion. SYSTEM.5.
-
No caching below the store.
OTHERandBINDINGmodules, over the variables OTHER.1 and BINDING.1 point out: a synchronous helper or binding holds nothing between calls beyond a device's technical state behind its device handle; an asynchronous binding holds transfer state only, a single-producer single-consumer queue, the interrupt one side and the System's call the other, each item consumed once, the protocol's indices beside it, no lock. The one test: can a second call obtain what a first one already obtained? A queue says no, a cache says yes. A stateful helper imported by two Systems is a channel beside the store. A violation. -
The module body rule. A body initialises the module's own memory, never hardware; the bring-up is the exception, and which modules are the bring-up is a role the tools cannot know. The kinds' check-points pin the module bodies the ECS file reads; a transport,
OTHER,BINDINGorPARTITIONbody is read by eye against the rule. -
Content. Names, header text, the logic inside
<runproc>, the order of registration: authored freedom. The run order is derived; registration order means nothing.
Legitimate gaps are recorded as such, never as findings: a coverage gap the reviewer matches to a waiver read from <gateproc>, SCHEDULE.4, and a generated skeleton, the kind shapes present and the content not yet written, which is built before it is checked like any program. A tree without build products is not a gap for the tools: they refuse it, and the rebuild is the check. For the review by hand a deep-cleaned tree is reviewed from its sources, and the precondition check-points do not apply.
Tool Support
The tools hold the check-points marked Tool-checked or Tool-recorded: extract-ecs reads the build, the declarations and the facts and writes the ECS file; check-ecs prints the findings. Each prints a finding with the check-point's identifier as its first field and the position in the sources, so a finding is read against this guide by its identifier. The tools are described in their own pages, extract-ecs and check-ecs.
See Also
- ECS for Control: Concepts
- ECS for Control: Implementation
- ECS for Control: The ECS File
- ECS for Control: extract-ecs
- ECS for Control: check-ecs
Last updated: 2 November 2026