rus3 0.1.2 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -1
- data/Gemfile.lock +1 -1
- data/README.md +14 -6
- data/exe/rus3 +26 -2
- data/lib/rus3.rb +3 -0
- data/lib/rus3/ast.rb +70 -0
- data/lib/rus3/ast/branch_node.rb +412 -0
- data/lib/rus3/ast/error.rb +8 -0
- data/lib/rus3/ast/leaf_node.rb +55 -0
- data/lib/rus3/error.rb +15 -1
- data/lib/rus3/evaluator.rb +38 -54
- data/lib/rus3/evaluator/environment.rb +25 -0
- data/lib/rus3/evaluator/scheme_evaluator.rb +79 -0
- data/lib/rus3/evaluator/translator.rb +337 -0
- data/lib/rus3/{parser/lexer.rb → lexer.rb} +22 -52
- data/lib/rus3/parser.rb +39 -23
- data/lib/rus3/parser/scheme_parser.rb +595 -306
- data/lib/rus3/procedure/char.rb +21 -17
- data/lib/rus3/procedure/control.rb +28 -24
- data/lib/rus3/procedure/list.rb +210 -207
- data/lib/rus3/procedure/predicate.rb +267 -264
- data/lib/rus3/procedure/utils.rb +20 -16
- data/lib/rus3/procedure/vector.rb +68 -65
- data/lib/rus3/procedure/write.rb +107 -103
- data/lib/rus3/repl.rb +57 -47
- data/lib/rus3/token.rb +35 -0
- data/lib/rus3/version.rb +2 -2
- metadata +11 -3
data/lib/rus3/procedure/char.rb
CHANGED
@@ -1,30 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rus3
|
4
|
-
module
|
3
|
+
module Rus3
|
4
|
+
module Procedure
|
5
5
|
|
6
|
-
|
6
|
+
module Char
|
7
7
|
|
8
|
-
|
9
|
-
Rus3::Char.char_to_integer(char)
|
10
|
-
end
|
8
|
+
# - procedure (R5RS): (char->integer char)
|
11
9
|
|
12
|
-
|
10
|
+
def char_to_integer(char)
|
11
|
+
Rus3::Char.char_to_integer(char)
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
Rus3::Char.integer_to_char(n)
|
16
|
-
end
|
14
|
+
# - procedure (R5RS): (integer->char n)
|
17
15
|
|
18
|
-
|
16
|
+
def integer_to_char(n)
|
17
|
+
Rus3::Char.integer_to_char(n)
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
# - library procedure (R5RS): (char-upcase char)
|
21
|
+
|
22
|
+
def char_upcase(char)
|
23
|
+
Rus3::Char.upcase(char)
|
24
|
+
end
|
25
|
+
|
26
|
+
# - library procedure (R5RS): (char-downcase char)
|
23
27
|
|
24
|
-
|
28
|
+
def char_downcase(char)
|
29
|
+
Rus3::Char.downcase(char)
|
30
|
+
end
|
25
31
|
|
26
|
-
def char_downcase(char)
|
27
|
-
Rus3::Char.downcase(char)
|
28
32
|
end
|
29
33
|
|
30
34
|
end
|
@@ -1,34 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rus3
|
4
|
-
module
|
3
|
+
module Rus3
|
4
|
+
module Procedure
|
5
5
|
|
6
|
-
|
7
|
-
include Rus3::EmptyList
|
6
|
+
module Control
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
include Predicate
|
9
|
+
include Rus3::EmptyList
|
10
|
+
|
11
|
+
def map(prc, *lists)
|
12
|
+
case lists.size
|
13
|
+
when 0
|
14
|
+
EMPTY_LIST
|
15
|
+
when 1
|
16
|
+
raise Rus3::ListRequiredError, lists[0] unless list?(lists[0])
|
17
|
+
lists[0].map(&prc)
|
18
|
+
else
|
19
|
+
zip(*lists).map {|args|
|
20
|
+
prc.call(*args)
|
21
|
+
}
|
22
|
+
end
|
20
23
|
end
|
21
|
-
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
def zip(*lists)
|
26
|
+
case lists.size
|
27
|
+
when 0
|
28
|
+
EMPTY_LIST
|
29
|
+
when 1
|
30
|
+
lists[0]
|
31
|
+
else
|
32
|
+
lists[0].zip(*lists[1..-1])
|
33
|
+
end
|
31
34
|
end
|
35
|
+
|
32
36
|
end
|
33
37
|
|
34
38
|
end
|
data/lib/rus3/procedure/list.rb
CHANGED
@@ -1,272 +1,275 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rus3
|
3
|
+
module Rus3
|
4
|
+
module Procedure
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
# - R5RS 6.3.2 Pairs and lists
|
10
|
-
# - R7RS 6.4 Pairs and lists
|
11
|
-
|
12
|
-
module List
|
13
|
-
|
14
|
-
include Utils
|
15
|
-
include Predicate
|
16
|
-
include Rus3::EmptyList
|
17
|
-
|
18
|
-
# Constructs a Pair object with arguments.
|
6
|
+
# The module holds list operation proceduress of Scheme. Most of
|
7
|
+
# those procedures are defined in R(n)RS (the specification of
|
8
|
+
# Scheme language).
|
19
9
|
#
|
20
|
-
# -
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
10
|
+
# - R5RS 6.3.2 Pairs and lists
|
11
|
+
# - R7RS 6.4 Pairs and lists
|
12
|
+
|
13
|
+
module List
|
14
|
+
|
15
|
+
include Utils
|
16
|
+
include Predicate
|
17
|
+
include Rus3::EmptyList
|
18
|
+
|
19
|
+
# Constructs a Pair object with arguments.
|
20
|
+
#
|
21
|
+
# - procedure (R5RS): (cons obj1 obj2)
|
22
|
+
|
23
|
+
def cons(obj1, obj2)
|
24
|
+
case obj2
|
25
|
+
when Rus3::Pair
|
26
|
+
if null?(obj2.cdr) # (foo . ())
|
27
|
+
[obj1, obj2.car]
|
28
|
+
else
|
29
|
+
Rus3::Pair.new(obj1, obj2)
|
30
|
+
end
|
31
|
+
when Array
|
32
|
+
[obj1].concat(obj2)
|
27
33
|
else
|
28
34
|
Rus3::Pair.new(obj1, obj2)
|
29
35
|
end
|
30
|
-
when Array
|
31
|
-
[obj1].concat(obj2)
|
32
|
-
else
|
33
|
-
Rus3::Pair.new(obj1, obj2)
|
34
36
|
end
|
35
|
-
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def car(pair)
|
43
|
-
case pair
|
44
|
-
when Rus3::Pair
|
45
|
-
pair.car
|
46
|
-
when Array
|
47
|
-
raise Rus3::PairOrListRequiredError, pair if pair.empty?
|
48
|
-
pair[0]
|
49
|
-
else
|
50
|
-
raise Rus3::PairOrListRequiredError, pair
|
51
|
-
end
|
52
|
-
end
|
38
|
+
# Returns the CAR part of the argument. If the arguemnt is not
|
39
|
+
# a pair, raises PairRequiredError.
|
40
|
+
#
|
41
|
+
# - procedure (R5RS): (car pair)
|
53
42
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
raise Rus3::PairOrListRequiredError, pair if pair.empty?
|
65
|
-
pair[1..-1]
|
66
|
-
else
|
67
|
-
raise Rus3::PairOrListRequiredError, pair
|
43
|
+
def car(pair)
|
44
|
+
case pair
|
45
|
+
when Rus3::Pair
|
46
|
+
pair.car
|
47
|
+
when Array
|
48
|
+
raise Rus3::PairOrListRequiredError, pair if pair.empty?
|
49
|
+
pair[0]
|
50
|
+
else
|
51
|
+
raise Rus3::PairOrListRequiredError, pair
|
52
|
+
end
|
68
53
|
end
|
69
|
-
end
|
70
54
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
55
|
+
# Returns the CDR part of the argument. If the arguemnt is not
|
56
|
+
# a pair, raises PairRequiredError.
|
57
|
+
#
|
58
|
+
# - procedure (R5RS): (cdr pair)
|
59
|
+
|
60
|
+
def cdr(pair)
|
61
|
+
case pair
|
62
|
+
when Rus3::Pair
|
63
|
+
pair.cdr
|
64
|
+
when Array
|
65
|
+
raise Rus3::PairOrListRequiredError, pair if pair.empty?
|
66
|
+
pair[1..-1]
|
67
|
+
else
|
68
|
+
raise Rus3::PairOrListRequiredError, pair
|
69
|
+
end
|
84
70
|
end
|
85
|
-
Rus3::UNDEF
|
86
|
-
end
|
87
71
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
when Array
|
98
|
-
case obj
|
72
|
+
# Replaces the CAR part with the 2nd argument and returns UNDEF.
|
73
|
+
# If the 1st arguemnt is not a pair, raises PairRequiredError.
|
74
|
+
#
|
75
|
+
# - procedure (R5RS): (set-car! pair obj)
|
76
|
+
|
77
|
+
def set_car!(pair, obj)
|
78
|
+
case pair
|
79
|
+
when Rus3::Pair
|
80
|
+
pair.set_car!(obj)
|
99
81
|
when Array
|
100
|
-
pair
|
101
|
-
pair.concat(obj)
|
82
|
+
pair[0] = obj
|
102
83
|
else
|
103
|
-
|
104
|
-
# `set_cdr!` would be a Pair instance. However, in this
|
105
|
-
# case, the given `pair` is an Array instance, there is no
|
106
|
-
# way to replace it with a new Pair instance.
|
107
|
-
raise UnsupportedFeatureError.new("set_cdr!", obj)
|
84
|
+
raise Rus3::PairOrListRequiredError, pair
|
108
85
|
end
|
109
|
-
|
110
|
-
raise Rus3::PairOrListRequiredError, pair
|
86
|
+
Rus3::UNDEF
|
111
87
|
end
|
112
|
-
Rus3::UNDEF
|
113
|
-
end
|
114
88
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
89
|
+
# Replaces the CDR part with the 2nd argument and returns UNDEF.
|
90
|
+
# If the 1st arguemnt is not a pair, raises PairRequiredError.
|
91
|
+
#
|
92
|
+
# - procedure (R5RS): (set-cdr! pair obj)
|
119
93
|
|
120
|
-
|
121
|
-
|
122
|
-
|
94
|
+
def set_cdr!(pair, obj)
|
95
|
+
case pair
|
96
|
+
when Rus3::Pair
|
97
|
+
pair.set_cdr!(obj)
|
98
|
+
when Array
|
99
|
+
case obj
|
100
|
+
when Array
|
101
|
+
pair.slice!(1, pair.size - 1)
|
102
|
+
pair.concat(obj)
|
103
|
+
else
|
104
|
+
# If `obj` was not a proper list of Scheme, the result of
|
105
|
+
# `set_cdr!` would be a Pair instance. However, in this
|
106
|
+
# case, the given `pair` is an Array instance, there is no
|
107
|
+
# way to replace it with a new Pair instance.
|
108
|
+
raise UnsupportedFeatureError.new("set_cdr!", obj)
|
109
|
+
end
|
110
|
+
else
|
111
|
+
raise Rus3::PairOrListRequiredError, pair
|
112
|
+
end
|
113
|
+
Rus3::UNDEF
|
114
|
+
end
|
123
115
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
116
|
+
# Retrieves the CAR part of the CAR part of the given pair.
|
117
|
+
#
|
118
|
+
# - library procedure (R5RS): (caar pair)
|
119
|
+
# - procedure (R7RS): (caar pair)
|
128
120
|
|
129
|
-
|
130
|
-
|
131
|
-
|
121
|
+
def caar(pair)
|
122
|
+
car(car(pair))
|
123
|
+
end
|
132
124
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
125
|
+
# Retrieves the CAR part of the CDR part of the given pair.
|
126
|
+
#
|
127
|
+
# - library procedure (R5RS): (cadr pair)
|
128
|
+
# - procedure (R7RS): (cadr pair)
|
137
129
|
|
138
|
-
|
139
|
-
|
140
|
-
|
130
|
+
def cadr(pair)
|
131
|
+
car(cdr(pair))
|
132
|
+
end
|
141
133
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
134
|
+
# Retrieves the CDR part of the CAR part of the given pair.
|
135
|
+
#
|
136
|
+
# - library procedure (R5RS): (cdar pair)
|
137
|
+
# - procedure (R7RS): (cdar pair)
|
146
138
|
|
147
|
-
|
148
|
-
|
149
|
-
|
139
|
+
def cdar(pair)
|
140
|
+
cdr(car(pair))
|
141
|
+
end
|
150
142
|
|
151
|
-
|
143
|
+
# Retrieves the CDR part of the CDR part of the given pair.
|
144
|
+
#
|
145
|
+
# - libbrary procedure (R5RS): (cddr pair)
|
146
|
+
# - procedure (R7RS): (cddr pair)
|
152
147
|
|
153
|
-
|
154
|
-
|
148
|
+
def cddr(pair)
|
149
|
+
cdr(cdr(pair))
|
150
|
+
end
|
155
151
|
|
156
|
-
|
152
|
+
# :stopdoc:
|
157
153
|
|
158
|
-
|
159
|
-
|
160
|
-
# - library procedure (R5RS): (list obj ...)
|
154
|
+
# - procedure (R7RS): (make-list k)
|
155
|
+
# - procedure (R7RS): (make-list k fill)
|
161
156
|
|
162
|
-
|
163
|
-
Array[*objs]
|
164
|
-
end
|
157
|
+
# :startdoc:
|
165
158
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
# - library procedure (R5RS): (length list)
|
170
|
-
# - procedure (R7RS): (length list)
|
159
|
+
# Constructs a list from arguments in its order.
|
160
|
+
#
|
161
|
+
# - library procedure (R5RS): (list obj ...)
|
171
162
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
end
|
163
|
+
def list(*objs)
|
164
|
+
Array[*objs]
|
165
|
+
end
|
176
166
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
167
|
+
# Returns the length of the arguemnt. If the argument is not a
|
168
|
+
# proper list, raises ListRequiredError.
|
169
|
+
#
|
170
|
+
# - library procedure (R5RS): (length list)
|
171
|
+
# - procedure (R7RS): (length list)
|
182
172
|
|
183
|
-
|
184
|
-
lists.each { |lst|
|
173
|
+
def length(lst)
|
185
174
|
check_list(lst)
|
186
|
-
|
187
|
-
|
188
|
-
end
|
175
|
+
lst.size
|
176
|
+
end
|
189
177
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
178
|
+
# Concatenates given lists into a single list. Each argument
|
179
|
+
# must be a proper list, otherwise raises ListRequiredError.
|
180
|
+
#
|
181
|
+
# - library procedure (R5RS): (append list ...)
|
182
|
+
# - procedure (R7RS): (append list ...)
|
183
|
+
|
184
|
+
def append(*lists)
|
185
|
+
lists.each { |lst|
|
186
|
+
check_list(lst)
|
187
|
+
}
|
188
|
+
[].concat(*lists)
|
189
|
+
end
|
194
190
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
191
|
+
# Returns a list of the same elements in reverse order.
|
192
|
+
#
|
193
|
+
# - library procedure (R5RS): (reverse list)
|
194
|
+
# - procedure (R7RS): (reverse list)
|
199
195
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
# This implementation logic comes from R5RS 6.3.2.
|
205
|
-
#
|
206
|
-
# - library procedure (R5RS): (list-tail list k)
|
207
|
-
# - procedure (R7RS): (list-tail list k)
|
196
|
+
def reverse(lst)
|
197
|
+
check_list(lst)
|
198
|
+
lst.sort {|a, b| b <=> a}
|
199
|
+
end
|
208
200
|
|
209
|
-
|
210
|
-
|
211
|
-
|
201
|
+
# Returns the sublist of the arguemnt by omitting the first k
|
202
|
+
# elements. The 2nd argument, k must be in 0..length(lst),
|
203
|
+
# otherwise raises ExceedUppeerLimitError.
|
204
|
+
#
|
205
|
+
# This implementation logic comes from R5RS 6.3.2.
|
206
|
+
#
|
207
|
+
# - library procedure (R5RS): (list-tail list k)
|
208
|
+
# - procedure (R7RS): (list-tail list k)
|
212
209
|
|
213
|
-
lst
|
214
|
-
|
210
|
+
def list_tail(lst, k)
|
211
|
+
check_list(lst)
|
212
|
+
check_upper_limit(k, length(lst)+1)
|
215
213
|
|
216
|
-
|
217
|
-
|
218
|
-
#
|
219
|
-
# - library procedure (R5RS): (list-ref list k)
|
220
|
-
# - procedure (R7RS): (list-ref list k)
|
214
|
+
lst.drop(k)
|
215
|
+
end
|
221
216
|
|
222
|
-
|
223
|
-
|
224
|
-
|
217
|
+
# Returns kth element of the argument. k must be less than the
|
218
|
+
# length of the list, otherwise, raises ExceedUppeerLimitError.
|
219
|
+
#
|
220
|
+
# - library procedure (R5RS): (list-ref list k)
|
221
|
+
# - procedure (R7RS): (list-ref list k)
|
225
222
|
|
226
|
-
lst
|
227
|
-
|
223
|
+
def list_ref(lst, k)
|
224
|
+
check_list(lst)
|
225
|
+
check_upper_limit(k, length(lst))
|
228
226
|
|
229
|
-
|
227
|
+
lst[k]
|
228
|
+
end
|
229
|
+
|
230
|
+
# :stopdoc:
|
230
231
|
|
231
|
-
|
232
|
+
# - procedure (R7RS): (list-set! list k obj)
|
232
233
|
|
233
|
-
|
234
|
+
# :startdoc:
|
234
235
|
|
235
|
-
|
236
|
+
# :stopdpc:
|
236
237
|
|
237
|
-
|
238
|
-
|
238
|
+
# - library procedure (R5RS): (memq obj list)
|
239
|
+
# - procedure (R7RS): (memq obj list)
|
239
240
|
|
240
|
-
|
241
|
-
|
241
|
+
# - library procedure (R5RS): (memv obj list)
|
242
|
+
# - procedure (R7RS): (memv obj list)
|
242
243
|
|
243
|
-
|
244
|
-
|
244
|
+
# - library procedure (R5RS): (member obj list)
|
245
|
+
# - procedure (R7RS): (member obj list)
|
245
246
|
|
246
|
-
|
247
|
+
# - procedure (R7RS): (member obj list compare)
|
247
248
|
|
248
|
-
|
249
|
+
# :startdoc:
|
249
250
|
|
250
|
-
|
251
|
+
# :stopdpc:
|
251
252
|
|
252
|
-
|
253
|
-
|
253
|
+
# - library procedure (R5RS): (assq obj alist)
|
254
|
+
# - procedure (R7RS): (assq obj alist)
|
254
255
|
|
255
|
-
|
256
|
-
|
256
|
+
# - library procedure (R5RS): (assv obj alist)
|
257
|
+
# - procedure (R7RS): (assv obj alist)
|
257
258
|
|
258
|
-
|
259
|
-
|
259
|
+
# - library procedure (R5RS): (assoc obj alist)
|
260
|
+
# - procedure (R7RS): (assoc obj alist)
|
260
261
|
|
261
|
-
|
262
|
+
# - procedure (R7RS): (assoc obj alist compare)
|
262
263
|
|
263
|
-
|
264
|
+
# :startdoc:
|
264
265
|
|
265
|
-
|
266
|
+
# :stopdoc:
|
266
267
|
|
267
|
-
|
268
|
+
# - procedure (R7RS): (list-copy obj)
|
268
269
|
|
269
|
-
|
270
|
+
# :startdoc:
|
271
|
+
|
272
|
+
end
|
270
273
|
|
271
274
|
end
|
272
275
|
end
|