heist 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|