michał “phoe” herda

Post on 27-Jan-2022

5 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Michał “phoe” Herda

phoe@disroot.orghttps://phoe.github.io

1

2

• We need means of unwinding and protecting against unwinds

3

• We need means of unwinding and protecting against unwinds

4

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

5

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

6

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

7

• This includes non-local jumps(a secret Common Lisp feature)

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

8

• This includes non-local jumps(a secret Common Lisp feature)

• This includes loops• This includes switches• This includes error handling• This includes restart handling

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

9

• This includes non-local jumps(a secret Common Lisp feature)

• This includes loops• This includes switches• This includes error handling• This includes restart handling• The above four groups

are implemented in Common Lisp itself

10

• Software engineer at Ericsson (C/C++/Erlang)

11

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)

12

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)• Author of The Common Lisp Condition System (Apress, 2020)

13

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)• Author of The Common Lisp Condition System (Apress, 2020)

• Somewhat capable of writing other programming languages

14

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)• Author of The Common Lisp Condition System (Apress, 2020)

• Somewhat capable of writing other programming languages

• I kinda like the topic of control flow

15

• I kinda like the topic of control flow

16

• I kinda like the topic of control flow

17

18

19

20

21

22

23

24

foo()

bar()

baz()

25

foo()

bar()

baz()

1/0

26

foo()

bar()

baz()

1/0

ArithmeticException

27

foo()

bar()

baz()

1/0

ArithmeticException

28

foo()

bar()

baz()

1/0

ArithmeticException

29

foo()

bar()

baz()

1/0

ArithmeticException

30

foo()

bar()

baz()

1/0

catch

ArithmeticException

31

foo()

bar()

baz()

1/0

catch

32

foo()

bar()

33

foo()

bar()

... // execution continues

34

35

36

37

38

(foo)

(bar)

(baz)

39

(foo)

(bar)

(baz)

(/ 1 0)

40

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

41

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

42

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

43

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

44

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

45

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

46

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

47

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

handler-1

48

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

handler-2

49

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

handler-3

50

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

51

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

52

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

53

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

54

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

55

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

56

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

57

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

non-local jump

58

(foo)

59

(foo)

... // execution continues

60

(foo)

... // execution continues

61

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

62

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

restart-1restart-2

restart-4

restart-3

63

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

“Return 42 instead.”“Query the user for new numbers.”

“Abort and return to toplevel.”

“Try opening another file.”

64

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

“Return 42 instead.”“Query the user for new numbers.”

“Abort and return to toplevel.”

“Try opening another file.”

?

?

??

?

65

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

(invoke-debugger ...)

“Return 42 instead.”“Query the user for new numbers.”

“Abort and return to toplevel.”

“Try opening another file.”

division-by-zero

66

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

67

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

68

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

“Try opening another file.”

69

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

“Try opening another file.”

restart-fn

70

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

“Try opening another file.”

restart-fn

non-localjump

71

(foo)

(bar)

72

(foo)

(bar)

... // execution continues

73

74

(foo)

(bar)

(baz)

(quux)

75

(foo)

(bar)

(baz)

(quux)some-condition

76

(foo)

(bar)

(baz)

(quux)some-condition

(signal ...)

77

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

78

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

handler-1

79

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

handler-2

80

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

handler-3

81

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

82

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

¯\_(ツ)_/¯

83

(foo)

(bar)

(baz)

(quux)

84

(foo)

(bar)

(baz)

(quux)

... // execution continues

85

• Construct the exception object

86

• Construct the exception object• Unwind the stack immediately

• Stop unwinding when something catches the exception

87

• Construct the exception object• Unwind the stack immediately

• Stop unwinding when something catches the exception• Continue execution from that point

88

89

• Construct the condition object

90

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?

91

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?

92

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code

93

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart

94

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return

95

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point

96

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers

97

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it

98

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

99

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

100

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

101

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

102

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

103

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

104

105

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

106

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

107

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

108

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

109

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

110

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

111

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

112

• if

(if (foo) (bar) (baz))

113

• if• tagbody/go

(tagbody 10 (print “hello”) 20 (go 10))

114

(block my-block (...) (... (return-from my-block 42)) (...))

115

• if• tagbody/go• block/return-from

(catch ‘quux (...) (... (foo)) (...)))

(defun foo () (throw ‘quux 42))

116

• if• tagbody/go• block/return-from• catch/throw

• if• tagbody/go• block/return-from• catch/throw• unwind-protect

(let ((thing (make-thing))) (unwind-protect (frob thing) (cleanup thing)))

117

(let ((fn (lambda ...)) (args ...)) (apply fn 1 2 3 args))

118

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(let ((fn (lambda ...)) (args ...)) (apply fn 1 2 3 args))

(let ((fn (lambda ...))) (funcall fn 1 2 3))

119

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply ; and funcall

120

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

121

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

122

(let ((x 42)) (lambda () x))

123

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

124

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>)

125

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>);; => 42

126

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>);; => 42

;; but we can close over more;; than just lexical variables!

127

128

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>);; => 42

;; but we can close over more;; than just lexical variables!

129

(defun foo (x) (funcall x))

130

(defun foo (x) (funcall x))

(defun bar () ; block bar ...)

131

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) ...))

132

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

133

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)

134

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

135

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

136

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

(lambda () ...)

137

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

(lambda () ...)

138

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

(lambda () ...)

139

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar);; => 42

140

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar);; => 42

141

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

142

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

143

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

144

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

145

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

1

!

146

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

147

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)1

?

?

?

148

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)1

?

?

?

149

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)1

2?

?

?

!

150

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

151

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

152

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

153

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

154

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives

155

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)

156

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)

157

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)

158

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

159

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

• This list includes use cases that are not related to exception handling

160

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

• This list includes use cases that are not related to exception handling

161

• Control flow ≠ exception handling

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

• This list includes use cases that are not related to exception handling

162

• Control flow ≠ exception handling

163

• Control flow ≠ exception handling

• Do not conflate unwinding with throwing exceptions

164

• Control flow ≠ exception handling

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow

165

• Control flow ≠ exception handling

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow• Throwing exceptions is not synonymous with unwinding

166

• Control flow ≠ exception handling

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow• Throwing exceptions is not synonymous with unwinding• Throwing exceptions is not a primitive operation

167

• Control flow ≠ exception handling

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow• Throwing exceptions is not synonymous with unwinding• Throwing exceptions is not a primitive operation

• Proofs: Common Lisp, Dylan, Smalltalk

168

• Control flow ≠ exception handling

169

but wait hold on for just one moment

170

Appendix A

Proving one-phase unwind in TAGBODY and BLOCK

171

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

172

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

173

174

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

(block foo (lambda () (return-from foo)))

175

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

(let ((fn (block foo (lambda () (return-from foo))))) (funcall fn)); ...?

176

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

(let ((fn (block foo (lambda () (return-from foo))))) (funcall fn)); ERROR: Condition CONTROL-ERROR; was signaled.

177

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply (let ((fn (block foo

(lambda () (return-from foo))))) (funcall fn)); ERROR: Condition CONTROL-ERROR; was signaled.

178

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply (let ((fn (block foo

(lambda () (return-from foo))))) (funcall fn)); ERROR: Condition CONTROL-ERROR; was signaled.

179

? ?

(block foo (lambda () (return-from foo)))

180

(block foo ...)

181

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo ...) (setf return-valid-p nil)))

182

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo ...) ;; let’s expand the lambda! (setf return-valid-p nil)))

183

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

184

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

185

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

186

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

;; similar validation scheme applies for TAGBODY/GO

187

Appendix B

Describing UNWIND-PROTECT

188

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

189

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

190

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

191

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

192

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

193

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

194

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

195

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

196

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

197

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

198

Appendix C

Common Lisp condition system without Common Lisp

(this is the last one I promise)199

200

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

201

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

202

203

204

205• Can we port the condition system to Java?

206• Can we port CL control flow to Java?

207• Can we port CL control flow to Java?

208

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

209

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

210

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

“I suppose it is tempting, if the only tool you have is a hammer,to treat everything as if it were a nail.”

--- Abraham H. Maslow

211

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

https://github.com/phoe/cafe-latte

212

yes, it’s seriously the end this time

213

top related