rus3 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -3
- data/Gemfile.lock +1 -1
- data/README.md +8 -2
- data/exe/rus3 +14 -1
- data/lib/rus3.rb +3 -0
- data/lib/rus3/error.rb +17 -1
- data/lib/rus3/evaluator.rb +1 -0
- data/lib/rus3/parser/lexer.rb +6 -3
- data/lib/rus3/parser/scheme_parser.rb +45 -10
- data/lib/rus3/procedure/list.rb +45 -62
- data/lib/rus3/procedure/predicate.rb +6 -5
- data/lib/rus3/procedure/utils.rb +28 -0
- data/lib/rus3/procedure/vector.rb +98 -0
- data/lib/rus3/repl.rb +3 -1
- data/lib/rus3/vector.rb +57 -0
- data/lib/rus3/version.rb +2 -1
- data/rus3.gemspec +1 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfda189d1f2499f00d441efe70f0e8db49ecc443a8c414ec7b4f9282caf28fe2
|
4
|
+
data.tar.gz: 1a0c858ec768aec68e79b66815fd8b5cdd2c6eef2f4e688e55f90fbcd1fde558
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb42c290cdcea8dacd9ae0b024ce0c2b266ae912ddc4178c40c5134fda5a79507d420ab959fc10a9860dd8bf3d805e16347a9cd791c4e90ddffaf1e7afd29932
|
7
|
+
data.tar.gz: 16450eb77a484889dc5572a62fd48670b278fac5f4845111d6b192dbf8820bac54854a150a628004b9461b995a166f1957876d72636b732b11cf7c6db3dbc6c6
|
data/CHANGELOG.md
CHANGED
@@ -5,9 +5,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
|
-
-
|
9
|
-
|
10
|
-
|
8
|
+
- (nothing to record)
|
9
|
+
|
10
|
+
## [0.1.1] - 2021-04-22
|
11
|
+
### Added
|
12
|
+
- Add `vector`:
|
13
|
+
- add Rus3::Vector class,
|
14
|
+
- modify Rus3::Parser::Lexer to accept a vector literal,
|
15
|
+
- modify Rus3::Parser::SchemeParser to parse and translate a vector
|
16
|
+
literal,
|
17
|
+
- Add new error classes (VectorRequiredError and ExceedUpperLimitError),
|
18
|
+
- Add tests around `vector`.
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
- Modify Rus3::Parser::Lexer to convert "->" to "_to_",
|
22
|
+
- now, the Scheme identifier such "list->vector" is usable in the
|
23
|
+
REPL
|
11
24
|
|
12
25
|
## [0.1.0] - 2021-04-21
|
13
26
|
- Initial release:
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -52,6 +52,8 @@ Rus3(scheme)> 1/9
|
|
52
52
|
==> (1/9)
|
53
53
|
Rus3(scheme)> 3+4i
|
54
54
|
==> (3+4i)
|
55
|
+
Rus3(scheme)> #(1 2 3)
|
56
|
+
==> #<Rus3::Vector:0x00007facf12d9fb0 @content=[1, 2, 3]>
|
55
57
|
```
|
56
58
|
|
57
59
|
### Procedure call
|
@@ -115,8 +117,8 @@ Following procedures described in the spec is available.
|
|
115
117
|
- Predicates:
|
116
118
|
- null?, list?
|
117
119
|
- eqv?, eq?
|
118
|
-
- boolean?, pair?, symbol?, number?, string?
|
119
|
-
- char
|
120
|
+
- boolean?, pair?, symbol?, number?, string?, vector?
|
121
|
+
- char? and port? are defined but it always returns `false`.
|
120
122
|
- complex?, real?, rational?, integer?
|
121
123
|
- zero?, positive?, negative?, odd?, even?
|
122
124
|
- string-eq?, string-ci-eq?, string-lt?, string-gt?, string-le?,
|
@@ -128,6 +130,10 @@ Following procedures described in the spec is available.
|
|
128
130
|
- cons, car, cdr, set-car!, set-cdr!, cxxr (caar and so on)
|
129
131
|
- list, length, append, reverse, list-tail, list-ref
|
130
132
|
|
133
|
+
- Vector operations
|
134
|
+
- make-vector, vector, vector-length, vector-ref, vector-set!,
|
135
|
+
vector->list, list->vector, vector-fill!
|
136
|
+
|
131
137
|
- Write values
|
132
138
|
- write
|
133
139
|
- display
|
data/exe/rus3
CHANGED
@@ -2,4 +2,17 @@
|
|
2
2
|
|
3
3
|
require "rus3"
|
4
4
|
|
5
|
-
|
5
|
+
opts = {}
|
6
|
+
|
7
|
+
while ARGV.size > 0
|
8
|
+
arg = ARGV.shift
|
9
|
+
case arg
|
10
|
+
when "-d", "--debug"
|
11
|
+
opts[:debug] = true
|
12
|
+
when "-v", "--version"
|
13
|
+
puts "rus3 version #{Rus3::VERSION} (#{Rus3::RELEASE})"
|
14
|
+
exit 0
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Rus3::Repl.start(verbose: opts[:debug])
|
data/lib/rus3.rb
CHANGED
@@ -39,9 +39,12 @@ module Rus3
|
|
39
39
|
require_relative "rus3/pair"
|
40
40
|
require_relative "rus3/char"
|
41
41
|
require_relative "rus3/port"
|
42
|
+
require_relative "rus3/vector"
|
42
43
|
|
44
|
+
require_relative "rus3/procedure/utils"
|
43
45
|
require_relative "rus3/procedure/predicate"
|
44
46
|
require_relative "rus3/procedure/list"
|
47
|
+
require_relative "rus3/procedure/vector"
|
45
48
|
require_relative "rus3/procedure/control"
|
46
49
|
require_relative "rus3/procedure/write"
|
47
50
|
|
data/lib/rus3/error.rb
CHANGED
@@ -11,12 +11,14 @@ module Rus3
|
|
11
11
|
"()"
|
12
12
|
else # a normal proper list
|
13
13
|
list_notation = obj.to_s().gsub(/[\[\],]/, A2L_MAP)
|
14
|
-
"list( %s )" %
|
14
|
+
"list( %s )" % list_notation
|
15
15
|
end
|
16
16
|
when Numeric
|
17
17
|
"number(%d)" % obj
|
18
18
|
when Rus3::Pair
|
19
19
|
"pair(%s)" % obj
|
20
|
+
when Rus3::Vector
|
21
|
+
"vector(%s)" % obj
|
20
22
|
else
|
21
23
|
"%s(%s)" % [obj.class, obj]
|
22
24
|
end
|
@@ -31,7 +33,9 @@ module Rus3
|
|
31
33
|
:pair_required => "pair required: got=%s",
|
32
34
|
:list_required => "proper list required: got=%s",
|
33
35
|
:pair_or_list_required => "pair or proper list required: got=%s",
|
36
|
+
:vector_required => "vector required: got=%s",
|
34
37
|
:out_of_range => "argument out of range: got=%s",
|
38
|
+
:exceed_upper_limit => "argument exceeds its upper limit (%d): got=%d",
|
35
39
|
:unsupported_method => "specified method does not work now.",
|
36
40
|
:wrong_type => "wrong type argument: got=%s, wants=%s",
|
37
41
|
:integer_required => "integer required: got=%s",
|
@@ -63,12 +67,24 @@ module Rus3
|
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
70
|
+
class VectorRequiredError < Error
|
71
|
+
def initialize(obj)
|
72
|
+
super(EMSG[:vector_required] % smart_error_value(obj))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
66
76
|
class OutOfRangeError < Error
|
67
77
|
def initialize(obj)
|
68
78
|
super(EMSG[:out_of_range] % smart_error_value(obj))
|
69
79
|
end
|
70
80
|
end
|
71
81
|
|
82
|
+
class ExceedUpperLimitError < Error
|
83
|
+
def initialize(value, limit)
|
84
|
+
super(EMSG[:exceed_upper_limit] % [limit, value])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
72
88
|
class UnsupportedMethodError < Error
|
73
89
|
def initialize
|
74
90
|
super(EMSG[:unsupported_method])
|
data/lib/rus3/evaluator.rb
CHANGED
data/lib/rus3/parser/lexer.rb
CHANGED
@@ -5,7 +5,7 @@ module Rus3::Parser
|
|
5
5
|
class Lexer < Enumerator
|
6
6
|
|
7
7
|
# Indicates the version of the lexer class
|
8
|
-
LEXER_VERSION = "0.1.
|
8
|
+
LEXER_VERSION = "0.1.1"
|
9
9
|
|
10
10
|
# :stopdoc:
|
11
11
|
|
@@ -13,6 +13,7 @@ module Rus3::Parser
|
|
13
13
|
# delimiters
|
14
14
|
:lparen,
|
15
15
|
:rparen,
|
16
|
+
:vec_lparen,
|
16
17
|
# value types
|
17
18
|
:boolean,
|
18
19
|
:ident,
|
@@ -31,12 +32,12 @@ module Rus3::Parser
|
|
31
32
|
STRING = /\A\"[^\"]*\"\Z/
|
32
33
|
|
33
34
|
# idents
|
34
|
-
EXTENDED = "
|
35
|
+
EXTENDED = "\\->"
|
35
36
|
IDENT_PAT = "[a-zA-Z_][\\w?!#{EXTENDED}]*"
|
36
37
|
IDENTIFIER = Regexp.new("\\A#{IDENT_PAT}\\Z")
|
37
38
|
|
38
39
|
EXTENDED_REGEXP = Regexp.new("[#{EXTENDED}]")
|
39
|
-
EXTENDED_MAP = { "-" => "_", }
|
40
|
+
EXTENDED_MAP = { "-" => "_", ">" => "to_"}
|
40
41
|
|
41
42
|
# operators
|
42
43
|
ARITHMETIC_OPS = /\A[+\-*\/%]\Z/
|
@@ -90,6 +91,8 @@ module Rus3::Parser
|
|
90
91
|
Token.new(:lparen, literal)
|
91
92
|
when "]"
|
92
93
|
Token.new(:rparen, literal)
|
94
|
+
when "#["
|
95
|
+
Token.new(:vec_lparen, literal)
|
93
96
|
when BOOLEAN
|
94
97
|
Token.new(:boolean, literal)
|
95
98
|
when IDENTIFIER
|
@@ -6,7 +6,7 @@ module Rus3::Parser
|
|
6
6
|
class SchemeParser < Parser
|
7
7
|
|
8
8
|
# Indicates the version of the parser class
|
9
|
-
PARSER_VERSION = "0.1.
|
9
|
+
PARSER_VERSION = "0.1.1"
|
10
10
|
|
11
11
|
# Constructs the version string.
|
12
12
|
|
@@ -115,6 +115,10 @@ module Rus3::Parser
|
|
115
115
|
# ["mul", "x", "y"]] ... i_exp
|
116
116
|
# -> "lambda { |x, y| mul(x, y) }.call(2, 3)" ... r_exp
|
117
117
|
#
|
118
|
+
# - vector (s_exp -> r_exp)
|
119
|
+
# - #(1 2 #(3 4) 5)
|
120
|
+
# -> "vector(1, 2, vector(3, 4), 5)"
|
121
|
+
#
|
118
122
|
# - list (s_exp -> r_exp)
|
119
123
|
# - (1 2 3 (4 5) (6 7 8) 9 0)
|
120
124
|
# -> "[1, 2, 3, [4, 5], [6, 7, 8], 9, 0]"
|
@@ -125,18 +129,25 @@ module Rus3::Parser
|
|
125
129
|
|
126
130
|
def parse_tokens(lexer) # :nodoc:
|
127
131
|
r_exps = []
|
128
|
-
loop {
|
129
|
-
token = lexer.next
|
130
|
-
if token.type == :lparen
|
131
|
-
i_exp = parse_compound(lexer)
|
132
|
-
r_exps << translate(i_exp)
|
133
|
-
else
|
134
|
-
r_exps << parse_primitive(token)
|
135
|
-
end
|
136
|
-
}
|
132
|
+
loop { r_exps << parse_s_exp(lexer) }
|
137
133
|
r_exps.join("\n")
|
138
134
|
end
|
139
135
|
|
136
|
+
def parse_s_exp(lexer)
|
137
|
+
r_exp = nil
|
138
|
+
token = lexer.next
|
139
|
+
case token.type
|
140
|
+
when :lparen
|
141
|
+
i_exp = parse_compound(lexer)
|
142
|
+
r_exp = translate(i_exp)
|
143
|
+
when :vec_lparen
|
144
|
+
r_exp = parse_vector(lexer)
|
145
|
+
else
|
146
|
+
r_exp = parse_primitive(token)
|
147
|
+
end
|
148
|
+
r_exp
|
149
|
+
end
|
150
|
+
|
140
151
|
def parse_primitive(token)
|
141
152
|
r_exp = nil
|
142
153
|
case token.type
|
@@ -153,6 +164,30 @@ module Rus3::Parser
|
|
153
164
|
r_exp
|
154
165
|
end
|
155
166
|
|
167
|
+
def parse_vector(lexer)
|
168
|
+
r_exp = "vector("
|
169
|
+
Kernel.loop {
|
170
|
+
token = lexer.peek
|
171
|
+
case token.type
|
172
|
+
when :lparen
|
173
|
+
lexer.next
|
174
|
+
i_exp = parse_compound(lexer)
|
175
|
+
r_exp += translate(i_exp)
|
176
|
+
when :vec_lparen
|
177
|
+
lexer.next
|
178
|
+
r_exp += parse_vector(lexer)
|
179
|
+
when :rparen
|
180
|
+
lexer.next
|
181
|
+
r_exp = r_exp.sub(/,\s*\Z/, "") + ")"
|
182
|
+
break
|
183
|
+
else
|
184
|
+
r_exp += parse_s_exp(lexer)
|
185
|
+
end
|
186
|
+
r_exp += ", "
|
187
|
+
}
|
188
|
+
r_exp
|
189
|
+
end
|
190
|
+
|
156
191
|
def parse_compound(lexer)
|
157
192
|
i_exp = []
|
158
193
|
Kernel.loop {
|
data/lib/rus3/procedure/list.rb
CHANGED
@@ -11,12 +11,13 @@ module Rus3::Procedure
|
|
11
11
|
|
12
12
|
module List
|
13
13
|
|
14
|
+
include Utils
|
14
15
|
include Predicate
|
15
16
|
include Rus3::EmptyList
|
16
17
|
|
17
18
|
# Constructs a Pair object with arguments.
|
18
19
|
#
|
19
|
-
# - R5RS
|
20
|
+
# - procedure (R5RS): (cons obj1 obj2)
|
20
21
|
|
21
22
|
def cons(obj1, obj2)
|
22
23
|
case obj2
|
@@ -36,7 +37,7 @@ module Rus3::Procedure
|
|
36
37
|
# Returns the CAR part of the argument. If the arguemnt is not
|
37
38
|
# a pair, raises PairRequiredError.
|
38
39
|
#
|
39
|
-
# - R5RS
|
40
|
+
# - procedure (R5RS): (car pair)
|
40
41
|
|
41
42
|
def car(pair)
|
42
43
|
case pair
|
@@ -53,7 +54,7 @@ module Rus3::Procedure
|
|
53
54
|
# Returns the CDR part of the argument. If the arguemnt is not
|
54
55
|
# a pair, raises PairRequiredError.
|
55
56
|
#
|
56
|
-
# - R5RS
|
57
|
+
# - procedure (R5RS): (cdr pair)
|
57
58
|
|
58
59
|
def cdr(pair)
|
59
60
|
case pair
|
@@ -70,7 +71,7 @@ module Rus3::Procedure
|
|
70
71
|
# Replaces the CAR part with the 2nd argument and returns UNDEF.
|
71
72
|
# If the 1st arguemnt is not a pair, raises PairRequiredError.
|
72
73
|
#
|
73
|
-
# - R5RS
|
74
|
+
# - procedure (R5RS): (set-car! pair obj)
|
74
75
|
|
75
76
|
def set_car!(pair, obj)
|
76
77
|
case pair
|
@@ -87,7 +88,7 @@ module Rus3::Procedure
|
|
87
88
|
# Replaces the CDR part with the 2nd argument and returns UNDEF.
|
88
89
|
# If the 1st arguemnt is not a pair, raises PairRequiredError.
|
89
90
|
#
|
90
|
-
# - R5RS
|
91
|
+
# - procedure (R5RS): (set-cdr! pair obj)
|
91
92
|
|
92
93
|
def set_cdr!(pair, obj)
|
93
94
|
case pair
|
@@ -113,8 +114,8 @@ module Rus3::Procedure
|
|
113
114
|
|
114
115
|
# Retrieves the CAR part of the CAR part of the given pair.
|
115
116
|
#
|
116
|
-
# -
|
117
|
-
# - R7RS
|
117
|
+
# - library procedure (R5RS): (caar pair)
|
118
|
+
# - procedure (R7RS): (caar pair)
|
118
119
|
|
119
120
|
def caar(pair)
|
120
121
|
car(car(pair))
|
@@ -122,8 +123,8 @@ module Rus3::Procedure
|
|
122
123
|
|
123
124
|
# Retrieves the CAR part of the CDR part of the given pair.
|
124
125
|
#
|
125
|
-
# -
|
126
|
-
# - R7RS
|
126
|
+
# - library procedure (R5RS): (cadr pair)
|
127
|
+
# - procedure (R7RS): (cadr pair)
|
127
128
|
|
128
129
|
def cadr(pair)
|
129
130
|
car(cdr(pair))
|
@@ -131,8 +132,8 @@ module Rus3::Procedure
|
|
131
132
|
|
132
133
|
# Retrieves the CDR part of the CAR part of the given pair.
|
133
134
|
#
|
134
|
-
# -
|
135
|
-
# - R7RS
|
135
|
+
# - library procedure (R5RS): (cdar pair)
|
136
|
+
# - procedure (R7RS): (cdar pair)
|
136
137
|
|
137
138
|
def cdar(pair)
|
138
139
|
cdr(car(pair))
|
@@ -140,8 +141,8 @@ module Rus3::Procedure
|
|
140
141
|
|
141
142
|
# Retrieves the CDR part of the CDR part of the given pair.
|
142
143
|
#
|
143
|
-
# -
|
144
|
-
# - R7RS
|
144
|
+
# - libbrary procedure (R5RS): (cddr pair)
|
145
|
+
# - procedure (R7RS): (cddr pair)
|
145
146
|
|
146
147
|
def cddr(pair)
|
147
148
|
cdr(cdr(pair))
|
@@ -149,15 +150,14 @@ module Rus3::Procedure
|
|
149
150
|
|
150
151
|
# :stopdoc:
|
151
152
|
|
152
|
-
# - R7RS:
|
153
|
-
|
154
|
-
# - R7RS: procedure: (make-list k fill)
|
153
|
+
# - procedure (R7RS): (make-list k)
|
154
|
+
# - procedure (R7RS): (make-list k fill)
|
155
155
|
|
156
156
|
# :startdoc:
|
157
157
|
|
158
158
|
# Constructs a list from arguments in its order.
|
159
159
|
#
|
160
|
-
# -
|
160
|
+
# - library procedure (R5RS): (list obj ...)
|
161
161
|
|
162
162
|
def list(*objs)
|
163
163
|
Array[*objs]
|
@@ -166,8 +166,8 @@ module Rus3::Procedure
|
|
166
166
|
# Returns the length of the arguemnt. If the argument is not a
|
167
167
|
# proper list, raises ListRequiredError.
|
168
168
|
#
|
169
|
-
# -
|
170
|
-
# - R7RS
|
169
|
+
# - library procedure (R5RS): (length list)
|
170
|
+
# - procedure (R7RS): (length list)
|
171
171
|
|
172
172
|
def length(lst)
|
173
173
|
check_list(lst)
|
@@ -177,8 +177,8 @@ module Rus3::Procedure
|
|
177
177
|
# Concatenates given lists into a single list. Each argument
|
178
178
|
# must be a proper list, otherwise raises ListRequiredError.
|
179
179
|
#
|
180
|
-
# -
|
181
|
-
# - R7RS
|
180
|
+
# - library procedure (R5RS): (append list ...)
|
181
|
+
# - procedure (R7RS): (append list ...)
|
182
182
|
|
183
183
|
def append(*lists)
|
184
184
|
lists.each { |lst|
|
@@ -189,8 +189,8 @@ module Rus3::Procedure
|
|
189
189
|
|
190
190
|
# Returns a list of the same elements in reverse order.
|
191
191
|
#
|
192
|
-
# -
|
193
|
-
# - R7RS
|
192
|
+
# - library procedure (R5RS): (reverse list)
|
193
|
+
# - procedure (R7RS): (reverse list)
|
194
194
|
|
195
195
|
def reverse(lst)
|
196
196
|
check_list(lst)
|
@@ -199,12 +199,12 @@ module Rus3::Procedure
|
|
199
199
|
|
200
200
|
# Returns the sublist of the arguemnt by omitting the first k
|
201
201
|
# elements. The 2nd argument, k must be in 0..length(lst),
|
202
|
-
# otherwise raises
|
202
|
+
# otherwise raises ExceedUppeerLimitError.
|
203
203
|
#
|
204
204
|
# This implementation logic comes from R5RS 6.3.2.
|
205
205
|
#
|
206
|
-
# -
|
207
|
-
# - R7RS
|
206
|
+
# - library procedure (R5RS): (list-tail list k)
|
207
|
+
# - procedure (R7RS): (list-tail list k)
|
208
208
|
|
209
209
|
def list_tail(lst, k)
|
210
210
|
check_list(lst)
|
@@ -214,10 +214,10 @@ module Rus3::Procedure
|
|
214
214
|
end
|
215
215
|
|
216
216
|
# Returns kth element of the argument. k must be less than the
|
217
|
-
# length of the list, otherwise, raises
|
217
|
+
# length of the list, otherwise, raises ExceedUppeerLimitError.
|
218
218
|
#
|
219
|
-
# -
|
220
|
-
# - R7RS
|
219
|
+
# - library procedure (R5RS): (list-ref list k)
|
220
|
+
# - procedure (R7RS): (list-ref list k)
|
221
221
|
|
222
222
|
def list_ref(lst, k)
|
223
223
|
check_list(lst)
|
@@ -228,62 +228,45 @@ module Rus3::Procedure
|
|
228
228
|
|
229
229
|
# :stopdoc:
|
230
230
|
|
231
|
-
# - R7RS
|
231
|
+
# - procedure (R7RS): (list-set! list k obj)
|
232
232
|
|
233
233
|
# :startdoc:
|
234
234
|
|
235
235
|
# :stopdpc:
|
236
236
|
|
237
|
-
# -
|
238
|
-
# - R7RS
|
237
|
+
# - library procedure (R5RS): (memq obj list)
|
238
|
+
# - procedure (R7RS): (memq obj list)
|
239
239
|
|
240
|
-
# -
|
241
|
-
# - R7RS
|
240
|
+
# - library procedure (R5RS): (memv obj list)
|
241
|
+
# - procedure (R7RS): (memv obj list)
|
242
242
|
|
243
|
-
# -
|
244
|
-
# - R7RS
|
243
|
+
# - library procedure (R5RS): (member obj list)
|
244
|
+
# - procedure (R7RS): (member obj list)
|
245
245
|
|
246
|
-
# - R7RS
|
246
|
+
# - procedure (R7RS): (member obj list compare)
|
247
247
|
|
248
248
|
# :startdoc:
|
249
249
|
|
250
250
|
# :stopdpc:
|
251
251
|
|
252
|
-
# -
|
253
|
-
# - R7RS
|
252
|
+
# - library procedure (R5RS): (assq obj alist)
|
253
|
+
# - procedure (R7RS): (assq obj alist)
|
254
254
|
|
255
|
-
# -
|
256
|
-
# - R7RS
|
255
|
+
# - library procedure (R5RS): (assv obj alist)
|
256
|
+
# - procedure (R7RS): (assv obj alist)
|
257
257
|
|
258
|
-
# -
|
259
|
-
# - R7RS
|
258
|
+
# - library procedure (R5RS): (assoc obj alist)
|
259
|
+
# - procedure (R7RS): (assoc obj alist)
|
260
260
|
|
261
|
-
# - R7RS
|
261
|
+
# - procedure (R7RS): (assoc obj alist compare)
|
262
262
|
|
263
263
|
# :startdoc:
|
264
264
|
|
265
265
|
# :stopdoc:
|
266
266
|
|
267
|
-
# - R7RS
|
267
|
+
# - procedure (R7RS): (list-copy obj)
|
268
268
|
|
269
269
|
# :startdoc:
|
270
270
|
|
271
|
-
private
|
272
|
-
|
273
|
-
def check_pair(pair) # :nodoc:
|
274
|
-
if !pair.instance_of?(Rus3::Pair) and !pair.instance_of?(Array)
|
275
|
-
raise Rus3::PairRequiredError, pair
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
def check_list(lst) # :nodoc:
|
280
|
-
raise Rus3::ListRequiredError, lst unless list?(lst)
|
281
|
-
end
|
282
|
-
|
283
|
-
# To make sure the number is less than its upper limit.
|
284
|
-
def check_upper_limit(k, limit) # :nodoc:
|
285
|
-
raise Rus3::OutOfRangeError, k if k >= limit
|
286
|
-
end
|
287
|
-
|
288
271
|
end
|
289
272
|
end
|
@@ -44,12 +44,12 @@ module Rus3::Procedure
|
|
44
44
|
# provides some classes for the rest of them.
|
45
45
|
#
|
46
46
|
# boolean? ---> FalseClass or TrueClass
|
47
|
-
# pair? ------> Rus3::Pair
|
47
|
+
# pair? ------> Array (as a list) or Rus3::Pair (as a dotted pair)
|
48
48
|
# symbol? ----> Symbol
|
49
49
|
# number? ----> Numeric
|
50
50
|
# char? ------> Rus3::Char
|
51
51
|
# string? ----> String
|
52
|
-
# vector? ---->
|
52
|
+
# vector? ----> Rus3::Vector
|
53
53
|
# port? ------> Rus3::Port
|
54
54
|
# procedure? -> Proc
|
55
55
|
|
@@ -64,11 +64,11 @@ module Rus3::Procedure
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def symbol?(obj)
|
67
|
-
obj.
|
67
|
+
obj.instance_of?(Symbol) && obj != Rus3::UNDEF
|
68
68
|
end
|
69
69
|
|
70
70
|
def number?(obj)
|
71
|
-
obj.
|
71
|
+
obj.kind_of?(Numeric)
|
72
72
|
end
|
73
73
|
|
74
74
|
def char?(obj)
|
@@ -79,8 +79,9 @@ module Rus3::Procedure
|
|
79
79
|
obj.kind_of?(String)
|
80
80
|
end
|
81
81
|
|
82
|
+
# procedure (R5RS/R7RS): (vector? obj)
|
82
83
|
def vector?(obj)
|
83
|
-
|
84
|
+
obj.instance_of?(Rus3::Vector)
|
84
85
|
end
|
85
86
|
|
86
87
|
def port?(obj)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rus3::Procedure
|
4
|
+
module Utils
|
5
|
+
|
6
|
+
def check_pair(pair) # :nodoc:
|
7
|
+
if !pair.instance_of?(Rus3::Pair) and !pair.instance_of?(Array)
|
8
|
+
raise Rus3::PairRequiredError, pair
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_list(lst) # :nodoc:
|
13
|
+
raise Rus3::ListRequiredError, lst unless list?(lst)
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_vector(obj) # :nodoc:
|
17
|
+
raise Rus3::VectorRequiredError, obj unless vector?(obj)
|
18
|
+
end
|
19
|
+
|
20
|
+
# To make sure the number is less than its upper limit. When k
|
21
|
+
# greater than or equal to limit, raises ExceedUpperLimitError.
|
22
|
+
|
23
|
+
def check_upper_limit(k, limit)
|
24
|
+
raise Rus3::ExceedUpperLimitError.new(k, limit) if k >= limit
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rus3::Procedure
|
4
|
+
|
5
|
+
# Provides procedures to operate a vector.
|
6
|
+
|
7
|
+
module Vector
|
8
|
+
|
9
|
+
include Utils
|
10
|
+
include List
|
11
|
+
include Predicate
|
12
|
+
include Rus3::EmptyList
|
13
|
+
|
14
|
+
UNDEF = Rus3::UNDEF
|
15
|
+
|
16
|
+
# - procedure (R5RS/R7RS): (make-vector k) or (make-vector k fill)
|
17
|
+
|
18
|
+
def make_vector(k, fill = UNDEF)
|
19
|
+
Rus3::Vector.new(k, fill)
|
20
|
+
end
|
21
|
+
|
22
|
+
# - library procedure (R5RS/R7RS): (vector obj ...)
|
23
|
+
|
24
|
+
def vector(*objs)
|
25
|
+
Rus3::Vector.vector(*objs)
|
26
|
+
end
|
27
|
+
|
28
|
+
# - procedure (R5RS/R7RS): (vector-length vector)
|
29
|
+
|
30
|
+
def vector_length(vec)
|
31
|
+
check_vector(vec)
|
32
|
+
vec.length
|
33
|
+
end
|
34
|
+
|
35
|
+
# - procedure (R5RS/R7RS): (vector-ref vector, k)
|
36
|
+
|
37
|
+
def vector_ref(vec, k)
|
38
|
+
check_vector(vec)
|
39
|
+
check_upper_limit(k, vec.length)
|
40
|
+
vec.ref(k)
|
41
|
+
end
|
42
|
+
|
43
|
+
# - procedure (R5RS/R7RS): (vector-set! vector k obj)
|
44
|
+
|
45
|
+
def vector_set!(vec, k, obj)
|
46
|
+
check_vector(vec)
|
47
|
+
Rus3::Vector.vector_set!(vec, k, obj)
|
48
|
+
end
|
49
|
+
|
50
|
+
# - library procedure (R5RS): (vector->list vector)
|
51
|
+
# - procedure (R7RS):
|
52
|
+
# (vector->list vector)
|
53
|
+
# (vector->list vector start)
|
54
|
+
# (vector->list vector start end)
|
55
|
+
|
56
|
+
def vector_to_list(vec, start_index = 0, end_index = -1)
|
57
|
+
end_index = vec.length if end_index == -1
|
58
|
+
|
59
|
+
check_vector(vec)
|
60
|
+
check_limits(start_index, end_index, vec.length)
|
61
|
+
|
62
|
+
list(*vec.ref(start_index...end_index))
|
63
|
+
end
|
64
|
+
|
65
|
+
# - library procedure (R5RS): (list->vector list)
|
66
|
+
# - procedre (R7RS): (list->vector list)
|
67
|
+
|
68
|
+
def list_to_vector(lst)
|
69
|
+
Rus3::Vector.list_to_vector(lst)
|
70
|
+
end
|
71
|
+
|
72
|
+
# - library procedure (R5RS): (vector-fill! vector fill)
|
73
|
+
# - procedure (R7RS): (vector-fill! vector fill start end)
|
74
|
+
|
75
|
+
def vector_fill!(vec, fill, start_index = 0, end_index = -1)
|
76
|
+
end_index = vec.length if end_index == -1
|
77
|
+
|
78
|
+
check_vector(vec)
|
79
|
+
check_limits(start_index, end_index, vec.length)
|
80
|
+
|
81
|
+
start_index.upto(end_index - 1) {|i| vec.set!(i, fill)}
|
82
|
+
end
|
83
|
+
|
84
|
+
# :stopdoc:
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Makes sure that start_index < end_index <= limit.
|
89
|
+
def check_limits(start_index, end_index, limit)
|
90
|
+
check_upper_limit(start_index, limit)
|
91
|
+
check_upper_limit(start_index, end_index)
|
92
|
+
check_upper_limit(end_index, limit + 1)
|
93
|
+
end
|
94
|
+
|
95
|
+
# :startdoc:
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
data/lib/rus3/repl.rb
CHANGED
@@ -97,7 +97,9 @@ module Rus3
|
|
97
97
|
# Shows the greeting message.
|
98
98
|
def greeting
|
99
99
|
puts "A simple REPL for Rus3:"
|
100
|
-
puts "- Rus3 version: #{Rus3::VERSION}"
|
100
|
+
puts "- Rus3 version: #{Rus3::VERSION} (#{Rus3::RELEASE})"
|
101
|
+
return unless @verbose
|
102
|
+
|
101
103
|
puts " - REPL version: #{VERSION}"
|
102
104
|
COMPONENTS.keys.each { |comp_name|
|
103
105
|
Kernel.print " - "
|
data/lib/rus3/vector.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module Rus3
|
6
|
+
|
7
|
+
# A class to represent a vector structure of Scheme.
|
8
|
+
|
9
|
+
class Vector
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Returns a new Vector instance which elements are the given objs.
|
14
|
+
def vector(*objs)
|
15
|
+
list_to_vector(objs)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Converts a list into a new Vector instance.
|
19
|
+
def list_to_vector(lst)
|
20
|
+
vec = self.new(lst.size)
|
21
|
+
lst.each_with_index {|e, i| vec.set!(i, e)}
|
22
|
+
vec
|
23
|
+
end
|
24
|
+
|
25
|
+
# Converts a Vector instance into a list.
|
26
|
+
def vector_to_list(vec)
|
27
|
+
vec.to_a
|
28
|
+
end
|
29
|
+
|
30
|
+
# Replaces the k-th element of the given vector with obj.
|
31
|
+
def vector_set!(vec, k, obj)
|
32
|
+
raise ExceedUpperLimitError.new(k, vec.length) if k >= vec.length
|
33
|
+
vec.set!(k, obj)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(k, fill = UNDEF)
|
39
|
+
@content = Array.new(k, fill)
|
40
|
+
end
|
41
|
+
|
42
|
+
def_delegator :@content, :[], :ref
|
43
|
+
def_delegator :@content, :[]=, :set!
|
44
|
+
def_delegator :@content, :size, :length
|
45
|
+
|
46
|
+
# Returns an Array instance which contains the vector contents.
|
47
|
+
def to_a
|
48
|
+
@content.dup
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts a string represents as a Scheme vector.
|
52
|
+
def to_s
|
53
|
+
"#(#{@content.join(' ')})"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/rus3/version.rb
CHANGED
data/rus3.gemspec
CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.summary = "Ruby with Syntax Sugar of Scheme"
|
12
12
|
spec.description = "Ruby with Syntax Sugar of Scheme"
|
13
13
|
spec.homepage = "https://github.com/mnbi/rus3"
|
14
|
+
spec.license = "MIT"
|
14
15
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
15
16
|
|
16
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rus3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mnbi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-04-
|
11
|
+
date: 2021-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby with Syntax Sugar of Scheme
|
14
14
|
email:
|
@@ -45,12 +45,16 @@ files:
|
|
45
45
|
- lib/rus3/procedure/control.rb
|
46
46
|
- lib/rus3/procedure/list.rb
|
47
47
|
- lib/rus3/procedure/predicate.rb
|
48
|
+
- lib/rus3/procedure/utils.rb
|
49
|
+
- lib/rus3/procedure/vector.rb
|
48
50
|
- lib/rus3/procedure/write.rb
|
49
51
|
- lib/rus3/repl.rb
|
52
|
+
- lib/rus3/vector.rb
|
50
53
|
- lib/rus3/version.rb
|
51
54
|
- rus3.gemspec
|
52
55
|
homepage: https://github.com/mnbi/rus3
|
53
|
-
licenses:
|
56
|
+
licenses:
|
57
|
+
- MIT
|
54
58
|
metadata:
|
55
59
|
homepage_uri: https://github.com/mnbi/rus3
|
56
60
|
source_code_uri: https://github.com/mnbi/rus3
|