next up previous
Nächste Seite: Lokale Klassen in Java Aufwärts: Compilerbau Vorlesung, Wintersemester 2003 Vorherige Seite: Unterprogramme (I) (22. 10.

Unterprogramme (II) (27. 10. 03)

Wiederholung: Statische Ketten

$ $Id: wdhlg.tex,v 1.1 2003/10/26 23:25:31 joe Exp $ $

int n1 ( int x1 ) {
  int n2 ( int x2 ) {
    int n3 ( int x3 ) {
      return x3 + x2 + x1; } // benuzten
    return n3 (n3 (0)); }    // verlängern
  return n2 (n2 (0)); }      // verlängern

Kette verlängern:
movl  %esp, %ebp
subl  $24, %esp
leal  8(%ebp), %eax
movl  %eax, -8(%ebp)
movl  %ecx, -4(%ebp)
movl  $0, (%esp)
movl  %ebp, %ecx 
call  n3.1

statische Kette benutzen:
movl -4(%ecx), %edx 
movl -8(%ecx), %eax
movl (%eax), %eax
addl 8(%ebp), %eax
movl -4(%edx), %edx 
addl (%edx), %eax

Zeiger auf Nested Functions

$ $Id: problem.tex,v 1.1 2003/10/26 23:25:31 joe Exp $ $

int twice 
  ( int fun (int)
  , int x ) 
{ 
  return 
    fun (fun (x)); 
}

int f0 ( int x0 ) {
  return x0 * x0;
}
int f1 ( int x1 ) {
  int f2 ( int x2 ) {
    int f3 ( int x3 ) {
      return x3 + x2 + x1;
    }
    return twice (f3, 0);
  }
  return twice (f2, 0);
}

Für twice(f0,*) reicht einfacher Zeiger auf f0,
für twice(f2,*) braucht man closure von f2 (mit Frame von f1).

Lösung in gcc: Trampolins

$ $Id: trampolin.tex,v 1.1 2003/10/26 23:25:31 joe Exp $ $

Entwurfs-Ziele:

Falls Funktion g innerhalb von f definiert, und Closure (Zeiger auf) g benötigt, dann:

Trampolin-Beispiel

int f2 ( int x2 ) {
  int f3 ( int x3 ) { return x3 + x2 + x1; }
  return twice (f3, 0);
}

movl %esp, %ebp
leal 8(%ebp), %eax
subl $56, %esp
leal -40(%ebp), %edx
movl %eax, -16(%ebp)
movl $f3.3+22, %eax
movl %ecx, -12(%ebp)
leal -8(%ebp), %ecx
subl %ecx, %eax
movl %eax, -34(%ebp)
xorl %eax, %eax
movb $-71, -40(%ebp)
movl %ecx, -39(%ebp)
movb $-23, -35(%ebp)
movl %eax, 4(%esp)
movl %edx, (%esp)
call twice

Funktionen als Werte

$ $Id: funarg.tex,v 1.3 2003/10/29 18:30:55 joe Exp $ $

Funktionen als Werte von Argumenten. Beispiel in Pascal, in C.

Funktionen als Rückgabe-Werte. Beispiele? Warum nicht in Pascal?

Beachte: Wenn eine Funktion als Wert zurückgegeben werden soll, braucht man dazu auch ihre statische Kette. Die entsprechende dynamische Kette ist zu dem Zeitpunkt evtl. schon verschwunden!

Funktionen als Werte: Beispiel

In C geht es nicht (ausprobieren!)
typedef int fun (int);

fun * plus (int x) {
  int f (int y) { 
    return x + y; 
  }
  return & f;
}
int p (int x) {
  fun * g = plus (3);
  fun * h = plus (5);
  return g (h (0));
}

In Haskell (www.haskell.org) geht es:
plus :: Int 
  -> ( Int -> Int )
plus x = 
  let f :: Int -> Int
      f y = x + y
  in  f
p :: Int -> Int
p x = 
  let f = plus 3
      g = plus 5
  in  f (g (0))

Funktionen als Werte

D. h. die Frames verhalten sich nicht LIFO und können nicht auf den Stack.

D. h. extra-Speicherverwaltung ist nötig (Garbage Collection).

Aufgabe: warum braucht man das nicht in Pascal?

In Standard-C: keine nested functions, statische Kette ist immer leer.

Aufgabe: suche in gcc-Beschreibung: was passiert, wenn Zeiger auf innere Funktion benutzt wird, wenn dynamische Kette schon weg ist?


next up previous
Nächste Seite: Lokale Klassen in Java Aufwärts: Compilerbau Vorlesung, Wintersemester 2003 Vorherige Seite: Unterprogramme (I) (22. 10.
Johannes Waldmann 2004-01-28