ConditionTriggeredInstructions (Wenn => Dann)

  1. CTI besteht aus Konditionen (auch Bedingungen genannt), Instruktionen und Deklarationen.
  2. Programme werden als geschlossene Systeme betrachtet, die nur über entsprechend deklarierte Datenobjekte kommunizieren, die gemeinsam verwendet werden. Interne, nicht für die gemeinsame Verwendung deklarierte Daten dürfen zwischen Systemen nicht ausgetauscht werden oder zugreifbar sein. Die bedingten Anweisungen, aus denen ein System besteht, werden CI genannt. Dadurch ist es "hardwarenah" ; CIs können leicht in Schaltungen umgesetzt werden (quasi "instruktionsweise"). Die Bedingungen werden durch Gatter, die Instruktionen durch verschiedene Speicher realisiert. Funktionen sind Module oder Chips (mit eigenem Takt).
  3. Jegliche Sequentialität ist implizit über die Bedingungen. Instruktionen können einzeln oder geblockt sein. Instruktionen innerhalb von Blöcken müssen streng "parallel" sein ; es darf keinerlei Bedingungen für ihre Ausführung (z.B. Sequentialität) oder Abhängigkeiten geben außer der, dass alle Instruktionen immer zusammen (im gleichen "Takt") ausgeführt werden, also nicht nur ein Teil davon.
    Auch die "blockfreien" (unbedingten) CIs eines Systems sind als "parallel" zu betrachten, werden also quasi in der Theorie alle zugleich ausgeführt, und dürfen untereinander keinerlei Abhängigkeiten besitzen, die sich nicht implizit aus den Bedingungen und ihren Instruktionen ergeben.
  4. Prinzipiell müssen alle Bedingungen, die theoretisch (also nicht praktisch) eintreten können, auch durch Instruktionen bearbeitet werden, also Bedingung in einer CI sein (Vollständigkeit). Bedingungen, die nicht eintreten dürfen, erhalten als Instruktion eine ERROR-Fehlerfunktion. Durch die Funktion EXIT können (solche) Funktionen das Programmende bewirken. Andernfalls steuert die ERROR-Funktion die weitere Programmausführung über die zur Kommunikation benutzten Datenobjekte.
  5. CIs mit den selben Bedingungsteilen innerhalb des gleichen Blocks (also gleichen Prio-Bedingungen) werden automatisch zu einer CI mit einem Block der Vereinigung all ihrer Instruktionen zusammengefasst (ergibt sich aus 3).
  6. Die Instruktionen von CIs werden insofern auf Widerspruchsfreiheit geprüft, als sie nicht zu verschiedenen Ergebnissen führen dürfen, wenn ihre zugehörigen Bedingungen zugleich erfüllt sein können (Unverträglichkeit). Die Bedingungen von CIs müssen sich bei möglichen Widersprüchen durch die Instruktionen also definitiv ausschließen. Beispiel: Z ≠ 2 => I= 1  und Z > 1 => I= 3 sind unverträglich.
  7. Funktionen können direkt implementiert oder CI-Subsysteme sein. Der Datenaustausch erfolgt in jedem Fall durch als Parameter übergebene Datenobjekte ohne Nebenwirkungen oder direkte (Return-)Wertübergabe. Wert- Funktionen liefern nur einen einzelnen Wert zurück, z.B. einen Wahrheitswert, und sind nur für die Verwendung in Bedingungen bestimmt. Sie dürfen als Parameter übergebene Datenobjekte nicht ändern. Bei CI-Implementierung nutzen Wert-Funktionen die Instruktion RETURN(Wert) zum Verlassen der Funktion und zur Wertübergabe. CI-Subsysteme sind der Direktimplementierung vorzuziehen (Fehlersicherheit). Funktionsnamen, die mit einem "?" enden, bezeichnen stets Funktionen mit Wahrheits-Returnwert TRUE oder FALSE.
  8. Das CTI-EntwicklungsSystem soll selbst in CTI implementiert sein. Hierzu muss eine erste Übersetzung der CIs des Entwicklungssystems in eine vorhandene Programmiersprache (C++) manuell erfolgen, die schließlich ein ausführbares Programm liefert. CTI-ES soll später voll interaktiv arbeiten und CTI selbstständig compilieren.
    Eine CI müsste in (erweitertem) C++ stets so darstellbar sein:
    if ( Bedingung ) { Instruktionsfolge } [ else { Instruktionsfolge }. Der Bereich "else" kann fehlen, falls dort keine Instruktionen anzugeben sind.

    Elementardaten- und Datenstruktur-Deklarationen (struct oder class) wie in C++ (mit dynamischer Allokation wie bei Java).
    Es gibt weder Sprünge, Schleifen noch verdeckte Abhängigkeiten.
  9. Sequenzen:
    Strenge
    (inhaltliche) Sequenzen werden so realisiert, dass ihre CI indiziert werden (durchnummeriert) und der Index der CI  innerhalb ihrer Instruktionsfolge einer Indexvariablen zugewiesen wird. Diese kann in der Bedingung der Nachfolger-CI auf den Wert des Index der zuletzt ausgeführten geprüft werden.  "Taktsynchrone" Sequenzierung (Indexfortschaltung bei Schleifen) kann durch das Kopierprinzip für RW-Objekte (13) implizit ohne Flags und Bedingungsabfragen erfolgen (außer bei transparenten Funktionen ?). Technische Sequenzierung innerhalb eines Taktes, ja formale Sequenzierung überhaupt, ist überflüssig und mit dem CTI-Konzept der reinen Bedingungssteurung unvereinbar (zu beweisen).

    Infolge der Kopie-Rückkopie-Funktion und der nur einmaligen Änderungsmöglichkeit pro Takt ändern reguläre Anweisungen innerhalb eines Taktes keine Daten, so dass nachfolgende Anweisungen kein geändertes Environment vorfinden. Es können durch technische Sequenzen nur Flags, sowie deren Abfrage, und Takte eingespart werden, also Ausführungszeit.
    Vorsicht bei Iteration oder Rekursion einer Sequenz !

    Indexvariable sind, außer bei transparenten Sequenzfunktionen, lokal, temporär und zu 0 initialisiert. Die Indexvariable bestimmt die Instanz einer Sequenz. Die Sequenz läuft, solange die Indexvariable != 0 ist.
    Die erste CI  setzt die Indexvariable auf 2 und "Index == 1" wird als nächstes abfragt. Die folgenden CI der Sequenz fragen den Index des Vorgängers ab und die letzte CI setzt die Indexvariable wieder 0. Die Sequenz wird also mit Index=1 gestartet. Mehrfachausführung der CI einer Sequenz innerhalb einer Instanz (vgl. ZYKLUS) sind so ausgeschlossen. Um eine Sequenz nur einmal zu konstruieren und iterativ oder rekursiv mehrfach auszuführen, muss sie in eine Funktion eingebettet werden, deren Parameter eine Indexvariable beinhalten kann. Diese "Sequenz-Funktion" wird normalerweise erst beendet, wenn die letzte Instruktion der Sequenz ausgeführt ist. In diesem Fall (keine "Transparenz") ist keine Indexvariable als Parameter erforderlich (nur lokal). Ist sie aber vorhanden und durch die Funktion änderbar (Referenz-Übergabe), so kann die Sequenz auch vor ihrem Ende mit dem Funktions-RETURN verlassen und bei Wiederaufruf fortgeführt werden ("Transparenz"). Das Sequenzende muss dann extern abgefragt werden.
    Technische Indexvariablen
    Technische Indexvariable sind RW und immediate (inhaltliche nicht), d.h. es wird innerhalb eines Ausführungstaktes auch beim Lesen immer auf den Write-Anteil der Variable selbst zugegriffen, nicht auf den taktinvarianten Read-Anteil (bzw. eine  Kopie davon). Das Update der technischen Indexvariablen nach Bearbeitung einer CI-Instruktion ist unabhängig von deren Ausführungsbedingung. Nur bei inhaltlicher Sequenz ist zu unterscheiden, ob die Inkrementierung der Indexvariablen von der Erfüllung der CI-Bedingung abhängig sein soll oder nicht (Inkrementierung dann zusätzlich auch im else-Bereich ). Sie müssen per Instruktion am Ende der Sequenz 0 gesetzt werden, da sich die Sequenz über mehrere "Takte" erstrecken kann. Technische Indexvariable werden vom System geführt und enthalten ein Ausführungsflag für jede lokale Instruktion, das abgefragt werden kann. Kurze technische, nicht transparente Sequenzen könnten auch durch eine Sequenz-Anweisung der Form seq { Instruktionsfolge } realisiert werden, die vom System besonders geprüft und konventionell der Reihe nach abgearbeitet wird. Es ist nur eine seq-Anweisung pro Block (Menge der Anweisungen im selben "Takt") erlaubt. Alle Variablen und Daten sind innerhalb immediate, werden also von ihrer Write-Komponente gelesen statt von ihrer Read-Komponente. Die Ergebnisse einer seq-Anweisung müssen von der Ausführungsreihenfolge im Rahmen der regulären CI-Instruktionen unabhängig sein. Mit der auch für "transparente Sequenzfunktionen" gültigen Festlegung, dass ein Verlassen der Funktion stets nach Taktende erfolgt, gilt auch für diese, dass technische Indexvariable beim Funktionseintritt initalisiert werden müssen. Durch diesen Mechanismus lassen sich "Takte" einsparen (sonst nichts).
  10. Prio-Bedingungen, Blockung
    CI-Anweisungen können auch geblockt sein. Ein CI-Block hat die Form Prio-Bedingung => CI-Instruktionsfolge, darstellbar als if ( Prio-Bedingung ) { if ( Bedingung1 ) { Instruktionfolge1 } ; if ( Bedingung2 ) { Instruktionfolge2 } .... }. Dies ist äquivalent zu { if ( Prio-Bedingung && Bedingung1 ) { Instruktionfolge1 } ;  if ( Prio-Bedingung && Bedingung2 ) { Instruktionfolge2 } .... }.
    Mit der Erzeugung einer AO-Instanz (siehe Folgepunkt) in einem Block wird dieser durch deren CI-Anweisungen erweitert. Diese CI-Anweisungen sind auf den Block beschränkt und damit dessen Prio-Bedingungen unterworfen. Dies gilt insbesondere für Funktionen, wobei der Funktionsaufruf selbst quasi die Prio-Bedingung darstellt.
  11. Algorithmische Objekte ("Programme", z.B. ZYKLUS, Funktionen, "Macros" usw. ; um Instruktionen erweiterte "class"-Definition)
    AOs bestehen aus Parametern, Datenobjekten, Instruktionsfolgen, Funktionen und Eigenschaften. Letztere sollen sicherstellen, dass das AO genau das tut, was es soll, und keine Fehlfunktionen möglich sind. AOs können wie Bausteine über das CTI-ES an jeder Stelle eingesetzt werden, an der eine Instruktion stehen kann. Das CTI-ES fragt interaktiv Parameter ab und prüft, ob bereits zur Entwicklungszeit prüfbare Randbedingungen verletzt werden. AOs können statisch (fester Programmbestandteil, wie Macros) und dynamisch (werden bei Bedarf generiert und wieder gelöscht) sein, werden durch CLOSE geschlossen (beim Verlassen beendet ; alle inneren Daten werden ungültig) oder sind transparent (Default ; alle inneren Daten bleiben bis zum expliziten Abschluss gültig). Dies gehört alles zu den "Eigenschaften". Eingebettete AOs ("inline", "Macro") können die Variablen ihrer Umgebung benutzen, wenn sie unverwechselbar und namensgleich sind. Solche "externen" Variablen sind uneingeschränkt manipulierbar. Die Unveränderlichkeit RO externer Variablen kann erreicht werden, indem sie explizit innerhalb des AOs auf lokale Variable kopiert werden oder sie kann in den AO-Eigenschaften verankert sein und wird geprüft (Default: Veränderlichkeit RW). Interne und externe Variablen von AOs können (bei Namensungleichheit) durch Kopplungsanweisungen der Form "interne Variable"="externe Variable" (dem AO-Namen in Klammern nachgestellt) verbunden werden. Dies gilt auch für Funktionsaufrufe ; die Parameter werden also auch hier nicht positionsgebunden, sondern durch explizite Zuweisung zugeordnet. Bei der Funktionsimplementierung müssen keine Übergabeparameter angegeben werden. Interne Variablen von AOs müssen vor ihrer Nutzung als Wert initialisiert oder mit einer externen Variablen verknüpft werden. Im letzteren Fall wird deren Initialisierung geprüft.
    AOs werden über die reservierte RETURN-Instruktion verlassen. Hierdurch wird die wiederholte Ausführung der CIs beendet. Ein automatisches Verlassen nach Abarbeitung aller Instruktionen findet nicht statt. Alle Variablen behalten auch nach dem Verlassen durch RETURN ihren Wert (sind also "statisch"), wenn sie nicht durch die Funktionen RELEASE() oder CLOSE in den Grundzustand zurückversetzt werden. Nur durch CLOSE wird ein dynamisches AO entladen. RELEASE allein setzt alle internen Variablen eines AOs in den Grundzustand zurück, ohne das AO zu schließen. Sie ist Teil des "Creators" für die Einstellung des Grundzustands.
  12. ZYKLUS
    Ein ZYKLUS ist ein AO, das in definierten Zyklen arbeitet. Es ist eine Zyklus-Variable und eine ?ZYKLUS_NEXT-Funktion erforderlich. Diese Funktion bestimmt, ob ein Durchlauf abgearbeitet ist oder alle Durchläufe abgearbeitet sind und schaltet gegebenenfalls die Zyklus-Variable fort. Die Zyklus-Variable "zählt" die durchlaufenen Zyklen und kann zur Adressierung z.B. von Array-Komponenten verwendet werden. Ein ZYKLUS-AO hat als Basis-Eigenschaften (Flags): INITIALISIERT, AKTUELLER_DURCHLAUF_ABGEARBEITET, NÄCHSTER_DURCHLAUF und ALLE_DURCHLÄUFE_ABGEARBEITET (DISABLE). Die Eigenschaften werden durch RELEASE und CLOSE in den Grundzustand versetzt. Eine Zyklus-Variable ist nicht immediate. Alle CTI-Instruktionen müssen "per Hand" in eine compilierbare Programmiersprache übersetzbar sein.
  13. Die Ausführung eines CTI-Programms muss "getaktet" erfolgen. Hierbei werden alle (auf Grund erfüllter Bedingungen) erreichbaren CI-Anweisungen und -Instruktionen innerhalb eines "Taktes" genau einmal ausgeführt ; d.h. die Instruktionen von CIs ohne erfüllte Bedingung und CIs, die auf Grund nicht erfüllter Prio-Bedingungen nicht angesprochen werden, bleiben unausgeführt. Innerhalb eines Taktzyklus dürfen keine Variablen oder sonstigen Daten geändert werden, die im Taktzyklus auch gelesen werden, es sei denn sie sind ausdrücklich "immediate" (jeder Lese-Zugriff muss auf originale Daten erfolgen). Hieraus ergibt sich, dass alle RW-Variablen (und anderen Datenobjekte) einen Read- und einen Write-Anteil besitzen müssen (, sind also keine Skalare mehr, sondern "Vektoren"). Konstanten und WO-Objekte können weiterhin skalar bleiben. Der Write-Anteil wird am "Taktende" (, wenn alle zum Takt gehörenden CI-Instruktionen ausgeführt wurden) systemimmanent auf den Read-Anteil zurückkopiert. "Außerhalb" aller Takteinheiten müssen Read- und Write-Anteil identisch sein.
    Funktionen bilden ein eigenes "Taktobjekt". Hierzu werden die Read-Anteile aller externen RW-Objekte, auf die die Funktion zugreift, kopiert und alle Rückabbildungen von Write- auf Read-Anteile durch funktionsinterne Takte wie gehabt an den Kopien durchgeführt. Die Write-Anteile von (externen) Referenzobjekten werden direkt geschrieben (sind immer "immediate").  RETURN und CLOSE werden erst ausgeführt, wenn alle erreichbaren CI-Anweisungen des letzten Taktes, während dessen die RETURN-oder CLOSE-Instruktion angesprochen wird, ausgeführt wurden. Eine Rückabbildung der Write- auf die Read-Anteile erfolgt für externe RW-Referenzobjekte durch die Funktion nicht. Bei internen statischen Variablen transparenter Funktionen erfolgt die Rückabbildung regulär bei jedem Taktende und durch RETURN bzw. CLOSE. Transparente Funktionen beginnen also stets mit einem neuen Takt.
    RW- und WO-Objekte dürfen innerhalb eines Taktzyklus nur einmal beschrieben werden (auch Spiegelungen).
  14. Daten-Validierung
    Das CTI-ES sieht vor, dass alle Datenobjekte mit Bedingungen für den Zugriff auf sie versehen werden können. Die Prüfung geschieht zur Entwicklungszeit. Ein Zugriff ist nur gültig (valid), wenn die Bedingungen, unter denen die CTI-Instruktion ausgeführt wird, während derer der Datenzugriff erfolgt, mit den Validitätsbedingungen des Datenobjekts übereinstimmt. Validitätsbedingungen können notwendig, hinreichend und optional sein. Optionale Bedingungen dürfen den Ausführungsbedingungen lediglich nicht widersprechen, können aber auch ohne Bezug dazu sein. Eine erfüllte hinreichende Bedingung setzt alle anderen Bedingungen außer Kraft (impliziert also notwendig&hinreichend). Ist keine hinreichende Bedingung erfüllt, so müssen alle notwendigen erfüllt sein und keiner optionalen darf widersprochen werden.
    Die Validierung umfasst auch ein Flag für die Initialisierung von Variablen, welches vor jedem Lesen der Variablen gesetzt werden muss. Die Überprüfung zur Entwicklungszeit setzt einen vollständigen "Verfolgungsalgorithmus" des CTI-ES voraus, der den Nachweis erlaubt, dass unter allen möglichen Bedingungen vor dem Lese-Zugriff auf eine Variable eine Initialisierung erfolgt ist.
  15. Modularisierung, Modulselektion

- Das CTI-ES  soll so arbeiten, dass neue Anweisungen immer dann eingegeben werden können, wenn sie mir einfallen (oder aus einer Datei gelesen werden können).
- Das CTI-ES soll für die Einordnung einer neuen CI alle vorhandenen Funktionen und Datenobjekte zur Auswahl stellen, die neue Anweisung im Kontext sofort prüfen und nötigenfalls anpassen (z.B. bezüglich der Namen von Datenobjekten).
- Für alle Funktionen, Datenobjekte und Anweisungen müssen ausführliche Erklärungstexte abrufbar sein.
- Die Bedingungen einer CI oder eines CI-Blocks müssen zusammengefasst darstellbar und in der Darstellung nach konjunktiven und disjunktiven Verknüpfungen gegliedert sein.
- Aufzeigen der Zusammenhänge von Datenobjekten.

CTI-Programmierung

Zuerst werden alle Anweisungen, Bedingungen und Vorgänge, die einem einfallen, sprachlich formuliert. Hierbei ergibt sich i.d.R. eine Daten- und Arbeitsvariablenstruktur. Auf diese Struktur aufbauend werden alle sprachlich formulierten Anweisungen in CTI-Instruktionen umgesetzt. Deren Modularisierung kann später erfolgen, bzw. es ergeben sich dabei auch Funktionsdefinitionen, die später ausgearbeitet werden. Das CTI-ES sorgt später für die Einhaltung der systemspezifischen Randbedingungen und Vollständigkeit. Die Programmierung kann dann durch Eingabe einzelner Anweisungen (unter Aufruf von Modulumgebungen und Einordnungshilfen) inkremental fortgesetzt werden. Durch direkte Umsetzung inkrementaler CTI-Instruktionen in Maschinencode kann dies sogar zur Programm-Laufzeit erfolgen und sofort wirksam werden. Dies sprachliche Umsetzung in CTI-Instruktionen kann mit entsprechendem Aufwand halb- oder vollautomatisch erfolgen. Hierzu muss das CTI-ES lernfähig gemacht werden, sowohl für die Umsetzung Sprache-CTI, als auch für die Compilierung von CTI in C++ oder Maschinencode.

Tabellarische Entwicklung

Zur besseren Darstellung, insbesondere für die Heraushebung und Gültigkeitsbereichs-Erkennung von Prio-Bedingungen, eignet sich die tabellarische Darstellung. Prio-Bedingungen belegen dabei eine eigene Spalte S und sind zu tieferen Zeilen Z hin gültig, bis in der selben oder in einer weiter links gelegenen Spalte in einer tiefer gelegenen Zeile Z' wieder eine Prio-Bedingung steht (Felder in Spalte S zwischen Z und Z' leer). Die parallelen Anweisungen stehen untereinander in der äußerst rechten noch belegten Spalte der jeweiligen Zeile und werden unter den UND-verknüpften Bedingungen in den Spalten weiter links ausgeführt:

  Prio1 Bed0 Bed_0A Anw_0A1
Anw_0A2
      Bed_0B Anw_0B
Prio2 PBed2 Bed1 Bed_1A Anw_1A1
Anw_1A2
Anw_1A3
Bed3 Anw_3      

entspricht:

Prio1 && Bed0 && Bed_0A: Anw0A1 ; Anw_0A2.
Prio1 && Bed0 && Bed_0B: Anw0B.
Prio2 && PBed2 && Bed1: Anw1A1 ; Anw_1A2 ; Anw_1A3.
Bed3: Anw_3.

Die Bedingungen in einer Spalte müssen eine vollständige disjunkte widerspruchsfreie (automatisch zu prüfende) Zerlegung bilden:
~(B1 | B2 ...| Bn) == FALSE und
für alle i != j gilt  (Bi && Bj) == FALSE und (Bi ~Bj) == FALSE


Übungen:

CTI für Suchalgorithmus mit inverser Vergleichsrichtung

Suchcode-Pointer                 scp        Suchcode-Anfangs- und Endpointer (Folgeadresse)    sca, sce
Vergleichsstring-Pointer       vsp        Vergleichsstring-Länge                        vl < 254
attribut-tabelle[c]                 atb      Attributtabellen-Länge    256
Vergleichszeichen                   c
match-Pointer-Tabelle[m]        mpt    mpt-Index    m        

memset(atb,0xFF,0x100)    ;
// for ( i= 0 ; i < 256 ; i++)  atb[i]= 255   ;        // atb initialisieren zu unbelegt

// Vergleichszeichen als atb-Index ; letzte Position im Vergleichsstring
for ( i= vl-1 ; i >= 0 ; i--)  atb[vsp[i]]= atb[vsp[i]] == 255 ? i : atb[vsp[i]]     ;

for ( m= 0 , scp= sca ; scp < sce ; scp++)
{    for ( i= vl-1 ; i >= 0 ; i-- )
        {  p=  atb[scp[i]]    ;
           if ( p == 255 ) { scp+= i ; break    ;  }    ;                // Suchcode-Pointer auf Zeichen (kein Vorkommen)
           if ( p == i ) continue    ;                                         // (letztes) Vorkommen an der gleichen Position
           if ( i > p ) { scp+= i-p-1   ; break    ; }    ;               //  synchronisieren (Zeichen beim Folgevergleich richtig stehend)
           if ( scp[i] != vsp[i] ) break    ;
        }    ;
     if ( i < 0 ) mpt[m++]= scp    ;
}    ;