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:
twice
.
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?