Skip to content

Commit eecace2

Browse files
committed
Implement SRFI 11 and SRFI 51.
1 parent d2a6157 commit eecace2

File tree

3 files changed

+356
-0
lines changed

3 files changed

+356
-0
lines changed

LispKit.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
CC35FD0F1C711FEA00C8B992 /* BindingGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC35FD0E1C711FEA00C8B992 /* BindingGroup.swift */; };
4747
CC3A025A1F97FD72009B959C /* json.sld in Copy pre-installed LispKit libraries */ = {isa = PBXBuildFile; fileRef = CC3A02591F97F3E1009B959C /* json.sld */; };
4848
CC3C92441D84C0D800016C28 /* Library.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3C92431D84C0D800016C28 /* Library.swift */; };
49+
CC3F782F2157D49000F88F9B /* 51.sld in Copy pre-installed SRFI libraries */ = {isa = PBXBuildFile; fileRef = CC3F782E2157D22B00F88F9B /* 51.sld */; };
50+
CC3F78312157D73700F88F9B /* 11.sld in Copy pre-installed SRFI libraries */ = {isa = PBXBuildFile; fileRef = CC3F78302157D63E00F88F9B /* 11.sld */; };
4951
CC436C401FFBD52F0095559E /* logic.sld in Copy pre-installed LispKit libraries */ = {isa = PBXBuildFile; fileRef = CC436C3F1FFBD5090095559E /* logic.sld */; };
5052
CC436C421FFD96800095559E /* Logic.scm in Resources */ = {isa = PBXBuildFile; fileRef = CC436C411FFD94870095559E /* Logic.scm */; };
5153
CC4385BC20BABAA600055289 /* HTTP.scm in Copy examples */ = {isa = PBXBuildFile; fileRef = CC4385BB20BAB79500055289 /* HTTP.scm */; };
@@ -400,6 +402,8 @@
400402
dstPath = LispKit/Resources/Libraries/srfi;
401403
dstSubfolderSpec = 7;
402404
files = (
405+
CC3F78312157D73700F88F9B /* 11.sld in Copy pre-installed SRFI libraries */,
406+
CC3F782F2157D49000F88F9B /* 51.sld in Copy pre-installed SRFI libraries */,
403407
CC1EA5CB214EF30E006BBE7E /* 161.sld in Copy pre-installed SRFI libraries */,
404408
CC26264020F8014900AC08E8 /* 113.sld in Copy pre-installed SRFI libraries */,
405409
CC26263E20F5707800AC08E8 /* 112.sld in Copy pre-installed SRFI libraries */,
@@ -478,6 +482,8 @@
478482
CC3A02591F97F3E1009B959C /* json.sld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = json.sld; sourceTree = "<group>"; };
479483
CC3C4E051CD81C5E00C78F89 /* TODO.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = TODO.md; sourceTree = "<group>"; };
480484
CC3C92431D84C0D800016C28 /* Library.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Library.swift; sourceTree = "<group>"; wrapsLines = 1; };
485+
CC3F782E2157D22B00F88F9B /* 51.sld */ = {isa = PBXFileReference; lastKnownFileType = text; path = 51.sld; sourceTree = "<group>"; };
486+
CC3F78302157D63E00F88F9B /* 11.sld */ = {isa = PBXFileReference; lastKnownFileType = text; path = 11.sld; sourceTree = "<group>"; };
481487
CC436C3F1FFBD5090095559E /* logic.sld */ = {isa = PBXFileReference; lastKnownFileType = text; path = logic.sld; sourceTree = "<group>"; };
482488
CC436C411FFD94870095559E /* Logic.scm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Logic.scm; sourceTree = "<group>"; };
483489
CC4385BB20BAB79500055289 /* HTTP.scm */ = {isa = PBXFileReference; lastKnownFileType = text; path = HTTP.scm; sourceTree = "<group>"; };
@@ -806,6 +812,7 @@
806812
CC5848051E56BD0B00BE6497 /* 1.sld */,
807813
CC5848061E56BD0B00BE6497 /* 2.sld */,
808814
CC5848071E56BD0B00BE6497 /* 8.sld */,
815+
CC3F78302157D63E00F88F9B /* 11.sld */,
809816
CC8A2AAE1F405CDD00D1E4D8 /* 17.sld */,
810817
CC5848081E56BD0B00BE6497 /* 19.sld */,
811818
CC5848091E56BD0B00BE6497 /* 27.sld */,
@@ -815,6 +822,7 @@
815822
CC48EBCD1F3E5AC700233FA9 /* 41 */,
816823
CC58480B1E56BD1800BE6497 /* 41.sld */,
817824
CC8A2AB01F40672700D1E4D8 /* 48.sld */,
825+
CC3F782E2157D22B00F88F9B /* 51.sld */,
818826
CC79DE031F883FED00CE7A5D /* 63.sld */,
819827
CCC072451F9AA8B70063974E /* 64.sld */,
820828
CC5E473C20D2D8B600F21B03 /* 69.sld */,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
;;; SRFI 11
2+
;;; Syntax for receiving multiple values
3+
;;;
4+
;;; The SRFI introduces syntactic forms `let-values` and `let*-values` that bind the values
5+
;;; of expressions that return multiple values.
6+
;;;
7+
;;; Author of spec: Lars T Hansen
8+
;;;
9+
;;; Copyright © 2018 Matthias Zenger. All rights reserved.
10+
;;;
11+
;;; Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
12+
;;; except in compliance with the License. You may obtain a copy of the License at
13+
;;;
14+
;;; http://www.apache.org/licenses/LICENSE-2.0
15+
;;;
16+
;;; Unless required by applicable law or agreed to in writing, software distributed under the
17+
;;; License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
18+
;;; either express or implied. See the License for the specific language governing permissions
19+
;;; and limitations under the License.
20+
21+
(define-library (srfi 11)
22+
23+
(export let-values
24+
let*-values)
25+
26+
(import (lispkit control))
27+
28+
;; Both forms are implemented natively in library `(lispkit control)`
29+
)
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
;;; SRFI 51
2+
;;; Handling rest list
3+
;;;
4+
;;; This SRFI introduces the rest-values procedure which has three modes of operation:
5+
;;; 1. it processes a rest list after checking its elements with default values
6+
;;; or predicate procedures,
7+
;;; 2. it processes a rest list with default values without checking its elements,
8+
;;; 3. it processes a default list whose elements are lists or pairs, after checking
9+
;;; their elements that are default values or predicate procedures with the elements
10+
;;; of a rest list,
11+
;;; and eight macros which additionally check the rest arguments that are returned by
12+
;;; `rest-values`.
13+
;;; When defining a procedure with a variable number of arguments, `rest-values` with or without
14+
;;; the checking macros reduces the clutter of various conditionals and error conditions.
15+
;;; The procedure and macros proposed in this SRFI make a strong combination with `receive`
16+
;;; (SRFI 8) and `let-values` (SRFI 11).
17+
;;;
18+
;;; Copyright © 2004 Joo ChurlSoo. All rights reserved.
19+
;;; Made an R7RS library by Taylan Ulrich Bayırlı/Kammer, Copyright © 2014.
20+
;;;
21+
;;; Permission is hereby granted, free of charge, to any person obtaining a copy
22+
;;; of this software and associated documentation files (the "Software"), to
23+
;;; deal in the Software without restriction, including without limitation the
24+
;;; rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
25+
;;; sell copies of the Software, and to permit persons to whom the Software is
26+
;;; furnished to do so, subject to the following conditions:
27+
;;;
28+
;;; The above copyright notice and this permission notice shall be included in
29+
;;; all copies or substantial portions of the Software.
30+
;;;
31+
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32+
;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33+
;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34+
;;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35+
;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
36+
;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
37+
;;; IN THE SOFTWARE.
38+
;;;
39+
;;; Adaptation to LispKit
40+
;;; Copyright © 2018 Matthias Zenger. All rights reserved.
41+
42+
(define-library (srfi 51)
43+
44+
(export rest-values
45+
arg-and
46+
arg-ands
47+
err-and
48+
err-ands
49+
arg-or
50+
arg-ors
51+
err-or
52+
err-ors)
53+
54+
(import (lispkit base)
55+
(srfi 1))
56+
57+
(begin
58+
(define (rest-values rest . default)
59+
(let* ((caller (if (or (null? default)
60+
(boolean? (car default))
61+
(integer? (car default))
62+
(memq (car default) (list + -)))
63+
'()
64+
(if (string? rest) rest (list rest))))
65+
(rest-list (if (null? caller) rest (car default)))
66+
(rest-length (if (list? rest-list)
67+
(length rest-list)
68+
(if (string? caller)
69+
(error caller rest-list 'rest-list
70+
'(list? rest-list))
71+
(apply error "bad rest list" rest-list 'rest-list
72+
'(list? rest-list) caller))))
73+
(default (if (null? caller) default (cdr default)))
74+
(default-list (if (null? default) default (cdr default)))
75+
(default-length (length default-list))
76+
(number
77+
(and (not (null? default))
78+
(let ((option (car default)))
79+
(or (and (integer? option)
80+
(or (and (> rest-length (abs option))
81+
(if (string? caller)
82+
(error caller rest-list 'rest-list
83+
`(<= (length rest-list)
84+
,(abs option)))
85+
(apply error "too many arguments"
86+
rest-list 'rest-list
87+
`(<= (length rest-list)
88+
,(abs option))
89+
caller)))
90+
(and (> default-length (abs option))
91+
(if (string? caller)
92+
(error caller default-list
93+
'default-list
94+
`(<= (length default-list)
95+
,(abs option)))
96+
(apply error "too many defaults"
97+
default-list 'default-list
98+
`(<= (length default-list)
99+
,(abs option))
100+
caller)))
101+
option))
102+
(eq? option #t)
103+
(and (not option) 'false)
104+
(and (eq? option +) +)
105+
(and (eq? option -) -)
106+
(if (string? caller)
107+
(error caller option 'option
108+
'(or (boolean? option)
109+
(integer? option)
110+
(memq option (list + -))))
111+
(apply error "bad optional argument" option 'option
112+
'(or (boolean? option)
113+
(integer? option)
114+
(memq option (list + -)))
115+
caller)))))))
116+
(cond
117+
((or (eq? #t number) (eq? 'false number))
118+
(and (not (every pair? default-list))
119+
(if (string? caller)
120+
(error caller default-list 'default-list
121+
'(every pair? default-list))
122+
(apply error "bad default list" default-list 'default-list
123+
'(every pair? default-list) caller)))
124+
(let loop ((rest-list rest-list)
125+
(default-list default-list)
126+
(result '()))
127+
(if (null? default-list)
128+
(if (null? rest-list)
129+
(apply values (reverse result))
130+
(if (eq? #t number)
131+
(if (string? caller)
132+
(error caller rest-list 'rest-list '(null? rest-list))
133+
(apply error "bad argument" rest-list 'rest-list
134+
'(null? rest-list) caller))
135+
(apply values (append-reverse result rest-list))))
136+
(if (null? rest-list)
137+
(apply values (append-reverse result (map car default-list)))
138+
(let ((default (car default-list)))
139+
(let lp ((rest rest-list)
140+
(head '()))
141+
(if (null? rest)
142+
(loop (reverse head)
143+
(cdr default-list)
144+
(cons (car default) result))
145+
(if (list? default)
146+
(if (member (car rest) default)
147+
(loop (append-reverse head (cdr rest))
148+
(cdr default-list)
149+
(cons (car rest) result))
150+
(lp (cdr rest) (cons (car rest) head)))
151+
(if ((cdr default) (car rest))
152+
(loop (append-reverse head (cdr rest))
153+
(cdr default-list)
154+
(cons (car rest) result))
155+
(lp (cdr rest) (cons (car rest) head)))))))))))
156+
((or (and (integer? number) (> number 0))
157+
(eq? number +))
158+
(and (not (every pair? default-list))
159+
(if (string? caller)
160+
(error caller default-list 'default-list
161+
'(every pair? default-list))
162+
(apply error "bad default list" default-list 'default-list
163+
'(every pair? default-list) caller)))
164+
(let loop ((rest rest-list)
165+
(default default-list))
166+
(if (or (null? rest) (null? default))
167+
(apply values
168+
(if (> default-length rest-length)
169+
(append rest-list
170+
(map car (list-tail default-list rest-length)))
171+
rest-list))
172+
(let ((arg (car rest))
173+
(par (car default)))
174+
(if (list? par)
175+
(if (member arg par)
176+
(loop (cdr rest) (cdr default))
177+
(if (string? caller)
178+
(error caller arg 'arg `(member arg ,par))
179+
(apply error "unmatched argument"
180+
arg 'arg `(member arg ,par) caller)))
181+
(if ((cdr par) arg)
182+
(loop (cdr rest) (cdr default))
183+
(if (string? caller)
184+
(error caller arg 'arg `(,(cdr par) arg))
185+
(apply error "incorrect argument"
186+
arg 'arg `(,(cdr par) arg) caller))))))))
187+
(else
188+
(apply values (if (> default-length rest-length)
189+
(append rest-list (list-tail default-list rest-length))
190+
rest-list))))))
191+
192+
(define-syntax arg-and
193+
(syntax-rules()
194+
((arg-and arg (a1 a2 ...) ...)
195+
(and (or (symbol? 'arg)
196+
(error "bad syntax" 'arg '(symbol? 'arg)
197+
'(arg-and arg (a1 a2 ...) ...)))
198+
(or (a1 a2 ...)
199+
(error "incorrect argument" arg 'arg '(a1 a2 ...)))
200+
...))
201+
((arg-and caller arg (a1 a2 ...) ...)
202+
(and (or (symbol? 'arg)
203+
(error "bad syntax" 'arg '(symbol? 'arg)
204+
'(arg-and caller arg (a1 a2 ...) ...)))
205+
(or (a1 a2 ...)
206+
(if (string? caller)
207+
(error caller arg 'arg '(a1 a2 ...))
208+
(error "incorrect argument" arg 'arg '(a1 a2 ...) caller)))
209+
...))))
210+
211+
;; accessory macro for arg-ands
212+
(define-syntax caller-arg-and
213+
(syntax-rules()
214+
((caller-arg-and caller arg (a1 a2 ...) ...)
215+
(and (or (symbol? 'arg)
216+
(error "bad syntax" 'arg '(symbol? 'arg)
217+
'(caller-arg-and caller arg (a1 a2 ...) ...)))
218+
(or (a1 a2 ...)
219+
(if (string? caller)
220+
(error caller arg 'arg '(a1 a2 ...))
221+
(error "incorrect argument" arg 'arg '(a1 a2 ...) caller)))
222+
...))
223+
((caller-arg-and null caller arg (a1 a2 ...) ...)
224+
(and (or (symbol? 'arg)
225+
(error "bad syntax" 'arg '(symbol? 'arg)
226+
'(caller-arg-and caller arg (a1 a2 ...) ...)))
227+
(or (a1 a2 ...)
228+
(if (string? caller)
229+
(error caller arg 'arg '(a1 a2 ...))
230+
(error "incorrect argument" arg 'arg '(a1 a2 ...) caller)))
231+
...))))
232+
233+
(define-syntax arg-ands
234+
(syntax-rules (common)
235+
((arg-ands (a1 a2 ...) ...)
236+
(and (arg-and a1 a2 ...) ...))
237+
((arg-ands common caller (a1 a2 ...) ...)
238+
(and (caller-arg-and caller a1 a2 ...) ...))))
239+
240+
(define-syntax arg-or
241+
(syntax-rules()
242+
((arg-or arg (a1 a2 ...) ...)
243+
(or (and (not (symbol? 'arg))
244+
(error "bad syntax" 'arg '(symbol? 'arg)
245+
'(arg-or arg (a1 a2 ...) ...)))
246+
(and (a1 a2 ...)
247+
(error "incorrect argument" arg 'arg '(a1 a2 ...)))
248+
...))
249+
((arg-or caller arg (a1 a2 ...) ...)
250+
(or (and (not (symbol? 'arg))
251+
(error "bad syntax" 'arg '(symbol? 'arg)
252+
'(arg-or caller arg (a1 a2 ...) ...)))
253+
(and (a1 a2 ...)
254+
(if (string? caller)
255+
(error caller arg 'arg '(a1 a2 ...))
256+
(error "incorrect argument" arg 'arg '(a1 a2 ...) caller)))
257+
...))))
258+
259+
;; accessory macro for arg-ors
260+
(define-syntax caller-arg-or
261+
(syntax-rules()
262+
((caller-arg-or caller arg (a1 a2 ...) ...)
263+
(or (and (not (symbol? 'arg))
264+
(error "bad syntax" 'arg '(symbol? 'arg)
265+
'(caller-arg-or caller arg (a1 a2 ...) ...)))
266+
(and (a1 a2 ...)
267+
(if (string? caller)
268+
(error caller arg 'arg '(a1 a2 ...))
269+
(error "incorrect argument" arg 'arg '(a1 a2 ...) caller)))
270+
...))
271+
((caller-arg-or null caller arg (a1 a2 ...) ...)
272+
(or (and (not (symbol? 'arg))
273+
(error "bad syntax" 'arg '(symbol? 'arg)
274+
'(caller-arg-or caller arg (a1 a2 ...) ...)))
275+
(and (a1 a2 ...)
276+
(if (string? caller)
277+
(error caller arg 'arg '(a1 a2 ...))
278+
(error "incorrect argument" arg 'arg '(a1 a2 ...) caller)))
279+
...))))
280+
281+
(define-syntax arg-ors
282+
(syntax-rules (common)
283+
((arg-ors (a1 a2 ...) ...)
284+
(or (arg-or a1 a2 ...) ...))
285+
((arg-ors common caller (a1 a2 ...) ...)
286+
(or (caller-arg-or caller a1 a2 ...) ...))))
287+
288+
(define-syntax err-and
289+
(syntax-rules ()
290+
((err-and err expression ...)
291+
(and (or expression
292+
(if (string? err)
293+
(error err 'expression)
294+
(error "false expression" 'expression err)))
295+
...))))
296+
297+
(define-syntax err-ands
298+
(syntax-rules ()
299+
((err-ands (err expression ...) ...)
300+
(and (err-and err expression ...)
301+
...))))
302+
303+
(define-syntax err-or
304+
(syntax-rules ()
305+
((err-or err expression ...)
306+
(or (and expression
307+
(if (string? err)
308+
(error err 'expression)
309+
(error "true expression" 'expression err)))
310+
...))))
311+
312+
(define-syntax err-ors
313+
(syntax-rules ()
314+
((err-ors (err expression ...) ...)
315+
(or (err-or err expression ...)
316+
...))))
317+
)
318+
)
319+

0 commit comments

Comments
 (0)