aboutsummaryrefslogtreecommitdiffstats
path: root/csc/loop.csc
blob: c7331fe93f330993869858a217777f8e9cb46cdb (plain) (blame)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
(define-library (csc loop)
  (export loop return)
  (import (scheme base))
  (begin


    (define-syntax initial-values
      (syntax-rules (=
                     by
                     collect
                     do
                     for
                     from
                     in
                     into
                     then
                     to)
        ((initial-values loop-name (acc* ...) ((for _ in l temp-name) clause clause* ...) body)
          (initial-values loop-name (acc* ... (temp-name l)) (clause clause* ...) body))
        ((initial-values loop-name (acc* ...) ((for x from start to _ by _) clause clause* ...) body)
          (initial-values loop-name (acc* ... (x start)) (clause clause* ...) body))
        ((initial-values loop-name (acc* ...) ((for x = init then consequent) clause clause* ...) body)
          (initial-values loop-name (acc* ... (x init)) (clause clause* ...) body))
        ((initial-values loop-name (acc* ...) ((collect _ into l last) clause clause* ...) body)
          (initial-values loop-name (acc* ... (l '()) (last #f)) (clause clause* ...) body))
        ((initial-values loop-name (acc* ...) ((collect _ l last)) body)
          (let loop-name (acc* ... (l '()) (last #f))
            body))
        ((initial-values loop-name (acc* ...) ((do _)) body)
          (let loop-name (acc* ...)
            body))))


    (define-syntax subsequent-values
      (syntax-rules (=
                     by
                     collect
                     do
                     for
                     from
                     in
                     into
                     then
                     to)
        ((subsequent-values loop-name (acc* ...) (for _ in _ l) clause clause* ...)
          (subsequent-values loop-name (acc* ... (cdr l)) clause clause* ...))
        ((subsequent-values loop-name (acc* ...) (for x from _ to _ by inc) clause clause* ...)
          (subsequent-values loop-name (acc* ... (+ x inc)) clause clause* ...))
        ((subsequent-values loop-name (acc* ...) (for x = _ then consequent) clause clause* ...)
          (subsequent-values loop-name (acc* ... consequent) clause clause* ...))
        ((subsequent-values loop-name (acc* ...) (collect expr into l last) clause clause* ...)
          (if last
            (begin
              (set-cdr! last (list expr))
              (subsequent-values loop-name (acc* ... l (cdr last)) clause clause* ...))
            (begin
              (set! l (list expr))
              (subsequent-values loop-name (acc* ... l l) clause clause* ...))))
        ((subsequent-values loop-name (acc* ...) (collect expr l last))
          (if last
            (begin
              (set-cdr! last (list expr))
              (loop-name acc* ... l (cdr last)))
            (begin
              (set! l (list expr))
              (loop-name acc* ... l l))))
        ((subsequent-values loop-name (acc* ...) (do expr))
          (begin
            expr
            (loop-name acc* ...)))))


    (define-syntax condition
      (syntax-rules (=
                     by
                     collect
                     for
                     from
                     in
                     into
                     then
                     to)
        ((condition)
          #t)
        ((condition (for _ in _ l) clause* ...)
          (and (pair? l) (condition clause* ...)))
        ((condition (for x from _ to limit by _) clause* ...)
          (and (<= x limit) (condition clause* ...)))
        ((condition (for _ = _ then _) clause* ...)
          (condition clause* ...))
        ((condition (collect _ into _ _) clause* ...)
          (condition clause* ...))))


    (define-syntax result
      (syntax-rules (collect)
        ((result (collect _ l _))
          l)
        ((result (do _))
          (if #f #f))))


    (define-syntax bindings
      (syntax-rules (=
                     by
                     collect
                     for
                     from
                     in
                     into
                     then
                     to)
        ((bindings () body)
          body)
        ((bindings ((for x in _ l) clause* ...) body)
          (let ((x (car l)))
            (bindings (clause* ...)
              body)))
        ((bindings ((for _ from _ to _ by _) clause* ...) body)
          (bindings (clause* ...) body))
        ((bindings ((for _ = _ then _) clause* ...) body)
          (bindings (clause* ...) body))
        ((bindings ((collect _ into _ _) clause* ...) body)
          (bindings (clause* ...) body))))


    (define (*current-loop-continuation* . args)
      (error "Can't use return outside of a loop"))


    (define-syntax loop-clauses
      (syntax-rules ()
        ((loop-clauses (clause* ...) fin body)
          (call/cc
            (lambda (k)
              (define prev-loop-continuation *current-loop-continuation*)
              (dynamic-wind
                (lambda ()
                  (set! *current-loop-continuation* k))
                (lambda ()
                  (initial-values loop-name () (clause* ... body)
                    (if (condition clause* ...)
                      (bindings (clause* ...)
                        (subsequent-values loop-name () clause* ... body))
                      (begin
                        fin
                        (result body)))))
                (lambda ()
                  (set! *current-loop-continuation* prev-loop-continuation))))))))


    (define-syntax clause-collector
      (syntax-rules (=
                     by
                     collect
                     do
                     finally
                     for
                     from
                     in
                     into
                     then
                     to)
        ((clause-collector (acc ...) fin for x in l clause clause* ...)
          (clause-collector (acc ... (for x in l temp-name)) fin clause clause* ...))
        ((clause-collector (acc ...) fin for x from start to limit by step clause clause* ...)
          (clause-collector (acc ... (for x from start to limit by step)) fin clause clause* ...))
        ((clause-collector (acc ...) fin for x from start to limit clause clause* ...)
          (clause-collector (acc ... (for x from start to limit by 1)) fin clause clause* ...))
        ((clause-collector (acc ...) fin for x = init then subsequent clause clause* ...)
          (clause-collector (acc ... (for x = init then subsequent)) fin clause clause* ...))
        ((clause-collector (acc ...) fin collect x into l clause clause* ...)
          (clause-collector (acc ... (collect x into l temp-name)) fin clause clause* ...))
        ((clause-collector (acc ...) #f finally expr)
          (loop-clauses (acc ...) expr (do (if #f #f))))
        ((clause-collector (acc ...) #f finally expr clause clause* ...)
          (clause-collector (acc ...) expr clause clause* ...))
        ((clause-collector (acc ...) fin collect expr)
          (loop-clauses (acc ...) fin (collect expr temp1 temp2)))
        ((clause-collector (acc ...) fin do body body* ...)
          (loop-clauses (acc ...) fin (do (let () body body* ...))))))


    ; loop is a general purpose looping construct cribbed from CL.
    (define-syntax loop
      (syntax-rules ()
        ((loop clause clause* ...)
          (clause-collector () #f clause clause* ...))))


    (define-syntax return
      (syntax-rules ()
        ((return expr)
          (call-with-values (lambda () expr) *current-loop-continuation*))))))