-
Notifications
You must be signed in to change notification settings - Fork 115
/
Copy pathlazy.ss
69 lines (61 loc) · 1.57 KB
/
lazy.ss
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
;;; -*- Gerbil -*-
;;; © vyzo
;;; Lazy evaluation
(export
(rename: delay-lazy lazy)
(rename: delay-eager delay)
(rename: force* force)
lazy? eager)
(defstruct lazy (e)
final: #t)
(defrules delay-lazy ()
((_ expr)
(@lazy lazy (lambda () expr))))
(defrules delay-eager ()
((_ expr)
(delay-lazy (eager expr))))
(defrules @lazy ()
((_ t expr)
(make-lazy (cons 't expr))))
(def (eager expr)
(cond
((lazy? expr)
expr)
((promise? expr)
(@lazy eager expr))
(else
(@lazy resolved expr))))
(def (force* obj)
(let (res (force obj))
(if (lazy? res)
(force-lazy res)
res)))
(def (force-lazy p)
(using (p : lazy)
(declare (not safe))
(let (content p.e)
(case (car content)
((resolved)
(cdr content))
((eager)
(let (val (force* (cdr content)))
(if (eq? (car content) 'eager) ; reentrance test
(begin
(set! (car content) 'resolved)
(set! (cdr content) val)
val)
(cdr content))))
((lazy)
(let ((p* ((cdr content)))
(content p.e))
(when (eq? (car content) 'lazy) ; reentrance test
(if (lazy? p*)
(using (p* :- lazy)
(let (content* p*.e)
(set! (car content) (car content*))
(set! (cdr content) (cdr content*))
(set! p.e content*)))
(begin
(set! (car content) 'eager)
(set! (cdr content) p*))))
(force-lazy p)))))))