rus3 0.1.0 → 0.1.1
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 +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
|