Hinweise fuer die Arbeit mit dem Apply-EuLisp-Compiler ====================================================== 1. Allgemeines -------------- Die zugrundeliegende Sprachbeschreibung fuer den Apply-EuLisp-Compiler ist "Programming Language Eulisp Version 0.99" (nachfolgend mit EL0.99 abgekuerzt). Implementiert wurde der groesste Teil von Level-0, die Einschraenkungen sind in Abschnitt 3 beschrieben. Ausser der im Kapitel 9 von EL0.99 definierten Modulsyntax, bei der die einzelnen Modul-Direktiven (import, syntax, expose, export) als Schluesselwoerter genutzt werden, wird aus Kompatibilitaetgruenden auch weiterhin die alte Form aus 0.75 als top-level-listen unterstuetzt. Wenn ein Modul diese nutzt, so wird beim Laden der Filename mit dem Zusatz [old style] versehen. Z.B.: ;.loading module /home/saturn/imohr/Lisp/ApplyModules/xxx.am[old style] Sowohl die Namen der Module als auch die darin enthaltenen Klassen, Funktionen, Makros und Spezialformen sind der Sprachbeschreibung zu entnehmen, so dass eine Beschreibung hier nicht notwendig ist. Der Modul-Name (d.h. der auf defmodule folgende Name) und der Filename des Modules muessen identisch sein; die Extension muss .am sein. 2. Voraussetzungen ------------------ Voraussetzungen zur Nutzung des Apply-EuLisp-Compiler sind: Hardware: Sun SPARC-Architektur (Sun4m, Sun4c) Software: Franz Allegro Common Lisp 4.1 (fuer andere Lisp-Systeme sind evtl. Anpassungsarbeiten erforderlich) GNU unzip GNU-C-Compiler gcc 2.2 oder spaeteres Release 3. Folgende Einschraenkungen sind zu beachten: ---------------------------------------------- 3.1. Es sind noch nicht verfuegbar: - generic-lambda; - unwind-protect; - Parallelverarbeitung (Module lock und thread); 3.2. Es sind noch nicht vollstaendig: - deep-copy: Methode fuer Klasse fehlt; - converter: Methoden fuer die Klassen und fehlen; - format: die Direktiven ~e, ~f und ~g sind noch nicht verfuegbar; - Makros koennen nur eingeschraenkt genutzt werden (siehe unten); - scan: ist nicht implementiert, es kann die Funktion read verwendet werden. 3.3. Bekannte Probleme: 1. Zur Compile-Zeit (beim Einlesen der .am-Module) werden Zeichen innerhalb von Symbolnamen generell in Grossbuchstaben ueberfuehrt. Wenn Symbolnamen zur Laufzeit eingelesen werden (read), so wird zwischen Gross- und Kleinschreibung unterschieden. Innerhalb von Strings wird Gross/Kleinschreibung beruecksichtigt. 2. Konstanten vom Typ koennen z.Z. nicht benutzt werden. Gleitkomma-Zahlen koennen jedoch dynamisch erzeugt werden: (defmodule ... (import (double-float ... (only (%double-float) tail) (only (make-dble) double-float-i)) syntax ...) (deflocal double (make-dble #%d-2.3)) (deflocal double (make-dble #%d15.6)) ... ) Man beachte hierbei, dass zusaetzlich je eine Bindung aus den Modulen tail bzw. double-float-i importiert werden muessen. Die Zahlen werden als TAIL- Literale notiert. 3. Abschnitt 9.4 in EL0.99: Der Modul selbst kann nicht in einer expose-Direktive angegeben werden. 4. Abschnitt 9.5 in EL0.99: Syntaximporte von Spezialformen und Standardmakros werden noch nicht unterstuetzt. Sie werden z.Z. speziell behandelt. 5. Numerische Fehler lassen sich zwar mit with-handler abfangen aber nicht fortsetzen. 6. Eine unendliche Rekursion, bei der der rekursive Aufruf auf dem top-level-Niveau innerhalb der Funktion steht, wird falsch uebersetzt: (defun loop () ... (loop)) In allen anderen Faellen wird richtiger Code erzeugt: (defun loop () (if ... (progn ... (loop)) (progn ... (loop)))) 7. Der Doppelpunkt ":" darf innerhalb von Symbolnamen nicht verwendet werden. 8. Die Funktion newline ist fehlerhaft. 9. tables koennen z.Z. nicht benutzt werden. 10 evenp arbeitet nicht korrekt. 3.4. Makros Makros sind bisher nur eingeschraenkt verwendbar. Es existiert auch noch keine portable Moeglichkeit Makros zu definieren, da die aktuelle Definition von EuLisp noch nichts ueber die Semantik und den Sprachumfang von Makros aussagt. In 'defmacro' koennen folgende Sprachelemente von EuLisp (Level 0) benutzt werden: Objekte: Listen, Symbole, Zahlen, Zeichen Syntax: Quasiquote (` , ,@) Aufrufe einfacher Funktionen (nicht von generischen) konstante globale lexikale Bindungen setq progn if let und let* Funktionen: car, cdr, list, null, cons, append eq + und alle mit 'defun' definierten Funktionen, die auf diese aufbauen 4. Arbeit mit dem Apply-EuLisp-Compiler --------------------------------------- Die gesamte Funktionalitaet des EuLisp-Compilers ist in dem Modul eulisp-level-0 enthalten. Wird der Modul eulisp-level-0 importiert, so werden von diesem alle zum Eulisp level 0 gehoerenden Basismodule importiert und alle zugehoerigen Spezialformen, Klassen, Funktionen und Makros aus den einzelnen zum Level 0 gehoerenden Modulen exportiert. In den import- und export Spezifikationen sind dann folgende Angaben zu machen: (defmodule test-module ( import (eulisp-level-0 nutzer-module) syntax (eulisp-level-0 nutzer-syntax-module) export (fkt1 fkt2 ...) expose (...) ) ...) Benoetigt ein Nutzer nicht die gesamte Funktionalitaet, so kann er in seiner Importliste die einzelnen Module angeben, die seiner gewuenschten Funktionalitaet entsprechen. Dies ist z.B. sinnvoll, um Lade-Zeit fuer die Module zu sparen. Wird nicht die gesamte Funktionalitaet von EuLisp Level 0 gewuenscht, so muessen ausser den gewuenschten Basismodulen zusaetzlich die Module tail und eulisp-kernel sowohl in der import- als auch in der syntax-Direktive angegeben werden. (Beim Einladen vom Modul eulisp-level-0 sind diese Importe automatisch mit enthalten). 5. Der Aufruf des Apply-EuLisp-Compiler --------------------------------------- Es sind zwei Environment Variablen zu setzen: APPLYROOT - zeigt zum Directory vom Apply-EuLisp-Compiler ACL - enthaelt den Pfad, um Franz Allegro 4.1 zu starten Der Aufruf des Apply-EuLisp-Compilers geschieht von Unix aus: compile.apply test-module Danach erscheinen auf dem Bildschirm folgende Ausgaben: Apply: (compile-application ^test-module) on host saturn (Aufruf des Apply-EuLisp-Compiler auf dem Host Saturn) /export/home/saturn/xxx/Lisp (Ausschrift des Arbeitsdirektories) Allegro CL 4.1 [SPARC; R1] (6/10/93 8:50) Copyright (C) 1985-1992, Franz Inc., Berkeley, CA, USA. All Rights Reserved. ;; Optimization settings: safety 1, space 1, speed 3, debug 2 ;; For a complete description of all compiler switches given the current ;; optimization settings evaluate (EXPLAIN-COMPILER-SETTINGS). USER(1): (Start des Lisp-Systems) --- resetting the compiler --- (Der Compiler wird initialisiert) --- loading basic modules --- .... (alle zugehoerigen Basismodule werden geladen) --- loading application modules --- ;loading module xy (die zugehoerigen Nutzermodule werden geladen) --- marking all exported bindings --- (die zu exportierenden Bindungen der einzelnen Module werden markiert) --- computing discriminating functions -- (die Diskriminationsfunktionen der generischen Funktionen werden berechnet) --- converting to MZS --- (es erfolgt die Umwandlung in die maschinennahe Zwischensprache) SsssssssSSS (s bedeutet, dass die Seiteneffektanalyse fuer einzelne Funktionen gemacht wird, S zeigt die Zusammenfassung dieser Analyseergebnisse) ****iii*****ii***i**i***i**i*i**...b...........b..b (jeder Stern bzw. Punkt gibt die Behandlung einer Funktion an; i bedeutet, dass in-line gemacht wird; b bedeutet, dass die Typen innerhalb der Typinferenz fuer die einzelnen Funktionen ausbalanciert werden) --- collecting static instances --- (alle statischen Daten werden eingesammelt) --- converting MZS to LZS --- (es erfolgt die Umwandlung von der maschinennahen Zwischensprache in die Lisp-nahe Zwischensprache) --- generating C-code --- ************************ (fuer jede generierte C-Funktion wird ein Stern ausgedruckt) --- end of compilation --- Total number of analysed function calls: 3539 Total number of joined function call descriptors: 14 (0.40 %) Total number of inferred function type schemes: 380 Total number of joined type scheme descriptors: 82 (21.58 %) Total number of inferred classes: 8405 "end of compilation" ("end of compilation" zeigt die erfolgreiche Abarbeitung der Funktion compile-application an) USER (2): EOF ; Auto-exit (Verlassen des Lisp-Systems) Nach der Erzeugung des .c und .inst Files durch den Apply-EuLisp-Compiler erfolgt die Compilation und das Linken der C-Quellen mit Hilfe des GNU-C-Compilers: Apply: successful compilation of test-module to C Apply: test-module.c was created gcc -o test-module -O2 -fwritable-strings -I /home/saturn/wheick/Lisp/ApplyC test-module.c $APPLYROOT/ApplyC/apply.a -lm Dabei koennen sowohl beim Compiler- als auch beim Link-Lauf Warnungen auftreten, die keine Auswirkung auf die Lauffaehigkeit des erzeugen Programmes haben. Der Aufruf des fertigen Programmes geschieht mit test-module 6. Beispiele ------------ In dem Modul tm-tak wird die Funktion tak definiert und exportiert. Durch den Import von eulisp-level-0 steht die volle Funktionalitaet des Level 0 von Eulisp zur Verfuegung (obwohl diese nicht genutzt wird). Das zugehoerige File, in dem der Modul tm-tak steht, muss den Namen tm-tak.am haben. (defmodule tm-tak ;Definition des Moduls tm-tak ( import (eulisp-level-0) syntax (eulisp-level-0) export (tak) ;export der funktion tak aus dem Modul tm-tak ) (defun tak (x y z) (if (null (< y x)) z (tak (tak (- x 1) y z) (tak (- y 1) z x) (tak (- z 1) x y)))) (print (tak 18 12 6)) ; Aufruf der Funktion tak und ; Druck des Ergebnisses ) ; Modulende Das naechste Beispiel zeigt den Anschluss einer C-Funktion (printf) mit Hilfe der in tail verfuegbaren Form %declare-external-function mit Angabe der zugehoerigen Typen und ihre Verwendung innerhalb einer EuLisp-Funktion (my-c-print). Dabei wird die oben definierte Funktion tak aus dem Modul tm-tak benutzt. Hier werden nur die Module importiert, die auch wirklich benoetigt werden Das zugehoerige File muss den Namen test-tak.am haben. (defmodule test-tak ;Definition des Moduls test-tak ( import (tail eulisp-kernel tm-tak) ;Nutzer import syntax (tail eulisp-kernel) ) (%declare-external-function (printf-int %signed-word-integer) ; Name und Ergebnistyp ((strng %string) ; 1. Arg Name und Typ (int %signed-word-integer)) ; 2. Arg Name und Typ language c ; die verwendete Sprache ist C external-name |printf|) ; dort hat die Funktion ; den Namen printf (defun my-c-print (i) (printf-int (%literal %string () ;%literal erzeugt den fuer printf ;benoetigten String "\n Ergebnis von (tak 18 12 6): %d ") (make-swi i)) ;make-swi erzeugt aus einer ;Lisp-Zahl eine Zahl fuer C ()) (my-c-print (tak 18 12 6)) ; Aufruf ) ;Modulende