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/lib/runtime/frame.rb
CHANGED
@@ -63,6 +63,13 @@ module Heist
|
|
63
63
|
stack = @scope.runtime.stack
|
64
64
|
stack << Frame.new(@current.car, @scope)
|
65
65
|
|
66
|
+
# If it's a Vector (it will be unquoted if it has arrived here, copy
|
67
|
+
# it and return it. We cannot freeze it for fear of breaking macros,
|
68
|
+
# and we must copy it so that vector-set! cannot modify the parse tree.
|
69
|
+
when Vector then
|
70
|
+
@complete = true
|
71
|
+
@expression.dup
|
72
|
+
|
66
73
|
# If the expression is an +Identifier+, just look it up.
|
67
74
|
when Identifier then
|
68
75
|
@complete = true
|
data/lib/runtime/runtime.rb
CHANGED
@@ -11,7 +11,8 @@ module Heist
|
|
11
11
|
#
|
12
12
|
class Runtime
|
13
13
|
|
14
|
-
%w[ data/expression data/identifier data/
|
14
|
+
%w[ data/expression data/identifier data/character
|
15
|
+
data/cons data/vector
|
15
16
|
callable/function callable/syntax callable/macro callable/continuation
|
16
17
|
frame stack stackless
|
17
18
|
scope binding
|
data/lib/runtime/scope.rb
CHANGED
@@ -20,7 +20,7 @@ module Heist
|
|
20
20
|
# The parent may also be a +Runtime+ instance, indicating that the
|
21
21
|
# new +Scope+ is being used as the top level of a runtime environment.
|
22
22
|
def initialize(parent = {})
|
23
|
-
@symbols =
|
23
|
+
@symbols = Trie.new
|
24
24
|
is_runtime = (Runtime === parent)
|
25
25
|
@parent = is_runtime ? {} : parent
|
26
26
|
@runtime = is_runtime ? parent : parent.runtime
|
@@ -145,14 +145,10 @@ module Heist
|
|
145
145
|
end
|
146
146
|
alias :exec :eval
|
147
147
|
|
148
|
-
# Returns
|
149
|
-
#
|
150
|
-
def
|
151
|
-
|
152
|
-
@symbols.each do |key, value|
|
153
|
-
base << key if key =~ pattern
|
154
|
-
end
|
155
|
-
base.uniq
|
148
|
+
# Returns the longest shared prefix match for the given variable name
|
149
|
+
# stub, used to support autocompletion in the REPL.
|
150
|
+
def longest_prefix(name)
|
151
|
+
@symbols.longest_prefix(to_name(name))
|
156
152
|
end
|
157
153
|
|
158
154
|
# Runs the given Scheme or Ruby definition file in the receiving
|
data/lib/runtime/stackless.rb
CHANGED
@@ -68,6 +68,13 @@ module Heist
|
|
68
68
|
expression.replace(value.expression)
|
69
69
|
return Frame.new(value.expression, scope)
|
70
70
|
|
71
|
+
# If the expression is a Vector (unquoted if found here), duplicate
|
72
|
+
# it and return it. We don't want to freeze unquoted vectors as this
|
73
|
+
# stops macros working, but also we don't want to allow procedures
|
74
|
+
# such as vector-set! to modify the parse tree.
|
75
|
+
when Vector then
|
76
|
+
expression.dup
|
77
|
+
|
71
78
|
# If the expression is an identifier, look up its value in
|
72
79
|
# the current scope
|
73
80
|
when Identifier then
|
data/lib/trie.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
module Heist
|
2
|
+
|
3
|
+
# A +Trie+ is a special type of key-value store, one in which the keys are all
|
4
|
+
# sequences of some kind: they could be strings, or arrays, or lists. We use
|
5
|
+
# tries to store symbol tables in Heist because it makes autocompletion easier
|
6
|
+
# to implement, and one aim of Heist is to be a pleasant interactive Scheme.
|
7
|
+
#
|
8
|
+
# In our particular implementation, keys (strings representing variable names)
|
9
|
+
# are split into arrays and stored in a series of nested hashtables whose keys
|
10
|
+
# are single characters. Strings sharing a common prefix share part of the tree
|
11
|
+
# structure. The <tt>Trie#inspect</tt> method provides a good representation
|
12
|
+
# of this (values omitted for the sake of brevity):
|
13
|
+
#
|
14
|
+
# tree = Trie.new
|
15
|
+
# tree['foo'] = 1
|
16
|
+
#
|
17
|
+
# tree #=> {"f"=>{"o"=>{"o"=>{}}}}
|
18
|
+
#
|
19
|
+
# tree['bar'] = 2
|
20
|
+
# tree['baz'] = 3
|
21
|
+
#
|
22
|
+
# tree #=> {"b"=>{"a"=>{"z"=>{}, "r"=>{}}}, "f"=>{"o"=>{"o"=>{}}}}
|
23
|
+
#
|
24
|
+
# A trie is a recursive structure; each key in a trie points to another trie.
|
25
|
+
# Every trie contains a list of its children (a hash mapping characters to
|
26
|
+
# subtries) and may contain a value if it appears at the end of a sequence
|
27
|
+
# making up a full key of the root trie.
|
28
|
+
#
|
29
|
+
# For more information, see http://en.wikipedia.org/wiki/Trie
|
30
|
+
#
|
31
|
+
class Trie
|
32
|
+
attr_accessor :value
|
33
|
+
|
34
|
+
# A +Trie+ is initialized with an optional +value+. The value may be
|
35
|
+
# omitted if the trie does not represent the end of a key sequence.
|
36
|
+
def initialize(value = nil)
|
37
|
+
@value = value
|
38
|
+
@children = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns +true+ iff the given +key+ is present in the +Trie+. They key
|
42
|
+
# must match a complete key sequence that maps to a value, not a partial
|
43
|
+
# prefix with no value attached.
|
44
|
+
def has_key?(key)
|
45
|
+
trie = traverse(key)
|
46
|
+
trie and not trie.value.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the value corresponding to +key+, or +nil+ if none is found.
|
50
|
+
def [](key)
|
51
|
+
trie = traverse(key)
|
52
|
+
trie ? trie.value : nil
|
53
|
+
end
|
54
|
+
|
55
|
+
# Assigns +value+ to the given +key+.
|
56
|
+
def []=(key, value)
|
57
|
+
traverse(key, true).value = value
|
58
|
+
end
|
59
|
+
|
60
|
+
# Walks the +Trie+ structure using the given +key+, returning the
|
61
|
+
# resulting subtrie or +nil+ if the key is absent. Pass +true+ as the
|
62
|
+
# second argument to create a subtrie for the key if none exists.
|
63
|
+
def traverse(key, create_if_absent = false)
|
64
|
+
key = convert_key(key)
|
65
|
+
return self if key.empty?
|
66
|
+
trie = @children[key.first]
|
67
|
+
return nil if trie.nil? and not create_if_absent
|
68
|
+
trie = @children[key.first] = Trie.new if trie.nil?
|
69
|
+
trie.traverse(key[1..-1], create_if_absent)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns an array of all the characters used as keys in this +Trie+.
|
73
|
+
# That is, this method returns the initial letters of all the keys
|
74
|
+
# stored in the +Trie+.
|
75
|
+
def prefixes
|
76
|
+
@children.keys
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns +true+ if the +Trie+ has no value and only one child. Used
|
80
|
+
# in +longest_prefix+ to find the longest unique prefix from some
|
81
|
+
# starting point.
|
82
|
+
def singular?
|
83
|
+
@value.nil? and @children.size == 1
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the longest unique key prefix that starts with +key+. This
|
87
|
+
# is used for autocompletion in the REPL. Given a string, this method
|
88
|
+
# returns another string such that the start of the output is the
|
89
|
+
# same as the input, and the output may contain zero or more additional
|
90
|
+
# characters such that all the keys that begin with the input also begin
|
91
|
+
# with the output.
|
92
|
+
#
|
93
|
+
# tree = Trie.new
|
94
|
+
# tree['foo'] = 1
|
95
|
+
# tree['bar'] = 2
|
96
|
+
# tree['baz'] = 3
|
97
|
+
#
|
98
|
+
# tree.longest_prefix 'f'
|
99
|
+
# #=> "foo"
|
100
|
+
# tree.longest_prefix 'b'
|
101
|
+
# #=> "ba"
|
102
|
+
#
|
103
|
+
def longest_prefix(key)
|
104
|
+
prefix = convert_key(key).dup
|
105
|
+
trie = traverse(key)
|
106
|
+
return nil if trie.nil?
|
107
|
+
while trie.singular?
|
108
|
+
next_key = trie.prefixes.first
|
109
|
+
prefix << next_key
|
110
|
+
trie = trie.traverse(next_key)
|
111
|
+
end
|
112
|
+
case key
|
113
|
+
when String then prefix.join('')
|
114
|
+
when Symbol then prefix.join('').to_sym
|
115
|
+
else prefix
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns a string representation of the trie's internal structure.
|
120
|
+
# Values are not printed; the main purpose of this method is to inspect
|
121
|
+
# the internal tree structure.
|
122
|
+
def inspect
|
123
|
+
@children.inspect
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
# Returns an array from the given +key+, making it ready for use as
|
129
|
+
# a key sequence.
|
130
|
+
def convert_key(key)
|
131
|
+
case key
|
132
|
+
when Array then key
|
133
|
+
when Symbol then key.to_s.split('')
|
134
|
+
when String then key.split('')
|
135
|
+
when Enumerable then key.entries
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
data/test/equivalence.scm
CHANGED
@@ -10,10 +10,17 @@
|
|
10
10
|
(assert (not (eqv? 42 #f)))
|
11
11
|
(assert (not (eqv? 42 42.0)))
|
12
12
|
|
13
|
+
(assert (eqv? #\A #\A))
|
14
|
+
(assert (not (eqv? #\A #\B)))
|
15
|
+
(assert (not (eqv? #\A #\a)))
|
16
|
+
|
13
17
|
(assert (eqv? '() '()))
|
14
18
|
(assert (not (eqv? '(1 2) '(1 2))))
|
15
19
|
(assert (not (eqv? '() '(1 2))))
|
16
20
|
|
21
|
+
(assert (not (eqv? #() #())))
|
22
|
+
(assert (not (eqv? #(4) #(4))))
|
23
|
+
|
17
24
|
(assert (eqv? ceil ceiling))
|
18
25
|
|
19
26
|
|
data/test/let.scm
CHANGED
@@ -40,3 +40,16 @@
|
|
40
40
|
|
41
41
|
(assert-equal 720 (do-factorial 6))
|
42
42
|
|
43
|
+
|
44
|
+
; R5RS compliance test -- http://okmij.org/ftp/Scheme/lambda-derived.txt
|
45
|
+
(assert-equal '(1 1 1 1 1 1 1)
|
46
|
+
(let ((foo (lambda (x) x)))
|
47
|
+
(list
|
48
|
+
(foo ((lambda () (define a 1) a)))
|
49
|
+
(foo (let () (define a 1) a))
|
50
|
+
(foo (let* () (define a 1) a))
|
51
|
+
(foo (letrec () (define a 1) a))
|
52
|
+
(foo (letrec () (define (b) (define a 1) a) (b)))
|
53
|
+
(foo (let-syntax () (define a 1) a))
|
54
|
+
(foo (letrec-syntax () (define a 1) a)))))
|
55
|
+
|
data/test/lists.scm
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
(assert (eqv? '() '()))
|
2
|
-
(assert (not (eqv? '(5) '(5))))
|
3
|
-
|
4
1
|
(assert (null? '()))
|
5
2
|
(assert (list? '()))
|
6
3
|
(assert (not (pair? '())))
|
7
4
|
|
5
|
+
(assert (not (vector? '(1 2 3))))
|
6
|
+
|
8
7
|
(define foo-list (list (+ 3 2) (* 4 5) 6))
|
9
8
|
(assert (not (eqv? '(5 20 6) foo-list)))
|
10
9
|
(assert (equal? '(5 20 6) foo-list))
|
data/test/macros.scm
CHANGED
@@ -88,12 +88,26 @@
|
|
88
88
|
[(_ foo bar . rest)
|
89
89
|
rest]))
|
90
90
|
(assert-equal 10 (rest 4 5 + 3 7))
|
91
|
+
|
91
92
|
(let-syntax ([foo (syntax-rules ()
|
92
93
|
[(_ expr ...)
|
93
94
|
(list expr ...)])])
|
94
95
|
(assert-equal '(1 2 3) (foo 1 2 3))
|
95
96
|
(assert-raise SyntaxError (foo 1 2 3 . 4)))
|
96
97
|
|
98
|
+
(let-syntax ([foo (syntax-rules ()
|
99
|
+
[(_ bindings body ...)
|
100
|
+
'(defun (proc . bindings) body ...)])])
|
101
|
+
|
102
|
+
(assert-equal '(defun (proc x y) (display x) y)
|
103
|
+
(foo (x y) (display x) y))
|
104
|
+
|
105
|
+
(assert-equal '(defun (proc x y . z) z)
|
106
|
+
(foo (x y . z) z))
|
107
|
+
|
108
|
+
(assert-equal '(defun (proc . z) z)
|
109
|
+
(foo z z)))
|
110
|
+
|
97
111
|
|
98
112
|
; Test input execution - example from R5RS
|
99
113
|
|
data/test/strings.scm
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
(assert (equal? (symbol->string 'foo) "foo"))
|
2
|
+
(assert (eqv? (string->symbol "foo") 'foo))
|
3
|
+
|
4
|
+
(assert (char? #\a))
|
5
|
+
(assert (char? #\ ))
|
6
|
+
(assert (char? #\)))
|
7
|
+
(assert (char? #\tab))
|
8
|
+
|
9
|
+
(assert (char=? #\F #\F))
|
10
|
+
(assert (char=? #\space #\space))
|
11
|
+
(assert (char=? #\space #\ ))
|
12
|
+
(assert (char=? #\ #\space))
|
13
|
+
(assert (not (char=? #\F #\f)))
|
14
|
+
(assert (not (char=? #\8 #\f)))
|
15
|
+
|
16
|
+
(assert (char<? #\A #\B))
|
17
|
+
(assert (char<? #\a #\b))
|
18
|
+
(assert (char<? #\0 #\9))
|
19
|
+
|
20
|
+
(assert (char=? (integer->char 97) #\a))
|
21
|
+
(assert-equal 100 (char->integer #\d))
|
22
|
+
|
23
|
+
(assert (char=? #\A (char-upcase #\a)))
|
24
|
+
(assert (char=? #\h (char-downcase #\H)))
|
25
|
+
|
26
|
+
(assert (char-alphabetic? #\A))
|
27
|
+
(assert (char-alphabetic? #\Z))
|
28
|
+
(assert (char-alphabetic? #\a))
|
29
|
+
(assert (char-alphabetic? #\z))
|
30
|
+
(assert (not (char-alphabetic? #\0)))
|
31
|
+
(assert (not (char-alphabetic? #\[)))
|
32
|
+
|
33
|
+
(assert (char-numeric? #\0))
|
34
|
+
(assert (char-numeric? #\9))
|
35
|
+
(assert (not (char-numeric? #\k)))
|
36
|
+
|
37
|
+
(assert (char-whitespace? #\ ))
|
38
|
+
(assert (char-whitespace? #\tab))
|
39
|
+
(assert (char-whitespace? #\newline))
|
40
|
+
(assert (char-whitespace? #\space))
|
41
|
+
(assert (not (char-whitespace? #\s)))
|
42
|
+
|
43
|
+
(assert (char-ci=? #\A #\a))
|
44
|
+
(assert (not (char-ci=? #\A #\b)))
|
45
|
+
|
46
|
+
(assert (string? "foo"))
|
47
|
+
(assert (not (string? 'foo)))
|
48
|
+
(assert (not (string? #\a)))
|
49
|
+
(assert (not (string? 9)))
|
50
|
+
|
51
|
+
(assert-equal " " (make-string 4))
|
52
|
+
(assert-equal ")))))))" (make-string 7 #\)))
|
53
|
+
|
54
|
+
(let ([g (lambda () "***")])
|
55
|
+
(assert-raise ImmutableError (string-set! (g) 0 #\?))
|
56
|
+
(assert-equal "***" (g)))
|
57
|
+
|
58
|
+
(assert-equal 13 (string-length "smoked salmon"))
|
59
|
+
(assert-equal #\o (string-ref "salmon" 4))
|
60
|
+
(assert-raise BadIndexError (string-ref "salmon" 7))
|
61
|
+
|
62
|
+
(let ([s (string-copy "saLMON")])
|
63
|
+
(string-set! s 4 #\k)
|
64
|
+
(assert-equal "saLMkN" s)
|
65
|
+
(assert (eqv? s s))
|
66
|
+
(assert (not (eqv? (string-copy s) s)))
|
67
|
+
(assert (equal? (string-copy s) s))
|
68
|
+
(string-fill! s #\G)
|
69
|
+
(assert-equal "GGGGGG" s))
|
70
|
+
|
71
|
+
(assert-equal "alm" (substring "salmon" 1 4))
|
72
|
+
|
73
|
+
(assert-equal "foo" (string #\f #\o #\o))
|
74
|
+
(assert-equal "" (string))
|
75
|
+
|
76
|
+
(assert-equal '(#\f #\o #\o) (string->list "foo"))
|
77
|
+
(assert-equal "foo" (list->string '(#\f #\o #\o)))
|
78
|
+
|
79
|
+
(assert-equal "foo bar baz" (string-append "foo " "ba" "r baz" ""))
|
80
|
+
|
81
|
+
(assert (string=? "foo" "foo"))
|
82
|
+
(assert (not (string=? "foo" "Foo")))
|
83
|
+
(assert (not (string=? "foo" "food")))
|
84
|
+
(assert (not (string=? "food" "foo")))
|
85
|
+
(assert (string-ci=? "foo" "Foo"))
|
86
|
+
(assert (not (string-ci=? "food" "Fool")))
|
87
|
+
|
88
|
+
(assert (string<? "abacus" "badger"))
|
89
|
+
(assert (string<? "badger" "badges"))
|
90
|
+
(assert (string<? "string" "stringify"))
|
91
|
+
(assert (not (string<? "stringify" "string")))
|
92
|
+
(assert (not (string<? "badger" "badger")))
|
93
|
+
(assert (not (string<? "badges" "badger")))
|
94
|
+
|
95
|
+
(assert (not (string>? "abacus" "badger")))
|
96
|
+
(assert (not (string>? "badger" "badges")))
|
97
|
+
(assert (not (string>? "string" "stringify")))
|
98
|
+
(assert (string>? "stringify" "string"))
|
99
|
+
(assert (not (string>? "badger" "badger")))
|
100
|
+
(assert (string>? "badges" "badger"))
|
101
|
+
|
102
|
+
(assert (string<=? "foo" "foo"))
|
103
|
+
(assert (string<=? "foo" "goo"))
|
104
|
+
(assert (string<=? "Foo" "foo"))
|
105
|
+
(assert (not (string<=? "foo" "Foo")))
|
106
|
+
|
107
|
+
(assert (string-ci<=? "foo" "Foo"))
|
108
|
+
(assert (not (string-ci>=? "abacus" "Badger")))
|
109
|
+
(assert (string>? "abacus" "Badger"))
|
110
|
+
|
data/test/test_heist.rb
CHANGED
data/test/vectors.scm
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
(assert (equal? #() #()))
|
2
|
+
(assert (equal? #(1 8 7) #(1 8 7)))
|
3
|
+
(assert (equal? #(1 (2 3) 7) #(1 (2 3) 7)))
|
4
|
+
(assert (not (equal? #(1 (2 3) 7) #(1 (2 4) 7))))
|
5
|
+
|
6
|
+
(assert (vector? #(1 2 3)))
|
7
|
+
(assert (vector? #()))
|
8
|
+
(assert (vector? #((1 2 3))))
|
9
|
+
|
10
|
+
(for-each (lambda (predicate)
|
11
|
+
(assert (not (predicate #()))))
|
12
|
+
`(,pair? ,list? ,null?))
|
13
|
+
|
14
|
+
(assert (vector? (vector 1 3)))
|
15
|
+
(assert-equal #(1 4) (vector 1 4))
|
16
|
+
(assert (not (equal? #(2 4) (vector 2 4 5))))
|
17
|
+
|
18
|
+
(assert (not (equal? '(1 2) #[1 2])))
|
19
|
+
(assert (equal? '(1 2) (vector->list #(1 2))))
|
20
|
+
(assert (equal? (list->vector '(1 2)) #(1 2)))
|
21
|
+
|
22
|
+
(assert-equal #(() () ()) (make-vector 3))
|
23
|
+
(assert-equal #(foo foo foo foo) (make-vector 4 'foo))
|
24
|
+
|
25
|
+
(assert-equal 0 (vector-length #()))
|
26
|
+
(assert-equal 3 (vector-length #(1 8 9)))
|
27
|
+
|
28
|
+
(assert-equal 8 (vector-ref '#(1 1 2 3 5 8 13 21) 5))
|
29
|
+
|
30
|
+
(assert-equal 13 (vector-ref '#[1 1 2 3 5 8 13 21]
|
31
|
+
(round (* 2 (acos -1)))))
|
32
|
+
|
33
|
+
(assert-equal #(0 ("Sue" "Sue") "Anna") (let ((vec (vector 0 '(2 2 2 2) "Anna")))
|
34
|
+
(vector-set! vec 1 '("Sue" "Sue"))
|
35
|
+
vec))
|
36
|
+
|
37
|
+
(assert-raise ImmutableError (vector-set! '#(0 1 2) 1 "doe"))
|
38
|
+
(assert-equal #(0 "doe" 2) (let ([v #(0 1 2)])
|
39
|
+
(vector-set! v 1 "doe")
|
40
|
+
v))
|
41
|
+
|
42
|
+
(assert-equal #(23 23 23) (let ([v (vector 1 2 3)])
|
43
|
+
(vector-fill! v 23)
|
44
|
+
v))
|
45
|
+
|
46
|
+
(define (create-unquoted-vector)
|
47
|
+
#(1 2 3))
|
48
|
+
|
49
|
+
(let ([a (create-unquoted-vector)])
|
50
|
+
(vector-set! a 1 7)
|
51
|
+
(assert-equal #(1 2 3) (create-unquoted-vector))
|
52
|
+
(assert-equal '#(1 7 3) a))
|
53
|
+
|
54
|
+
(define (create-quoted-vector)
|
55
|
+
'#(1 2 3))
|
56
|
+
|
57
|
+
(let ([a (create-quoted-vector)])
|
58
|
+
(assert-raise ImmutableError (vector-set! a 1 7)))
|
59
|
+
|
60
|
+
(define-syntax vector-mac (syntax-rules ()
|
61
|
+
((_ #(a (b c) d ...))
|
62
|
+
c)
|
63
|
+
((_ #(a b c))
|
64
|
+
a)))
|
65
|
+
|
66
|
+
(assert-equal 3 (vector-mac #(3 8 7)))
|
67
|
+
(assert-raise SyntaxError (vector-mac #(1 2)))
|
68
|
+
(assert-raise SyntaxError (vector-mac #(1 2 3 4)))
|
69
|
+
(assert-raise SyntaxError (vector-mac (1 2 3)))
|
70
|
+
|
71
|
+
(assert-equal 5 (vector-mac #(3 (4 5))))
|
72
|
+
(assert-equal 5 (vector-mac #(3 (4 5) 6)))
|
73
|
+
(assert-equal 3 (vector-mac #(3 #(4 5) 6)))
|
74
|
+
|
75
|
+
(assert-equal #(1 2 3) '#(1 2 3))
|
76
|
+
(assert-equal #(1 2 3) `#(1 2 3))
|
77
|
+
(assert-equal #(1 (* 7 4) 3) `#(1 (* 7 4) 3))
|
78
|
+
(assert-equal #(1 28 3) `#(1 ,(* 7 4) 3))
|
79
|
+
(assert-equal #(1 28 9 5) `#(1 ,(* 7 4) ,@'(9 5)))
|
80
|
+
(assert-equal #(1 28 9 5 8) `#(1 ,(* 7 4) ,@'(9 5) 8))
|
81
|
+
(assert-equal #(9 5 8) `#(,@'(9 5) 8))
|
82
|
+
(assert-equal #((9 5) 8) `#(,'(9 5) 8))
|
83
|
+
|