Class NeverEndingIterationMarker

java.lang.Object
org.ek9lang.antlr.EK9BaseListener
org.ek9lang.compiler.phase5.NeverEndingIterationMarker
All Implemented Interfaces:
org.antlr.v4.runtime.tree.ParseTreeListener, EK9Listener

final class NeverEndingIterationMarker extends EK9BaseListener
The phase-5 pre-pass that marks iteration the compiler can PROVE never ends (decision 15(a), phase 1: the infinite half). It runs over every source before Walk 1, so a stream in one file can read the verdict on an iterator declared in another; InfiniteStreamSourceOrError reads the marks.

It marks (NEVER_ENDING_ITERATION, the value is the reason in words):

  • INF-1 - a hasNext() METHOD whose returning variable is initialised with the literal true and never written: <- more as Boolean: true.
  • INF-2 - a hasNext() METHOD whose returning variable is initialised from a Boolean PROPERTY of its own class that is declared with the literal true, is never written anywhere in the class (by SymbolWrites, so a mutating operator such as :=: counts) and is read nowhere else in the class (escape-lite: no other code holds it, so nothing can flip it through an alias).
  • INF-3 - a function or method whose returning variable only ever receives a dynamic class whose hasNext() is marked, at least once in a position that always runs (MustExecutePosition) - the generator form, cat endless(), and an iterator() that returns such a dynamic class.

The mark is on the METHOD, not the class, so a closed class that inherits a marked hasNext() is covered and an open class never is - whether a SOURCE is infinite also needs its type to be closed, which is decided where the source is (InfiniteStreamSourceOrError).

Sound by construction: once hasNext() cannot return false, the only way out of the iteration is an exception or a Panic, so a stage that waits for the end never emits normally. Anything not matched is simply not marked - unknown sources keep today's behaviour. One residual is stated rather than closed: INF-2 trusts that no caller mutates the Boolean that hasNext() hands back (b <- it.hasNext(); b :=: false), which would flip the property through the alias the returning variable is.