summaryrefslogtreecommitdiff
path: root/modules/language/python/try.scm
blob: 50ca23fc8617e9899f92abc0b33b123aa9d3365a (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(define-module (language python try)
  #:use-module (language python exceptions)
  #:use-module (language python yield)
  #:use-module (oop pf-objects)
  #:use-module (oop goops)
  #:use-module (ice-9 control)
  #:use-module (ice-9 match)
  #:replace (raise)
  #:export (try))

(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))

(define-inlinable (standard-check class obj l)
  (cond
   ((eq? class #t)
    #t)
   ((struct? obj)
    (if (is-a? obj <p>)
	(if (is-a? class <p>)
	    (is-a? obj (ref class '__goops__))
	    (is-a? obj class))
	(if (is-a? obj <object>)
	    (is-a? obj class)
	    (eq? obj class))))
    ((and (procedure? class) (not (pyclass? class)))
     (apply class obj l))
    (else
     (eq? class obj))))
          
      
(define (check class obj l)
  (standard-check class obj l))

(define-syntax compile-error
  (lambda (x)
    (syntax-case x ()
      ((_ x)
       (error (syntax->datum #'x))))))

(define-syntax check-exception
  (syntax-rules (and or not)
    ((_ (or E ...) tag l)
     (or (check-exception E tag l) ...))
    ((_ (and E ...) tag l)
     (and (check-exception E tag l) ...))
    ((_ (not E) tag l)
     (not (check-exception E tag l)))
    ((_ E tag l)
     (check E tag l))))

(define (m code)
  (let ((c code))
    (lambda (k . l)
      (if (eq? k StopIteration)
	  (apply c 'python k l)
	  (apply c k l)))))

(define-syntax handler
  (lambda (x)
    (syntax-case x ()
      ((_ . l) #'(handler_ . l)))))

(define-syntax handler_
  (syntax-rules (=>)
    ((handler ecx)
     (m 
      (lambda (k tag . l)
	(handler ecx tag l))))
    
    ((handler ((#:except E => lam) . ecx) tag l)
     (if (check-exception E tag l)
         (lam tag l)
         (handler ecx tag l)))

    ((handler ((#:except E) . ecx) tag l)
     (if (check-exception E tag l)
         (begin (values))
         (handler ecx tag l)))

    ((handler ((#:except E code ...) . ecx) tag l)
     (if (check-exception E tag l)
         (begin code ...)
         (handler ecx tag l)))

    ((handler ((#:else code ...)) tag l)
     (begin code ...))

    ((handler () tag l)
     (apply throw 'python tag l))

    ((a ...)
     (compile-error "not a proper python macro try block"))))

    
    
(define-syntax try
  (syntax-rules ()
    ((try  code exc ... #:finally fin)
     (dynamic-wind
       (lambda () #f)
       (lambda ()
         (catch #t
           code
           (handler (exc ...))))
       (lambda ()
         (if (not (fluid-ref in-yield))
             (fin)))))

    ((try  code exc ...)
     (catch #t
       code
       (handler (exc ...))))))
  

(define raise
  (case-lambda
    ((x . l)
     (if (pyclass? x)
         (throw 'python (apply x l))
         (apply throw 'python x l)))

    (() (raise Exception))))