heist 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +17 -0
- data/Manifest.txt +5 -0
- data/README.txt +65 -51
- data/Rakefile +25 -1
- data/lib/builtin/library.scm +244 -9
- data/lib/builtin/primitives.rb +122 -10
- data/lib/builtin/syntax.scm +10 -14
- data/lib/heist.rb +5 -13
- data/lib/parser/nodes.rb +25 -5
- data/lib/parser/scheme.rb +394 -142
- data/lib/parser/scheme.tt +18 -6
- data/lib/repl.rb +19 -13
- data/lib/runtime/binding.rb +1 -0
- data/lib/runtime/callable/continuation.rb +1 -0
- data/lib/runtime/callable/macro.rb +37 -2
- data/lib/runtime/callable/macro/expansion.rb +34 -2
- data/lib/runtime/callable/syntax.rb +1 -0
- data/lib/runtime/data/character.rb +83 -0
- data/lib/runtime/data/cons.rb +17 -19
- data/lib/runtime/data/vector.rb +65 -0
- data/lib/runtime/frame.rb +7 -0
- data/lib/runtime/runtime.rb +2 -1
- data/lib/runtime/scope.rb +5 -9
- data/lib/runtime/stackless.rb +7 -0
- data/lib/trie.rb +141 -0
- data/test/equivalence.scm +7 -0
- data/test/let.scm +13 -0
- data/test/lists.scm +2 -3
- data/test/macros.scm +14 -0
- data/test/strings.scm +110 -0
- data/test/test_heist.rb +2 -0
- data/test/vectors.scm +83 -0
- metadata +10 -7
data/History.txt
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
=== Version 0.3.0 (2009-07-31)
|
2
|
+
|
3
|
+
We've got all your data types now
|
4
|
+
* Vectors are supported, including the full R5RS library, macro and quasiquoting support
|
5
|
+
* Characters are available, including named characters (#\newline, #\space, #\tab)
|
6
|
+
* The full R5RS character and string libraries are implemented
|
7
|
+
* Complex numbers work correctly on Ruby1.9
|
8
|
+
* Dotted tail notation properly supported in macro templates
|
9
|
+
|
10
|
+
|
11
|
+
=== Version 0.2.1 (2009-05-19)
|
12
|
+
|
13
|
+
* Fixed a bug in (append) where '() is the last argument
|
14
|
+
* Implemented (begin) in Ruby rather than Scheme for performance reasons
|
15
|
+
* Fixed a macro bug relating to binding of macro keywords
|
16
|
+
|
17
|
+
|
1
18
|
=== Version 0.2.0 (2009-04-01)
|
2
19
|
|
3
20
|
The 'lists' release
|
data/Manifest.txt
CHANGED
@@ -6,6 +6,7 @@ bin/heist
|
|
6
6
|
lib/bin_spec.rb
|
7
7
|
lib/heist.rb
|
8
8
|
lib/repl.rb
|
9
|
+
lib/trie.rb
|
9
10
|
lib/builtin/library.scm
|
10
11
|
lib/builtin/primitives.rb
|
11
12
|
lib/builtin/syntax.scm
|
@@ -20,9 +21,11 @@ lib/runtime/callable/macro.rb
|
|
20
21
|
lib/runtime/callable/macro/matches.rb
|
21
22
|
lib/runtime/callable/macro/tree.rb
|
22
23
|
lib/runtime/callable/macro/expansion.rb
|
24
|
+
lib/runtime/data/character.rb
|
23
25
|
lib/runtime/data/cons.rb
|
24
26
|
lib/runtime/data/expression.rb
|
25
27
|
lib/runtime/data/identifier.rb
|
28
|
+
lib/runtime/data/vector.rb
|
26
29
|
lib/runtime/binding.rb
|
27
30
|
lib/runtime/frame.rb
|
28
31
|
lib/runtime/runtime.rb
|
@@ -51,7 +54,9 @@ test/macro-helpers.scm
|
|
51
54
|
test/macros.scm
|
52
55
|
test/numbers.scm
|
53
56
|
test/plt-macros.txt
|
57
|
+
test/strings.scm
|
54
58
|
test/test_heist.rb
|
55
59
|
test/unhygienic.scm
|
56
60
|
test/vars.scm
|
61
|
+
test/vectors.scm
|
57
62
|
|
data/README.txt
CHANGED
@@ -46,52 +46,63 @@ Currently implemented R5RS features include:
|
|
46
46
|
* Numeric literals for integers, reals, rationals and complexes. The
|
47
47
|
latter two are mapped to Ruby's <tt>Rational</tt> and <tt>Complex</tt>
|
48
48
|
objects and Ruby handles all math procedures.
|
49
|
-
*
|
49
|
+
* Character, string and symbol literals
|
50
50
|
* Proper and improper lists and full (quasi)quoting with <tt>'</tt>,
|
51
51
|
<tt>`</tt>, <tt>,</tt>, <tt>,@</tt>
|
52
|
-
*
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
*
|
58
|
-
as <tt>call/cc</tt>
|
59
|
-
* Proper tail recursion
|
60
|
-
* Variable assignment: <tt>define</tt> and <tt>set!</tt>
|
61
|
-
* Lambda expressions: <tt>(lambda (x ...) body ...)</tt>, including lexical
|
62
|
-
scoping and closures. Supports varargs using <tt>(lambda args body ...)</tt>
|
63
|
-
and <tt>(lambda (x y . rest) body ...)</tt> forms.
|
64
|
-
* Control flow: <tt>begin</tt>, <tt>if</tt>, <tt>cond</tt>,
|
65
|
-
<tt>case</tt>
|
66
|
-
* Binding constructs: <tt>let</tt>, <tt>let*</tt>, <tt>letrec</tt>
|
52
|
+
* Vector literals, also with quasiquoting support
|
53
|
+
* Definition and assignment: <tt>define</tt>, <tt>set!</tt>
|
54
|
+
* Lambdas: <tt>(lambda (x y) body ...)</tt>, <tt>(lambda args body ...)</tt>,
|
55
|
+
<tt>(lambda (x y . rest) body ...)</tt>
|
56
|
+
* Conditionals: <tt>if</tt>, <tt>cond</tt>, <tt>case</tt>
|
57
|
+
* Binding constructs: <tt>let</tt>, <tt>let*</tt>, <tt>letrec</tt>, <tt>begin</tt>
|
67
58
|
* Iteration: named <tt>let</tt>, <tt>do</tt>
|
59
|
+
* Quoting: <tt>quote</tt>, <tt>quasiquote</tt> and shorthands <tt>'</tt>,
|
60
|
+
<tt>`</tt>, <tt>,</tt>, <tt>,@</tt>
|
61
|
+
* Macros: <tt>let-syntax</tt>, <tt>letrec-syntax</tt>, <tt>define-syntax</tt>,
|
62
|
+
<tt>syntax-rules</tt>
|
68
63
|
* Delayed evaluation: <tt>delay</tt> and <tt>force</tt>
|
69
|
-
*
|
70
|
-
*
|
71
|
-
|
72
|
-
<tt>
|
73
|
-
<tt
|
74
|
-
|
75
|
-
<tt
|
76
|
-
|
77
|
-
<tt
|
78
|
-
<tt>
|
79
|
-
<tt>
|
80
|
-
<tt>
|
81
|
-
<tt>acos</tt>, <tt>atan</tt>, <tt>expt</tt>, <tt>sqrt</tt>,
|
82
|
-
<tt>zero?</tt>, <tt>positive?</tt>, <tt>negative?</tt>, <tt>odd?</tt>,
|
83
|
-
<tt>even?</tt>, <tt>abs</tt>, <tt>gcd</tt>, <tt>lcm</tt>,
|
64
|
+
* Continuations: <tt>call-with-current-continuation</tt>, aliased as <tt>call/cc</tt>
|
65
|
+
* Equivalance predicates: <tt>eqv?</tt>, <tt>eq?</tt>, <tt>equal?</tt>
|
66
|
+
* Numeric library: <tt>number?</tt>, <tt>complex?</tt>, <tt>real?</tt>,
|
67
|
+
<tt>rational?</tt>, <tt>integer?</tt>, <tt>exact?</tt>, <tt>inexact?</tt>,
|
68
|
+
<tt>=</tt>, <tt><</tt>, <tt>></tt>, <tt><=</tt>, <tt>>=</tt>, <tt>zero?</tt>,
|
69
|
+
<tt>positive?</tt>, <tt>negative?</tt>, <tt>odd?</tt>, <tt>even?</tt>,
|
70
|
+
<tt>max</tt>, <tt>min</tt>, <tt>+</tt>, <tt>*</tt>, <tt>-</tt>, <tt>/</tt>,
|
71
|
+
<tt>abs</tt>, <tt>quotient</tt>, <tt>remainder</tt>, <tt>modulo</tt>,
|
72
|
+
<tt>gcd</tt>, <tt>lcm</tt>, <tt>numerator</tt>, <tt>denominator</tt>,
|
73
|
+
<tt>floor</tt>, <tt>ceiling</tt>, <tt>truncate</tt>, <tt>round</tt>,
|
74
|
+
<tt>exp</tt>, <tt>log</tt>, <tt>sin</tt>, <tt>cos</tt>, <tt>tan</tt>,
|
75
|
+
<tt>asin</tt>, <tt>acos</tt>, <tt>atan</tt>, <tt>sqrt</tt>, <tt>expt</tt>,
|
84
76
|
<tt>make-rectangular</tt>, <tt>make-polar</tt>, <tt>real-part</tt>,
|
85
|
-
<tt>imag-part</tt>, <tt>magnitude</tt>, <tt>angle</tt>, <tt>
|
86
|
-
<tt>number
|
87
|
-
*
|
88
|
-
|
89
|
-
<tt>
|
90
|
-
<tt>
|
91
|
-
<tt>
|
92
|
-
|
93
|
-
|
94
|
-
|
77
|
+
<tt>imag-part</tt>, <tt>magnitude</tt>, <tt>angle</tt>, <tt>number->string</tt>,
|
78
|
+
<tt>string->number</tt>
|
79
|
+
* Boolean library: <tt>and</tt>, <tt>or</tt>, <tt>not</tt>, <tt>boolean?</tt>
|
80
|
+
* List library: <tt>pair?</tt>, <tt>cons</tt>, <tt>car</tt>, <tt>cdr</tt>,
|
81
|
+
<tt>set-car!</tt>, <tt>set-cdr!</tt>, <tt>caar</tt>, <tt>cadr</tt> ...
|
82
|
+
<tt>cdddar</tt>, <tt>cddddr</tt>, <tt>null?</tt>, <tt>list?</tt>, <tt>list</tt>,
|
83
|
+
<tt>length</tt>, <tt>append</tt>, <tt>reverse</tt>, <tt>list-tail</tt>,
|
84
|
+
<tt>list-ref</tt>, <tt>memq</tt>, <tt>memv</tt>, <tt>member</tt>, <tt>assq</tt>,
|
85
|
+
<tt>assv</tt>, <tt>assoc</tt>
|
86
|
+
* Symbol library: <tt>symbol?</tt>, <tt>symbol->string</tt>, <tt>string->symbol</tt>
|
87
|
+
* Character library: <tt>char?</tt>, <tt>char=?</tt>, <tt>char<?</tt>,
|
88
|
+
<tt>char>?</tt>, <tt>char<=?</tt>, <tt>char>=?</tt>, <tt>char-ci=?</tt>,
|
89
|
+
<tt>char-ci<?</tt>, <tt>char-ci>?</tt>, <tt>char-ci<=?</tt>, <tt>char-ci>=?</tt>,
|
90
|
+
<tt>char-alphabetic?</tt>, <tt>char-numeric?</tt>, <tt>char-whitespace?</tt>,
|
91
|
+
<tt>char-upper-case?</tt>, <tt>char-lower-case?</tt>, <tt>char->integer</tt>,
|
92
|
+
<tt>integer->char</tt>, <tt>char-upcase</tt>, <tt>char-downcase</tt>
|
93
|
+
* String library: <tt>string?</tt>, <tt>make-string</tt>, <tt>string</tt>,
|
94
|
+
<tt>string-length</tt>, <tt>string-ref</tt>, <tt>string-set!</tt>,
|
95
|
+
<tt>string=?</tt>, <tt>string-ci=?</tt>, <tt>string<?</tt>, <tt>string>?</tt>,
|
96
|
+
<tt>string<=?</tt>, <tt>string>=?</tt>, <tt>string-ci<?</tt>, <tt>string-ci>?</tt>,
|
97
|
+
<tt>string-ci<=?</tt>, <tt>string-ci>=?</tt>, <tt>substring</tt>,
|
98
|
+
<tt>string-append</tt>, <tt>string->list</tt>, <tt>list->string</tt>,
|
99
|
+
<tt>string-copy</tt>, <tt>string-fill!</tt>
|
100
|
+
* Vector library: <tt>vector?</tt>, <tt>make-vector</tt>, <tt>vector</tt>,
|
101
|
+
<tt>vector-length</tt>, <tt>vector-ref</tt>, <tt>vector-set!</tt>,
|
102
|
+
<tt>vector->list</tt>, <tt>list->vector</tt>, <tt>vector-fill!</tt>
|
103
|
+
* Control features: <tt>procedure?</tt>, <tt>apply</tt>, <tt>map</tt>,
|
104
|
+
<tt>for-each</tt>, <tt>eval</tt>, <tt>load</tt>
|
105
|
+
* Input/output: <tt>display</tt>, <tt>newline</tt>
|
95
106
|
|
96
107
|
In addition to the above R5RS features, the following are provided. Heist
|
97
108
|
allows the behaviour of some of these features to be configured on a
|
@@ -194,16 +205,17 @@ For example, using our <tt>Heist::Runtime</tt> instance from above:
|
|
194
205
|
scheme.exec [:square, 9]
|
195
206
|
#=> 81
|
196
207
|
|
197
|
-
Arrays map directly to Scheme lists, symbols map to identifiers, strings
|
198
|
-
and
|
199
|
-
verbatim. So, you can use any piece of Ruby data in these
|
200
|
-
as long as the functions you're calling can operate on it.
|
208
|
+
Arrays map directly to Scheme lists, symbols map to identifiers, strings,
|
209
|
+
numbers and booleans are treated as literals, and any other data is
|
210
|
+
interpreted verbatim. So, you can use any piece of Ruby data in these
|
211
|
+
expressions as long as the functions you're calling can operate on it.
|
201
212
|
|
202
|
-
Due to syntactic limitations, some Scheme
|
203
|
-
interface. Quoting is out, so the expression <tt>'(1 2 3)</tt> would
|
204
|
-
need to be written <tt>[:quote, [1, 2, 3]]</tt>. Dotted pairs and
|
205
|
-
|
206
|
-
|
213
|
+
Due to syntactic limitations, some Scheme constructs cannot be used in this
|
214
|
+
interface. Quoting syntax is out, so the expression <tt>'(1 2 3)</tt> would
|
215
|
+
need to be written <tt>[:quote, [1, 2, 3]]</tt>. Dotted pairs and improper
|
216
|
+
lists are also not available, though you can work around this to some extent
|
217
|
+
using <tt>:cons</tt>. Vectors should be written as <tt>[:vector, 1, 2, 3]</tt>
|
218
|
+
for example. Characters are not supported at all.
|
207
219
|
|
208
220
|
|
209
221
|
== Notes
|
@@ -217,7 +229,9 @@ and can be assumed to be reasonably stable.
|
|
217
229
|
I have not documented how to write your own syntax using Ruby because
|
218
230
|
it requires far too much knowledge of Heist's plumbing at present (I
|
219
231
|
suspect this may be unavoidable). Besides, we have macros so if you
|
220
|
-
want new syntax we've got you covered.
|
232
|
+
want new syntax we've got you covered. In fact, writing syntax using
|
233
|
+
macros makes sure that new syntactic forms support continuations
|
234
|
+
correctly, and Heist itself eschews Ruby-based syntax where possible.
|
221
235
|
|
222
236
|
Heist is extremely liberal as regards symbols. Any sequence of
|
223
237
|
characters that does not contain any spaces or parentheses and that
|
data/Rakefile
CHANGED
@@ -4,9 +4,33 @@ require 'rubygems'
|
|
4
4
|
require 'hoe'
|
5
5
|
require './lib/heist.rb'
|
6
6
|
|
7
|
-
Hoe.
|
7
|
+
Hoe.spec('heist') do |p|
|
8
8
|
p.developer('James Coglan', 'jcoglan@googlemail.com')
|
9
9
|
p.extra_deps = %w(oyster treetop)
|
10
10
|
end
|
11
11
|
|
12
|
+
namespace :spec do
|
13
|
+
task :r5rs do
|
14
|
+
procedures = Dir['r5rs/*.html'].
|
15
|
+
map { |f| File.read(f) }.
|
16
|
+
join("\n").
|
17
|
+
split(/\n+/).
|
18
|
+
grep(/(syntax|procedure)\:/).
|
19
|
+
map { |s| s.gsub(/<\/?[^>]+>/, '').
|
20
|
+
scan(/\(([^\) ]+)/).
|
21
|
+
flatten.
|
22
|
+
first }.
|
23
|
+
uniq.
|
24
|
+
compact.
|
25
|
+
map { |s| s.gsub('<', '<').
|
26
|
+
gsub('>', '>') }
|
27
|
+
|
28
|
+
scope = Heist::Runtime.new.top_level
|
29
|
+
procedures.each do |proc|
|
30
|
+
message = scope.defined?(proc) ? scope.exec(proc) : 'MISSING'
|
31
|
+
puts " %-32s %-48s" % [proc, message]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
12
36
|
# vim: syntax=Ruby
|
data/lib/builtin/library.scm
CHANGED
@@ -25,14 +25,6 @@
|
|
25
25
|
(define (not x)
|
26
26
|
(if x #f #t))
|
27
27
|
|
28
|
-
; (negate x)
|
29
|
-
; Returns a negated form of x, like (not) but also
|
30
|
-
; works on functions
|
31
|
-
(define (negate proc)
|
32
|
-
(if (procedure? proc)
|
33
|
-
(lambda args (not (apply proc args)))
|
34
|
-
(not proc)))
|
35
|
-
|
36
28
|
; Longhand aliases for boolean constants
|
37
29
|
(define true #t)
|
38
30
|
(define false #f)
|
@@ -50,9 +42,19 @@
|
|
50
42
|
; Returns true iff x is any type of number
|
51
43
|
(define number? complex?)
|
52
44
|
|
45
|
+
; (exact? x)
|
46
|
+
; Returns true iff the given number is exact i.e. an integer, a
|
47
|
+
; rational, or a complex made of integers or rationals
|
48
|
+
(define (exact? x)
|
49
|
+
(or (rational? x)
|
50
|
+
(and (not (zero? (imag-part x)))
|
51
|
+
(exact? (real-part x))
|
52
|
+
(exact? (imag-part x)))))
|
53
|
+
|
53
54
|
; (inexact? x)
|
54
55
|
; Returns true iff x is not an exact number
|
55
|
-
(define inexact?
|
56
|
+
(define (inexact? x)
|
57
|
+
(not (exact? x)))
|
56
58
|
|
57
59
|
; Returns true iff all arguments are numerically equal
|
58
60
|
(define (= . args)
|
@@ -336,3 +338,236 @@
|
|
336
338
|
(proc (car list)
|
337
339
|
(foldr proc value (cdr list)))))
|
338
340
|
|
341
|
+
;----------------------------------------------------------------
|
342
|
+
|
343
|
+
; Character functions
|
344
|
+
|
345
|
+
; (char-upper-case? letter)
|
346
|
+
; Returns true iff letter is an uppercase letter
|
347
|
+
(define (char-upper-case? letter)
|
348
|
+
(and (char? letter)
|
349
|
+
(let ([code (char->integer letter)])
|
350
|
+
(and (>= code 65)
|
351
|
+
(<= code 90)))))
|
352
|
+
|
353
|
+
; (char-lower-case? letter)
|
354
|
+
; Returns true iff letter is a lowercase letter
|
355
|
+
(define (char-lower-case? letter)
|
356
|
+
(and (char? letter)
|
357
|
+
(let ([code (char->integer letter)])
|
358
|
+
(and (>= code 97)
|
359
|
+
(<= code 122)))))
|
360
|
+
|
361
|
+
; (char-alphabetic? char)
|
362
|
+
; Returns true iff char is an alphabetic character
|
363
|
+
(define (char-alphabetic? char)
|
364
|
+
(or (char-upper-case? char)
|
365
|
+
(char-lower-case? char)))
|
366
|
+
|
367
|
+
; (char-numeric? char)
|
368
|
+
; Returns true iff char is a numeric character
|
369
|
+
(define (char-numeric? char)
|
370
|
+
(and (char? char)
|
371
|
+
(let ([code (char->integer char)])
|
372
|
+
(and (>= code 48)
|
373
|
+
(<= code 57)))))
|
374
|
+
|
375
|
+
; (char-whitespace? char)
|
376
|
+
; Returns true iff char is a whitespace character
|
377
|
+
(define (char-whitespace? char)
|
378
|
+
(and (char? char)
|
379
|
+
(if (member (char->integer char)
|
380
|
+
'(9 10 32))
|
381
|
+
#t
|
382
|
+
#f)))
|
383
|
+
|
384
|
+
; (char-upcase char)
|
385
|
+
; Returns an uppercase copy of char
|
386
|
+
(define (char-upcase char)
|
387
|
+
(let ([code (char->integer char)])
|
388
|
+
(if (and (>= code 97) (<= code 122))
|
389
|
+
(integer->char (- code 32))
|
390
|
+
(integer->char code))))
|
391
|
+
|
392
|
+
; (char-downcase char)
|
393
|
+
; Returns a lowercase copy of char
|
394
|
+
(define (char-downcase char)
|
395
|
+
(let ([code (char->integer char)])
|
396
|
+
(if (and (>= code 65) (<= code 90))
|
397
|
+
(integer->char (+ code 32))
|
398
|
+
(integer->char code))))
|
399
|
+
|
400
|
+
(define (char-compare-ci operator)
|
401
|
+
(lambda (x y)
|
402
|
+
(operator (char-downcase x)
|
403
|
+
(char-downcase y))))
|
404
|
+
|
405
|
+
(define char-ci=? (char-compare-ci char=?))
|
406
|
+
(define char-ci<? (char-compare-ci char<?))
|
407
|
+
(define char-ci>? (char-compare-ci char>?))
|
408
|
+
(define char-ci<=? (char-compare-ci char<=?))
|
409
|
+
(define char-ci>=? (char-compare-ci char>=?))
|
410
|
+
|
411
|
+
;----------------------------------------------------------------
|
412
|
+
|
413
|
+
; String functions
|
414
|
+
|
415
|
+
; (string char ...)
|
416
|
+
; Returns a new string formed by combining the given characters
|
417
|
+
(define (string . chars) (list->string chars))
|
418
|
+
|
419
|
+
(define (string-compare string1 string2 char-less? char-greater?)
|
420
|
+
(if (or (not (string? string1))
|
421
|
+
(not (string? string2)))
|
422
|
+
(error "Expected two strings as arguments")
|
423
|
+
(do ([pair1 (string->list string1) (cdr pair1)]
|
424
|
+
[pair2 (string->list string2) (cdr pair2)]
|
425
|
+
[diff '()])
|
426
|
+
((integer? diff) diff)
|
427
|
+
(set! diff (cond [(null? pair1) (if (null? pair2) 0 -1)]
|
428
|
+
[(null? pair2) 1]
|
429
|
+
[else (let ([char1 (car pair1)]
|
430
|
+
[char2 (car pair2)])
|
431
|
+
(cond [(char-less? char1 char2) -1]
|
432
|
+
[(char-greater? char1 char2) 1]
|
433
|
+
[else '()]))])))))
|
434
|
+
|
435
|
+
; (string=? string1 string2)
|
436
|
+
; Returns true iff string1 and string2 are equal strings
|
437
|
+
(define (string=? string1 string2)
|
438
|
+
(zero? (string-compare string1 string2 char<? char>?)))
|
439
|
+
|
440
|
+
; (string-ci=? string1 string2)
|
441
|
+
; Returns true iff string1 and string2 are equal strings, ignoring case
|
442
|
+
(define (string-ci=? string1 string2)
|
443
|
+
(zero? (string-compare string1 string2 char-ci<? char-ci>?)))
|
444
|
+
|
445
|
+
; (string<? string1 string2)
|
446
|
+
; Returns true iff string1 is lexicographically less than string2
|
447
|
+
(define (string<? string1 string2)
|
448
|
+
(= (string-compare string1 string2 char<? char>?) -1))
|
449
|
+
|
450
|
+
; (string>? string1 string2)
|
451
|
+
; Returns true iff string1 is lexicographically greater than string2
|
452
|
+
(define (string>? string1 string2)
|
453
|
+
(= (string-compare string1 string2 char<? char>?) 1))
|
454
|
+
|
455
|
+
; (string<=? string1 string2)
|
456
|
+
; Returns true iff string1 is lexicographically less than or equal
|
457
|
+
; to string2
|
458
|
+
(define (string<=? string1 string2)
|
459
|
+
(not (string>? string1 string2)))
|
460
|
+
|
461
|
+
; (string>=? string1 string2)
|
462
|
+
; Returns true iff string1 is lexicographically greater than or equal
|
463
|
+
; to string2
|
464
|
+
(define (string>=? string1 string2)
|
465
|
+
(not (string<? string1 string2)))
|
466
|
+
|
467
|
+
; (string-ci<? string1 string2)
|
468
|
+
; Returns true iff string1 is lexicographically less than string2,
|
469
|
+
; ignoring differences in case
|
470
|
+
(define (string-ci<? string1 string2)
|
471
|
+
(= (string-compare string1 string2 char-ci<? char-ci>?) -1))
|
472
|
+
|
473
|
+
; (string-ci>? string1 string2)
|
474
|
+
; Returns true iff string1 is lexicographically greater than string2,
|
475
|
+
; ignoring differences in case
|
476
|
+
(define (string-ci>? string1 string2)
|
477
|
+
(= (string-compare string1 string2 char-ci<? char-ci>?) 1))
|
478
|
+
|
479
|
+
; (string-ci<=? string1 string2)
|
480
|
+
; Returns true iff string1 is lexicographically less than or equal
|
481
|
+
; to string2, ignoring differences in case
|
482
|
+
(define (string-ci<=? string1 string2)
|
483
|
+
(not (string-ci>? string1 string2)))
|
484
|
+
|
485
|
+
; (string-ci>=? string1 string2)
|
486
|
+
; Returns true iff string1 is lexicographically greater than or equal
|
487
|
+
; to string2, ignoring differences in case
|
488
|
+
(define (string-ci>=? string1 string2)
|
489
|
+
(not (string-ci<? string1 string2)))
|
490
|
+
|
491
|
+
; (substring string start end)
|
492
|
+
; Returns a string composed of the characters from start (inclusive)
|
493
|
+
; to end (exclusive) in string
|
494
|
+
(define (substring string start end)
|
495
|
+
(let ([size (string-length string)])
|
496
|
+
(cond [(< start 0) (error "start index must be positive")]
|
497
|
+
[(> end size) (error "end index must be <= the length of string")]
|
498
|
+
[(> start end) (error "start must be <= end index")]
|
499
|
+
[else
|
500
|
+
(let* ([subsize (- end start)]
|
501
|
+
[substr (make-string subsize)])
|
502
|
+
(do ([i 0 (+ i 1)])
|
503
|
+
((= i subsize) substr)
|
504
|
+
(string-set! substr i (string-ref string (+ start i)))))])))
|
505
|
+
|
506
|
+
; (list->string chars)
|
507
|
+
; Returns a new string formed by combining the list
|
508
|
+
(define (list->string chars)
|
509
|
+
(let* ([size (length chars)]
|
510
|
+
[str (make-string size)])
|
511
|
+
(do ([list chars (cdr list)]
|
512
|
+
[i 0 (+ i 1)])
|
513
|
+
((= i size) str)
|
514
|
+
(string-set! str i (car list)))))
|
515
|
+
|
516
|
+
; (string->list string)
|
517
|
+
; Returns a newly allocated list of the characters in the string
|
518
|
+
(define (string->list string)
|
519
|
+
(let ([size (string-length string)])
|
520
|
+
(do ([i size (- i 1)]
|
521
|
+
[list '() (cons (string-ref string (- i 1)) list)])
|
522
|
+
((zero? i) list))))
|
523
|
+
|
524
|
+
; (string-copy string)
|
525
|
+
; Returns a newly allocated copy of the string
|
526
|
+
(define (string-copy string)
|
527
|
+
(list->string (string->list string)))
|
528
|
+
|
529
|
+
; (string-fill! string char)
|
530
|
+
; Replaces every character of string with char
|
531
|
+
(define (string-fill! string char)
|
532
|
+
(let ([size (string-length string)])
|
533
|
+
(do ([i size (- i 1)])
|
534
|
+
((zero? i) string)
|
535
|
+
(string-set! string (- i 1) char))))
|
536
|
+
|
537
|
+
; (string-append string ...)
|
538
|
+
; Returns a new string formed by concatenating the arguments
|
539
|
+
(define (string-append . strings)
|
540
|
+
(list->string (apply append (map string->list strings))))
|
541
|
+
|
542
|
+
;----------------------------------------------------------------
|
543
|
+
|
544
|
+
; Vector functions
|
545
|
+
|
546
|
+
; (vector object ...)
|
547
|
+
; Returns a newly allocated vector from its arguments
|
548
|
+
(define (vector . args) (list->vector args))
|
549
|
+
|
550
|
+
; (list->vector list)
|
551
|
+
; Returns a newly allocated vector from a list
|
552
|
+
(define (list->vector list)
|
553
|
+
(let* ([size (length list)]
|
554
|
+
[new-vector (make-vector size)])
|
555
|
+
(do ([i 0 (+ i 1)]
|
556
|
+
[pair list (cdr pair)])
|
557
|
+
((= i size) new-vector)
|
558
|
+
(vector-set! new-vector i (car pair)))))
|
559
|
+
|
560
|
+
; (vector->list vector)
|
561
|
+
; Returns a newly allocated proper list from a vector
|
562
|
+
(define (vector->list vector)
|
563
|
+
(do ([i (vector-length vector) (- i 1)]
|
564
|
+
[pair '() (cons (vector-ref vector (- i 1)) pair)])
|
565
|
+
((zero? i) pair)))
|
566
|
+
|
567
|
+
; (vector-fill! vector fill)
|
568
|
+
; Sets every element of vector to fill
|
569
|
+
(define (vector-fill! vector fill)
|
570
|
+
(do ([i (vector-length vector) (- i 1)])
|
571
|
+
((zero? i) vector)
|
572
|
+
(vector-set! vector (- i 1) fill)))
|
573
|
+
|