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/utils.rb
CHANGED
@@ -1,27 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rus3
|
4
|
-
module
|
3
|
+
module Rus3
|
4
|
+
module Procedure
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
module Utils
|
7
|
+
|
8
|
+
def check_pair(pair) # :nodoc:
|
9
|
+
if !pair.instance_of?(Rus3::Pair) and !pair.instance_of?(Array)
|
10
|
+
raise Rus3::PairRequiredError, pair
|
11
|
+
end
|
9
12
|
end
|
10
|
-
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
def check_list(lst) # :nodoc:
|
15
|
+
raise Rus3::ListRequiredError, lst unless list?(lst)
|
16
|
+
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
def check_vector(obj) # :nodoc:
|
19
|
+
raise Rus3::VectorRequiredError, obj unless vector?(obj)
|
20
|
+
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
+
# To make sure the number is less than its upper limit. When k
|
23
|
+
# greater than or equal to limit, raises ExceedUpperLimitError.
|
24
|
+
|
25
|
+
def check_upper_limit(k, limit)
|
26
|
+
raise Rus3::ExceedUpperLimitError.new(k, limit) if k >= limit
|
27
|
+
end
|
22
28
|
|
23
|
-
def check_upper_limit(k, limit)
|
24
|
-
raise Rus3::ExceedUpperLimitError.new(k, limit) if k >= limit
|
25
29
|
end
|
26
30
|
|
27
31
|
end
|
@@ -1,98 +1,101 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rus3
|
3
|
+
module Rus3
|
4
|
+
module Procedure
|
4
5
|
|
5
|
-
|
6
|
+
# Provides procedures to operate a vector.
|
6
7
|
|
7
|
-
|
8
|
+
module Vector
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
include Utils
|
11
|
+
include List
|
12
|
+
include Predicate
|
13
|
+
include Rus3::EmptyList
|
13
14
|
|
14
|
-
|
15
|
+
UNDEF = Rus3::UNDEF
|
15
16
|
|
16
|
-
|
17
|
+
# - procedure (R5RS/R7RS): (make-vector k) or (make-vector k fill)
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def make_vector(k, fill = UNDEF)
|
20
|
+
Rus3::Vector.new(k, fill)
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
+
# - library procedure (R5RS/R7RS): (vector obj ...)
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
def vector(*objs)
|
26
|
+
Rus3::Vector.vector(*objs)
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
+
# - procedure (R5RS/R7RS): (vector-length vector)
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
def vector_length(vec)
|
32
|
+
check_vector(vec)
|
33
|
+
vec.length
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
+
# - procedure (R5RS/R7RS): (vector-ref vector, k)
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
def vector_ref(vec, k)
|
39
|
+
check_vector(vec)
|
40
|
+
check_upper_limit(k, vec.length)
|
41
|
+
vec.ref(k)
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
+
# - procedure (R5RS/R7RS): (vector-set! vector k obj)
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
def vector_set!(vec, k, obj)
|
47
|
+
check_vector(vec)
|
48
|
+
Rus3::Vector.vector_set!(vec, k, obj)
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
# - library procedure (R5RS): (vector->list vector)
|
52
|
+
# - procedure (R7RS):
|
53
|
+
# (vector->list vector)
|
54
|
+
# (vector->list vector start)
|
55
|
+
# (vector->list vector start end)
|
55
56
|
|
56
|
-
|
57
|
-
|
57
|
+
def vector_to_list(vec, start_index = 0, end_index = -1)
|
58
|
+
end_index = vec.length if end_index == -1
|
58
59
|
|
59
|
-
|
60
|
-
|
60
|
+
check_vector(vec)
|
61
|
+
check_limits(start_index, end_index, vec.length)
|
61
62
|
|
62
|
-
|
63
|
-
|
63
|
+
list(*vec.ref(start_index...end_index))
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
# - library procedure (R5RS): (list->vector list)
|
67
|
+
# - procedre (R7RS): (list->vector list)
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
def list_to_vector(lst)
|
70
|
+
Rus3::Vector.list_to_vector(lst)
|
71
|
+
end
|
71
72
|
|
72
|
-
|
73
|
-
|
73
|
+
# - library procedure (R5RS): (vector-fill! vector fill)
|
74
|
+
# - procedure (R7RS): (vector-fill! vector fill start end)
|
74
75
|
|
75
|
-
|
76
|
-
|
76
|
+
def vector_fill!(vec, fill, start_index = 0, end_index = -1)
|
77
|
+
end_index = vec.length if end_index == -1
|
77
78
|
|
78
|
-
|
79
|
-
|
79
|
+
check_vector(vec)
|
80
|
+
check_limits(start_index, end_index, vec.length)
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
start_index.upto(end_index - 1) {|i| vec.set!(i, fill)}
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
+
# :stopdoc:
|
85
86
|
|
86
|
-
|
87
|
+
private
|
87
88
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
89
|
+
# Makes sure that start_index < end_index <= limit.
|
90
|
+
def check_limits(start_index, end_index, limit)
|
91
|
+
check_upper_limit(start_index, limit)
|
92
|
+
check_upper_limit(start_index, end_index)
|
93
|
+
check_upper_limit(end_index, limit + 1)
|
94
|
+
end
|
94
95
|
|
95
|
-
|
96
|
+
# :startdoc:
|
97
|
+
|
98
|
+
end
|
96
99
|
|
97
100
|
end
|
98
101
|
end
|
data/lib/rus3/procedure/write.rb
CHANGED
@@ -1,130 +1,134 @@
|
|
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 Write
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
Rus3::UNDEF
|
12
|
-
end
|
13
|
-
|
14
|
-
def display(obj)
|
15
|
-
puts any_to_string(obj)
|
16
|
-
Rus3::UNDEF
|
17
|
-
end
|
8
|
+
include Predicate
|
9
|
+
include Rus3::EmptyList
|
18
10
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
TYPES = [
|
24
|
-
:null, # empty list
|
25
|
-
:boolean, # #f or #t
|
26
|
-
:pair, # (foo . bar)
|
27
|
-
:symbol,
|
28
|
-
:number,
|
29
|
-
:char,
|
30
|
-
:string,
|
31
|
-
:vector,
|
32
|
-
:port,
|
33
|
-
:procedure,
|
34
|
-
]
|
35
|
-
|
36
|
-
def private_method(name)
|
37
|
-
m = nil
|
38
|
-
if self.class.private_method_defined?(name)
|
39
|
-
um = self.class.instance_method(name)
|
40
|
-
m = um.bind(self)
|
11
|
+
def write(obj)
|
12
|
+
print any_to_string(obj)
|
13
|
+
Rus3::UNDEF
|
41
14
|
end
|
42
|
-
m
|
43
|
-
end
|
44
15
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
next unless respond_to?(predicate_name)
|
16
|
+
def display(obj)
|
17
|
+
puts any_to_string(obj)
|
18
|
+
Rus3::UNDEF
|
19
|
+
end
|
50
20
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
21
|
+
# :stopdoc:
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
TYPES = [
|
26
|
+
:null, # empty list
|
27
|
+
:boolean, # #f or #t
|
28
|
+
:pair, # (foo . bar)
|
29
|
+
:symbol,
|
30
|
+
:number,
|
31
|
+
:char,
|
32
|
+
:string,
|
33
|
+
:vector,
|
34
|
+
:port,
|
35
|
+
:procedure,
|
36
|
+
]
|
37
|
+
|
38
|
+
def private_method(name)
|
39
|
+
m = nil
|
40
|
+
if self.class.private_method_defined?(name)
|
41
|
+
um = self.class.instance_method(name)
|
42
|
+
m = um.bind(self)
|
55
43
|
end
|
56
|
-
|
57
|
-
|
58
|
-
end
|
44
|
+
m
|
45
|
+
end
|
59
46
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
47
|
+
def type(obj)
|
48
|
+
obj_type = nil
|
49
|
+
TYPES.each { |type|
|
50
|
+
predicate_name = "#{type}?".intern
|
51
|
+
next unless respond_to?(predicate_name)
|
52
|
+
|
53
|
+
predicate_prc = method(predicate_name)
|
54
|
+
if predicate_prc.call(obj)
|
55
|
+
obj_type = type
|
56
|
+
break
|
57
|
+
end
|
58
|
+
}
|
59
|
+
obj_type || :undef
|
60
|
+
end
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
62
|
+
def any_to_string(obj)
|
63
|
+
prc_name = "#{type(obj)}_to_string".intern
|
64
|
+
prc = private_method(prc_name)
|
65
|
+
prc ? prc.call(obj) : obj.to_s
|
66
|
+
end
|
69
67
|
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
def null_to_string(obj)
|
69
|
+
"()"
|
70
|
+
end
|
71
|
+
|
72
|
+
def boolean_to_string(obj)
|
73
|
+
obj ? "#t" : "#f"
|
74
|
+
end
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
76
|
+
def pair_to_string(obj)
|
77
|
+
if null?(obj)
|
78
|
+
# ()
|
79
|
+
null_to_string(obj)
|
80
|
+
elsif list?(obj)
|
81
|
+
# (1 2 3 4)
|
82
|
+
result = obj.map {|e| any_to_string(e) }
|
83
|
+
"(#{result.join(' ')})"
|
84
|
+
else
|
85
|
+
# (1 2 3 . 4)
|
86
|
+
# ==> (1 . (2 . (3 . 4)))
|
87
|
+
result = any_to_string(obj.car)
|
88
|
+
cp = obj.cdr
|
89
|
+
|
90
|
+
while pair?(cp)
|
91
|
+
result += " "
|
92
|
+
result += any_to_string(cp.car)
|
93
|
+
cp = cp.cdr
|
94
|
+
end
|
95
|
+
|
96
|
+
result += " . "
|
97
|
+
result += any_to_string(cp)
|
98
|
+
"(#{result})"
|
92
99
|
end
|
100
|
+
end
|
93
101
|
|
94
|
-
|
95
|
-
|
96
|
-
"(#{result})"
|
102
|
+
def symbol_to_string(obj)
|
103
|
+
":#{obj}"
|
97
104
|
end
|
98
|
-
end
|
99
105
|
|
100
|
-
|
101
|
-
|
102
|
-
|
106
|
+
def number_to_string(obj)
|
107
|
+
obj.to_s
|
108
|
+
end
|
103
109
|
|
104
|
-
|
105
|
-
|
106
|
-
|
110
|
+
def char_to_string(obj)
|
111
|
+
# TODO:
|
112
|
+
end
|
107
113
|
|
108
|
-
|
109
|
-
|
110
|
-
|
114
|
+
def string_to_string(obj)
|
115
|
+
"\"#{obj}\""
|
116
|
+
end
|
111
117
|
|
112
|
-
|
113
|
-
|
114
|
-
|
118
|
+
def vector_to_string(obj)
|
119
|
+
# TODO:
|
120
|
+
end
|
115
121
|
|
116
|
-
|
117
|
-
|
118
|
-
|
122
|
+
def port_to_string(obj)
|
123
|
+
# TODO:
|
124
|
+
end
|
119
125
|
|
120
|
-
|
121
|
-
|
122
|
-
|
126
|
+
def procedure_to_string(obj)
|
127
|
+
# TODO:
|
128
|
+
end
|
123
129
|
|
124
|
-
|
125
|
-
# TODO:
|
130
|
+
# :startdoc:
|
126
131
|
end
|
127
132
|
|
128
|
-
# :startdoc:
|
129
133
|
end
|
130
134
|
end
|