Еще один вариант эмуляции недетерминированного цикла Дейкстры. Он в некотором плане лучше предыдущих, так как у него спрятаны детали реализации цикла Дейкстры от непосредственно определения какого-то прикладного цикла.
## Код:
```
MODULE Dijkstra;

  IMPORT
    Memory;

  TYPE
    Repetition* = POINTER TO RecordRepetition;
    ProcCondition* = PROCEDURE (obj: Repetition): BOOLEAN;
    ProcCommand* = PROCEDURE (obj: Repetition);
    GuardedCommand* = RECORD
      condition*: ProcCondition;
      command*: ProcCommand
    END;
    GuardedCommands = POINTER TO RECORD
      guardedCommand: GuardedCommand;
      next: GuardedCommands
    END;
    RecordRepetition* = RECORD
      head: GuardedCommands
    END;

  PROCEDURE Add*(repetition: Repetition; VAR gc: GuardedCommand);
  VAR
    node: GuardedCommands;
  BEGIN
    NEW(node);
    IF node # NIL THEN
      node.guardedCommand := gc;
      node.next := repetition.head;
      repetition.head := node;
    END;
  END Add;

  PROCEDURE Execute*(repetition: Repetition);
  VAR
    node: GuardedCommands;
    prev: GuardedCommands;
    last: GuardedCommands;
  BEGIN
    prev := NIL;
    node := repetition.head;
    (* Ищем первое условие, которое выполняется. *)
    WHILE (node # NIL) & ~node.guardedCommand.condition(repetition) DO
      prev := node;
      node := node.next;
    END;
    (* Если условие найдено, то выполняем команду. *)
    WHILE node # NIL DO
      (* Выполняем команду. *)
      node.guardedCommand.command(repetition);
      (* Переставляем команду в конец очереди.*)
      last := node;
      WHILE last.next # NIL DO
        last := last.next;
      END;
      IF node # last THEN
        IF prev # NIL THEN
          prev.next := node.next;
        ELSE
          repetition.head := node.next;
        END;
        last.next := node;
        node.next := NIL;
      END;
      prev := NIL;
      node := repetition.head;
      (* Ищем первое условие, которое выполняется. *)
      WHILE (node # NIL) & ~node.guardedCommand.condition(repetition) DO
        prev := node;
        node := node.next;
      END;
    END;
    (* Если ни одно из условий не выполняется, то цикл Дейкстры завершается. *)
  END Execute;

END Dijkstra.
```

## Код:
```
MODULE Test;

  IMPORT
    Memory,
    Out,
    WinConsoleOut,
    Dijkstra;

  TYPE
    Repetition = POINTER TO RepetitionRecord;
    RepetitionRecord = RECORD (Dijkstra.RecordRepetition)
      n: INTEGER
    END;

  VAR
    writer: WinConsoleOut.Writer;

  PROCEDURE Condition1(obj: Dijkstra.Repetition): BOOLEAN;
  BEGIN
    RETURN obj(Repetition).n MOD 2 = 0
  END Condition1;

  PROCEDURE Command1(obj: Dijkstra.Repetition);
  BEGIN
    ASSERT(Out.Text(writer, "2 ")); 
    obj(Repetition).n := obj(Repetition).n DIV 2;
  END Command1;

  PROCEDURE Condition2(obj: Dijkstra.Repetition): BOOLEAN;
  BEGIN
    RETURN obj(Repetition).n MOD 3 = 0
  END Condition2;

  PROCEDURE Command2(obj: Dijkstra.Repetition);
  BEGIN
    ASSERT(Out.Text(writer, "3 ")); 
    obj(Repetition).n := obj(Repetition).n DIV 3;
  END Command2;

  PROCEDURE Condition3(obj: Dijkstra.Repetition): BOOLEAN;
  BEGIN
    RETURN obj(Repetition).n MOD 5 = 0
  END Condition3;

  PROCEDURE Command3(obj: Dijkstra.Repetition);
  BEGIN
    ASSERT(Out.Text(writer, "5 ")); 
    obj(Repetition).n := obj(Repetition).n DIV 5;
  END Command3;

  PROCEDURE Test;
  VAR 
    gc: Dijkstra.GuardedCommand;
    repetition: Repetition;  
  BEGIN
    NEW(repetition);
    gc.condition := Condition1;
    gc.command := Command1;
    Dijkstra.Add(repetition, gc);
    gc.condition := Condition2;
    gc.command := Command2;
    Dijkstra.Add(repetition, gc);
    gc.condition := Condition3;
    gc.command := Command3;
    Dijkstra.Add(repetition, gc);
    repetition.n := 466560000;
    Dijkstra.Execute(repetition);
  END Test;

BEGIN
  ASSERT(WinConsoleOut.Create(writer) & writer.Open(writer));
  Test;
  ASSERT(writer.Close(writer));
END Test.
```

Результат работы данной программы:
5 3 2 5 3 2 5 3 2 5 3 2 3 2 3 2 2 2 2 2