(** Emacs-Mode: -*-Text-*-  **)
(** Datum: Donnerstag, 11. September 1997, 23:40:05 **)

Folgende Dinge sind mir am Parallaxis-Compiler aufgefallen und sollten
evtl. noch geaendert werden:


------ Makefile ----------------------------------------------

Seit der Tree-Browser da ist, ist das Makefile wieder etwas
durcheinander. D.h. man muesste awk->sed ersetzen (oder umgekehrt),
dann die enstsprechenden Aktionen abhaengig davon, ob DEVELOP gesetzt
ist oder nicht.

Ausserdem waere es schoen, wenn alles Zusaetzliche fuer PVM in ein
Unterverzeichnis kaeme und alles fuer den Tree-Browser in ein weiteres
Unterverzeichnis. (-> auch im CVS umsetzen!)

Als letztes sollte noch ein Verzeichnis da sein, wo die Libraries
gebaut werden. Das sollten im Prinzip zwei Files sein: libp3.a fuer
alles was ohne X geht und libp3X fuer Sachen mit X-Windows.

------ codeLabelRange ----------------------------------------

Die case-Label-Generierung bei codeLabelRange laeuft in eine
Endlosschleife, wenn der obere Wert des Ranges MAX(INTEGER) bzw.
MAX(CARDINAL) entspricht. Dann gibt es einen Ueberlauf. (Siehe auch
FOR-Schleife).

------ Prozedurkoepfe ----------------------------------------

Die Prozedurkoepfe sind immer sehr umstaendlich deklariert. Hier waere
vielleicht ein Macro  ARGS oder PROT sinnvoll.

jetzt:

static void ALLOCATE
#ifdef __STDC__
(ADDRESS adr, CARDINAL len)
#else
(adr, len)
ADDRESS adr;
CARDINAL len;
#endif
{
  ...
}


besser:

static void ALLOCATE PROT((ADDRESS adr, CARDINAL len))

wobei PROT entsprechend zu definieren waere. 

Beispiel:

#define PROT(x) #ifdef __STDC__ x #else () #endif

Allerdings gehen mit dieser Definition die Parameter voellig verloren,
wenn es kein __STDC__ ist. Darum ist diese Definition nicht sehr gut.
Es anders zu machen, ist nicht so einfach, deshalb bleibt es wohl bei
der bisherigen Art und Weise der Handhabung.


----- Hilfsvariablen ----------------------------------------

Bis jetzt wird fuer jeden Term einer Expression eine Hilfsvariable
benannt. Bei groesseren Programmen sind das sehr viele und trotz
Hashing wird irgendwann die Identifier-Liste sehr langsam. Im Prinzip
genuegt es, nur fuer diese Terme eine Hilfsvariable anzulegen, die
auch UseHelpVar = TRUE haben.

(Geht erst, wenn Programm auf TakeHelpVar reagiert, nicht mehr auf
UseHelpVar. Ist aber vorbereitet (siehe parallaxis.cg))

Ausserdem sollten die Regeln fuer die Attributsauswertung von
UseHelpVar nochmal genau angeschaut werden. Hier kann man wohl auch
noch optimieren, da bei einer Expression bis jetzt viel zuviel vorab
ueber Hilfsvariable ausgewertet wird. (Teilweise schon erledigt. Jetzt
noch moegliche Verbesserung: Wenn bei binaeren Ausdruecken ein Teil
ueber Hilfsvariable bewertet werden muss (TakeHelpVar=T) und der
andere Teil nicht (z.B. skalare Konstante), dann kann der gesamte
Audruck in der Hilfsvariablen berechnet werden.

Bsp:  x := x<<5>>+4;

Ist bisher:  H_1 = x[5];
             FOR_ALL_ACTIVE(config) x[PE] = H_1 +4;
Waere neu:   H_1 = x[5] +4;
             FOR_ALL_ACTIVE(config) x[PE] = H_1;


----- Aufruf von Prozeduren mit VAR-Parametern -----------------------------

Wird eine Prozedur aufgerufen, die ein CHAR-Array als VAR-Parameter
hat, dann kann diese Routine faelschlicherweise auch mit einer
String-Konstanten aufgerufen werden. Hier muss eine Fehlermeldung
kommen.

----- Switch fuer Inline-Code ---------------------------------------

In p3 und die Compiler einen Switch einbauen, der es erlaubt, zwischen
kurzem Code (langsam) mit Funktionsaufrufen und langem Code (schnell)
mit Makros zu waehlen. Vielleicht noch abstufbar machen.


----- Diverse Ueberpruefungen -----------------------------------------

Es fehlen noch einige semantische Ueberpruefungen:

o Bei Connections darf in den entsprechenden Dimensionen nur der Typ
  Ausdruck auftauchen, fuer die auch die Configuration deklariert ist.
  Speziell: Bei int nur int, bei char nur char, bei enum nur enum.
  Speziell solte bei char auch eine char-Konstante, z.B. 034C, erlaubt
  sein. Ausserdem sollten Strings mit Laenge >1 verboten werden.

o Bei Array-Deklarationen duerfen keine Parameter der Prozedur
  vorkommen. Bsp:
    PROCEDURE p(x: INTEGER);
    VAR a: ARRAY [1..x] OF CHAR;
  muss verboten sein.

o Bei nicht-qualifiziertem Import (also FROM mod IMPORT id;) muss der
  id auch qualifiziert (mod.id) angesprochen werden duerfen.

o Wird ein Bezeichner aus einem Definition Module importiert, den es
  dort gar nicht gibt, muss eine Fehlermeldung erfolgen.

o IF-Expressions muessen BOOLEAN sein, bis jetzt kommt keine
  Fehlermeldung, wenn nicht.

  MODULE beate1;
  BEGIN
    IF 3 + 5 THEN ELSE END; (*IF*)
  END beate1.

o Wenn eine Variable als Vektor deklariert ist, dann kann man auf sie
  faelschlicherweise als ARRAY zugreifen.

  MODULE fehler22;
  CONFIGURATION quadrat[1..2],[1..2];
  VAR a:quadrat OF INTEGER;
  BEGIN
    a[1,1]:=1;
  END fehler22.

o Auf eine Connection kann faelschlicherweise wie auf eine Variable
  zugegriffen werden.

  MODULE bug_tree;
  CONFIGURATION tree[1..15];
  CONNECTION child: tree[i] -> tree[2*i];
  BEGIN
    child := 3;
  END bug_tree.

o Eine offene Konfiguration kann nicht direkt als Rueckgabewert einer
  Prozedur zurueckgegeben werden, sondern nur konkrete
  Konfigurationen. Allerdings ist die Fehlermeldung bei folgendem
  Programm nicht korrekt.

  MODULE fehler27;
  CONFIGURATION matrix[*],[*];
  CONFIGURATION vek[*];
  PROCEDURE multmatvek(a:matrix OF REAL):vek OF REAL;
  BEGIN
    RETURN vek(1.0);
  END multmatvek;
  CONFIGURATION ma3=matrix[1..3],[1..3];
  CONFIGURATION ve3=vek[1..3];
  VAR
   A:ma3 OF REAL;
   g:ve3 OF REAL;
  BEGIN
    A:=multmatvek(A);(* Faelschlicherweise keine Fehlermeldung *)
    g:=multmatvek(A);(* Unberechtigte Fehlermeldung *)
  END fehler27.


fehler27.pm line   15,  4: Error       assignment of incompatible types
fehler27.pm line   15,  3: Information Expected type: VECTOR 've3' OF REAL
fehler27.pm line   15,  6: Information Found type: VECTOR 'ma3' OF REAL

1 semantic error occured !

o Sobald ein Konstrukt im IMPLEMENTATION MODULE nochmal erklaert wird,
  das schon im DEFINITION MODULE erklaert war, dann muessen diese
  strukturell identisch sein und es muss auch das gleiche Objekt
  angelegt werden (nicht 2 verschiedene). Oder es muss eine
  entsprechende Fehlermeldung kommen.


------ Speicher fuer Configuration -----------------------------------

Der Speicher, der fuer lokale Konfigurationen alloziert wird (mit
malloc) wird nicht mehr freigegeben. Das ist extrem falsch!!!!

***Done***

------ lvalue-Indizes -----------------------------------------

Der Index eines lvalues bei einer Zuweisung wird erst ausgewertet,
nachdem die Vorabberechnung der Hilfsvariablen von der Expression auf
der rechten Seite abgeschlossen ist. In C wird strikt von links nach
rechts ausgewertet, d.h. der Index muss als erstes ausgewertet werden.

Bsp.:  a[f()] := f();
       mit Seiteneffekt in f() (z.B. globale Variable inkrementiert
       und zurueckgegeben)


------ Multiple Expressions -----------------------------------

Muss hier eigentlich eine Kurzauswertung stattfinden? Eigentlich ja!!!
Dann muss die Auswertungsreihenfolge definitiv anders werden. Evtl.
kann man sich die Hilfsvariable auf dem ersten und letzten Ausdruck
sparen.

------ .px-File erweitern ----------------------------------------

Ins .px-File sollten auch Konstanten rein:

C-name P3-name value

Falls noetig, dann ein "!" an den Anfang der Zeile


------ Harry fragen: ----------------------------------------

Was soll die generierte Funktion COMPUTE_config fuer jede generische
Konfiguration machen?


------ Ueberpruefen ----------------------------------------

Muessen die Deklarationen in CodeDefProg() nicht auch in einer
bestimmten Reihenfolge (erst Const, dann Config, Type, etc) ausgegeben
werden? Bis jetzt kommen sie noch durcheinander.

------ Types.c ----------------------------------------

In Funktion Coercible, Fall case kSymProcType:

hier kann man auch hinkommen, wenn nicht beides Prozedurtypen sind.
Hier ist also Rueckgabewert FALSE angesagt, wenn t2 kein Prozedurtyp
ist.

Im Zusammenhang damit pruefen, was passiert, wenn man 2 Prozedurtypen
addiert, vergleicht, etc.

*** Done ***

------ Konfigurations-Test ----------------------------------------

PROCEDURE f(): grid OF INTEGER;
...
RETURN 5;


Der Compiler sollte selbst die Konfiguration erkennen. Momentan noetig
ist RETURN grid(5);

----- Pruefung auf Seiteneffekte ------------------------------

Es koennte ein Attribut eingefuehrt werden, das berechnet, ob eine
Funktion Seiteneffekte hat oder nicht. Hierbei kann vielleicht nicht
immer garantiert werden, dass man Seiteneffekte erkennt, aber man kann
vielleicht garantieren, dass bestimmte Routinen *keine* Seiteneffekte
haben. Beispiel: keine Pointer, keine Routinen mit Seiteneffekten
aufgerufen, keine globalen Variablen oder VAR-Parameter angesprochen
-> keine Seiteneffekte.

----- RETURN --------------------------------------------------

RETURN kehrt bis jetzt *immer* zurueck. Das darf nicht sein, nur jeder
aktive PE muss *logisch* zurueckkehren, d.h. aus allen Active-Sets der
Funktion genommen werden. Durch ALL: evtl. mehrere RETURNs eines PEs
moeglich, es sei denn, man verbietet RETURN innerhalb eines ALL. Das
gleiche koennte man fuer ein paralleles EXIT verbieten.

----- Type --------------------------------------------

Typdefinitionen innerhalb von einer Prozedur sind falsch, wenn sie
sich auf eine lokale Konfiguration beziehen.

PROCEDURE f();
CONFIGURATION config[...];
TYPE t = config OF INTEGER;
VAR v: t;                  (* wird falsch *)
VAR w: config OF INTEGER;  (* wird richtig *)
...
END f;

----- reservierte Woerter ----------------------------------------

Die Liste der reservierten Woerter, die automatisch umbenannt werden,
muss um die Namen erweitert werden, die in den Headerfiles deklariert
sind, die von SYSTEM_C.h eingebunden werden. Dazu muessen _argc, _argv
und _envp kommen (sind in main() deklariert).

----- STORAGE ---------------------------------------------------

Es muss noch eine Fehlermeldung hin, wenn NEW/DISPOSE gemacht wird,
und diese nicht aus STORAGE importiert wurden.

(D.h. NEW/DISPOSE muessen aus SYSTEM weg.)

----- conf(Parameter) -------------------------------------------

Innerhalb von Prozeduren kann auf respezifizierte Konfigurationen
zugegriffen werden, indem man den Namen eines Parameters angibt. Idee:
conf(parameter). Probleme: 

1.) bei runden Klammern geht das schief:  RETURN grid(x)(5);  ???
2.) bei eckigen Klammern geht das schief wegen:
    CONNECTION list: grid[x][i,j] -> grid[x][i+1, j+1];

IDEE: Renaming der Parameter-Konfigurationen:

  PROCEDURE p(x: mygrid1=grid OF INTEGER;
              y: mygrid2=grid OF INTEGER;
              z: mygrid1      OF INTEGER): mygrid2 OF INTEGER;

  VAR a: mygrid1 OF REAL;
  CONNECTION lokright: mygrid1[i,j] -> mygrid1[i+1,j];
  ...
  a := mygrid1(5.0);


IDEE: Anstatt einer Konfiguration kann auch der Name eines Prozedur-
Parameters bzw. allgemein der Name einer Variablen stehen.

  PROCEDURE p(x: grid OF INTEGER; y: grid OF INTEGER; z: x OF INTEGER): 
                                                y OF INTEGER;
  VAR a: x OF REAL;
  CONNECTION lokright: x[i,j] -> x[i+1,j];
  ...
  a := x(5.0)

Problem dann: mit Prozedurtyp-Variablen laesst sich nicht casten, weil
das Konstrukt einem Aufruf der Prozedur entsprechen wuerde.

------ AND, OR, NOT -------------------------------------------------

Im Language-Report schauen, ob diese auch fuer CARDINAL/INTEGER
gelten.

------ doppeltes -,+ -----------------------------------------------

Taucht im Parallaxis-Quellcode ein doppeltes minus oder plus auf, dann
wird das im erzeugten C-Text nicht korrekt geklammert und entsprechend
als Dekrement- bzw. Inkrement-Operator erkannt.

CONST a=-(-5);

wird zu

#define a (--5)
           ^^ hier ist dekrement

------ mehrere generische Konfigurationen bei Parametern -----------

Wird eine generische Konfiguration an eine Prozedur uebergeben, evtl.
auch mehrfach, dann geht alles klar. Also z.B.

CONFIGURATION grid[*],[*];
PROCEDURE p(x: grid OF INTEGER; y: grid OF REAL): grid OF CHAR;

Dabei muss bis jetzt immer alles genau die gleiche Auspraegung der
Konfiguration sein, also alle Parameter muessen von derselben
Respezifikation sein.

Mehr als eine generische Konfiguration wird bis jetzt im Compiler noch
nicht zugelassen. D.h. auch verschiedene generische Konfigurationen
sind nicht erlaubt!

CONFIGURATION grid[*],[*];
CONFIGURATION list[*];
PROCEDURE p(x: grid OF INTEGER; y: list OF INTEGER);

ist *nicht* moeglich. Dann sollte aber auch die korrekte Fehlermeldung
kommen. (Einfach Fehlermeldung xxWrongGenericParams aendern.)

Betroffene Stellen: Symbols_GetResultType2()
Hier muesste eine Aenderung erfolgen, wenn mehrere offene
Konfigurationen moeglich sein sollen.

Sowas sollte irgendwann gehen:

MODULE fehler28;
CONFIGURATION matrix[*],[*];
CONFIGURATION vek[*];
CONFIGURATION ma3=matrix[1..3],[1..3];
CONFIGURATION ve3=vek[1..3];
VAR A:ma3 OF REAL;
    g,e:ve3 OF REAL;
PROCEDURE multmatvek(a:matrix OF REAL;g:vek OF REAL;VAR result:vek OF REAL);
END multmatvek;
BEGIN
  multmatvek(A,g,e);
END fehler28.

------ Qualid -> ConfigId ----------------------------------------

In der abstrakten Syntax sind alle Referenzen auf Konfigurationen
immer mit Qualid geloest. Das Problem ist, dass bei der
Attributauswertung der Qualid erst sehr spaet ausgewertet werden kann,
da er in der Liste *aller* Objekte suchen muss, die erst in Objects3
verfuegbar ist. Da eine Konfiguration aber eher einem Type entspricht,
muss er schon in Objects1 gesucht werden. Darum waere es sinnvoller,
Konfigurationen nicht mit Qualid sondern mit TypeId zu benennen, da
diese schon frueher gefunden werden koennen. Dies wuerde einige Zyklen
bei der Attributberechnung vermeiden.

Zusatzgedanke: Es ist im Gespraech, dass ueberall, wo Konfigurationen
stehen koennen, auch (Vektor-)Variablen stehen duerfen sollen. Das
bedeutet dann wieder einen Qualid. Darum sollte vielleicht doch nicht
direkt TypeId genommen werden, sondern ein neuer Id, z.B. ConfigId.
Der kann sich zuerst mal wie TypeId verhalten. Kommt dann die
Geschichte mit den Variablen dazu, dann kann man diese Beschreibung
erweitern, falls noetig. (Idee: auch alle SymVar schon in Objects1
aufnehmen, dann kann man sie suchen und die Config daraus nehmen,
Zumindest den Config-Eintrag kann man ja schon kurz nach Objects1
machen, zumindest dann, wenn Config kein Qualid mehr ist.)


------- Anzahl Dimensionen bei <: :>-Angaben testen -------------

CONFIGURATION c[1..5];

SEND.<:a,b,c,d,e,f:>(x, y);

ist bis jetzt durchaus moeglich und baut kraeftig Fehler in den Code.

------- Userdefinierte Reduce-Funktionen tun nicht ----------------

Das ganze Sach mit vom Benutzer definierten Reduce-Funktionen
erscheint mir mehr als wackelig in der C-Version. Bei SEND.<: :> (also
CodeStmtsSend bei DimSpec) habe ich mal versucht zu aendern, aber es
reicht nicht. Der Reduce ist auf einer Konfiguration definiert,
erwartet also Vektoren als Parameter. An der Stelle, wo reduziert
wird, ist aber nur eine skalare Routine noetig. Das scheint also
absolut noch nicht zu tun.

------- vektorielle Random-Zuweisungen muss nicht ueber Hilfsvar --------------

Durch eine Aenderung werden jetzt alle Random-Werte ueber
Hilfsvariablen ausgewertet. Dies muss bei vektoriellen Werten nicht
unbedingt sein (oder doch? Nochmal ueberlegen!). Hier kann evtl. in
parallaxis.cg in Modul UseHelpVar bei FuncCall geaendert werden:

  ... || Symbols_IsRandom(Designator:Type) || ...

aendern in:

  ... || (Symbols_IsRandom(Designator:Type) && ...!= kSymVector) || ...
                                                ^ was hier hin muss ist
                                                  die Frage
   irgendwas in der Art "Type->Kind"


------- UPPER, LOWER sollen Typ zurueckliefern --------------

MODULE testUPPER;

TYPE enumtype=(one, two, three, four);

CONFIGURATION conf4d[-3..5],[one..three],['a'..'e'],[FALSE..TRUE];
  test[MAX(CARDINAL)-3..MAX(CARDINAL)];

Je nach Dimension sollen UPPER und LOWER entsprechenden Typ (INTEGER,
Aufzaehlungstyp, CHAR, BOOLEAN oder CARDINAL) zurueckliefern. Also z.B.:

UPPER(conf4d, 2) = 'e'

###### Problem: das kann nicht gehen:

  y := UPPER(conf, x);

Hier kann dem Ausdruck kein Typ zugewiesen werden, da je nach x der
Typ anders sein kann.

---> gestorben, laesst sich nicht realisieren ########



------- Open Array of Vectortype geht nicht -----------------------

PROCEDURE p(a: ARRAY OF grid OF INTEGER);

laesst sich syntaktisch nicht eingeben. Es fehlt eine Regel in
parallaxis.ell.

  grid OF ARRAY OF INTEGER    geht hingegen.


------- Offene Konfiguration erzeugt GENERIC_CONFIGURATION in main() --------
MODULE bug_open2;
CONFIGURATION xyz[*];
CONNECTION ring: xyz[i] -> xyz[(i+1) MOD LEN(xyz)];

CONFIGURATION actual = xyz[0..9];

END bug_open2.

erzeugt:

static CONFIGURATION actual;
int main()
{
  INIT_CONFIGURATION("actual", &actual, 1);
  SET_BOUNDS(&actual, 0, 0, 9);
  INIT_STACKS(&actual);

  INIT_GENERIC_CONNECTION("ring", &actual);
  SOURCE_ARRAY = (INTEGER *) malloc(sizeof(INTEGER) * RANK(actual));
  { INTEGER i; for (i = LOWER(actual, 1); i <= UPPER(actual, 1); i++) {
    SOURCE_ARRAY[0] = i;
    DESTINATION_ARRAY = (INTEGER *) malloc(sizeof(INTEGER) * RANK(actual));
    DESTINATION_ARRAY[0] = MOD1(i + 1, LEN(GENERIC_CONFIGURATION));
    REGISTER_GENERIC_LINK("ring", &actual, SOURCE_ARRAY, DESTINATION_ARRAY);
    free(DESTINATION_ARRAY);
  } }
  free(SOURCE_ARRAY);
}

Problem: Beim berechnen der konkreten Connection fuer actual greift
der Code auf den Expression-Knoten zu, der zur Connection-Deklaration
gehoert. Dort steht aber die offene Konfiguration xyz drin. Darum wird
im Code dann GENERIC_CONFIGURATION erzeugt.


------- Fehlende Warnung bei WriteInt() --------

Wird WriteInt() mit einem CARDINAL aufgerufen, dann sollte zumindest
eine Warnung ausgegeben werden. Das gleiche gilt wahrscheinlich auch
fuer andere Kombinationen.


------- Typen etwas differenzierter angeben --------

Typen fuer INTEGER, CARDINAL usw. nicht einfach als long oder unsigned
long definieren. Dies fuehrt auf DEC-Alpha zu 64-Bit-Werten.
Alternativ sollten vielleicht die Berechnungen auf fehlerhafte Casts
untersucht werden, denn eigentlich sollten die langen Werte nichts
ausmachen.

------- Mengen gehoeren kraeftig getestet -----------

Die Mengenoperationen in Parallaxis gehoeren dringend mal
durchgetestet. Es scheinen diverse Warnungen und Fehlermeldungen zu
fehlen. Beispiel:

MODULE set;
BEGIN
  IF 5 IN {1,40} THEN  END; (*IF*)
END set.

liefert:

set.c: In function `main':
set.c:15: warning: left shift count >= width of type

