akaza 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +3 -5
- data/akaza.gemspec +1 -1
- data/lib/akaza.rb +1 -0
- data/lib/akaza/ast_ext.rb +7 -4
- data/lib/akaza/parser.rb +1 -1
- data/lib/akaza/ruby2ws.rb +320 -0
- data/lib/akaza/version.rb +1 -1
- data/lib/akaza/vm.rb +19 -9
- metadata +7 -7
- data/Gemfile.lock +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a887b99455c8e17fb594fe02a570c5ea0251c57b5d3e0a73030aeff7c7d5c35
|
4
|
+
data.tar.gz: 5f57819daa32f8560816bb36a45930acef8aeecb11d9bc1acf7f247d75c9484f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bbe86bad2ad3096bd1d6845bd6a88f831977022c7b31cf4bd0aa8b35f6f89e68907bb1cd813fd25b0f656e2c4e2be936d77a51efef554245ebae3ed05349584
|
7
|
+
data.tar.gz: f426f4188fdb40d9632042941c2633922df440bf9fea1f08338e2ebdc43b86bf6029bad3986e8cd2431df1bc1258e75d83bee6edb9d67459e1471ce591abe953
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -66,8 +66,7 @@ class A
|
|
66
66
|
Akaza::Body
|
67
67
|
|
68
68
|
|
69
|
-
|
70
|
-
|
69
|
+
|
71
70
|
output.string.to_i
|
72
71
|
|
73
72
|
end
|
@@ -112,8 +111,7 @@ This code is never evaluated.
|
|
112
111
|
So you can write any
|
113
112
|
sentences as comments!
|
114
113
|
|
115
|
-
|
116
|
-
|
114
|
+
|
117
115
|
|
118
116
|
|
119
117
|
end
|
@@ -123,7 +121,7 @@ a = A.new
|
|
123
121
|
input = StringIO.new("20\n22\n")
|
124
122
|
output = StringIO.new
|
125
123
|
a.sum(input, output)
|
126
|
-
p output.string
|
124
|
+
p output.string # => "42"
|
127
125
|
```
|
128
126
|
|
129
127
|
## Development
|
data/akaza.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
-
spec.add_development_dependency "bundler"
|
30
|
+
spec.add_development_dependency "bundler"
|
31
31
|
spec.add_development_dependency "rake", "~> 12.0"
|
32
32
|
spec.add_development_dependency "minitest", ">= 5"
|
33
33
|
end
|
data/lib/akaza.rb
CHANGED
data/lib/akaza/ast_ext.rb
CHANGED
@@ -5,10 +5,13 @@ module Akaza
|
|
5
5
|
file_content(path)[first_index(path)..last_index(path)]
|
6
6
|
end
|
7
7
|
|
8
|
-
def traverse(&
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def traverse(&on_enter)
|
9
|
+
opt = {}
|
10
|
+
on_enter.call self, opt
|
11
|
+
unless opt[:skip_children]
|
12
|
+
children.each do |child|
|
13
|
+
child.traverse(&on_enter) if child.is_a?(RubyVM::AbstractSyntaxTree::Node)
|
14
|
+
end
|
12
15
|
end
|
13
16
|
end
|
14
17
|
|
data/lib/akaza/parser.rb
CHANGED
@@ -0,0 +1,320 @@
|
|
1
|
+
module Akaza
|
2
|
+
# Convert Ruby like script to Whitespace.
|
3
|
+
# The syntax is a subset of Ruby,
|
4
|
+
# but it has different semantics with Ruby.
|
5
|
+
#
|
6
|
+
# # sample code
|
7
|
+
# # output
|
8
|
+
# put_as_number n
|
9
|
+
# put_as_char ch
|
10
|
+
# put_as_number 42
|
11
|
+
# put_as_char 'a'
|
12
|
+
#
|
13
|
+
# # input
|
14
|
+
# num = get_as_number
|
15
|
+
# char = get_as_char
|
16
|
+
#
|
17
|
+
# # flow
|
18
|
+
# def foo
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# exit
|
22
|
+
#
|
23
|
+
# if x == 0
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# if x < 0
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # heap
|
30
|
+
# x = 10
|
31
|
+
# push x
|
32
|
+
module Ruby2ws
|
33
|
+
using AstExt
|
34
|
+
SPACE = ' '
|
35
|
+
TAB = "\t"
|
36
|
+
NL = "\n"
|
37
|
+
|
38
|
+
class ParseError < StandardError; end
|
39
|
+
|
40
|
+
def self.ruby_to_ws(ruby_code)
|
41
|
+
Transpiler.new(ruby_code).transpile
|
42
|
+
end
|
43
|
+
|
44
|
+
class Transpiler
|
45
|
+
def initialize(ruby_code)
|
46
|
+
@ruby_code = ruby_code
|
47
|
+
@label_index = 0
|
48
|
+
end
|
49
|
+
|
50
|
+
def transpile
|
51
|
+
ast = RubyVM::AbstractSyntaxTree.parse(@ruby_code)
|
52
|
+
commands = ast_to_commands(ast, main: true)
|
53
|
+
commands_to_ws(commands)
|
54
|
+
end
|
55
|
+
|
56
|
+
private def ast_to_commands(ast, main:)
|
57
|
+
commands = []
|
58
|
+
methods = []
|
59
|
+
lvars = []
|
60
|
+
|
61
|
+
ast.traverse do |node, opt|
|
62
|
+
case node
|
63
|
+
in [:FCALL, :put_as_number, [:ARRAY, arg, nil]]
|
64
|
+
commands.concat(push_value(arg))
|
65
|
+
commands << [:io, :write_num]
|
66
|
+
opt[:skip_children] = true
|
67
|
+
in [:FCALL, :put_as_char, [:ARRAY, arg, nil]]
|
68
|
+
commands.concat(push_value(arg))
|
69
|
+
commands << [:io, :write_char]
|
70
|
+
opt[:skip_children] = true
|
71
|
+
in [:VCALL, :exit]
|
72
|
+
commands << [:flow, :exit]
|
73
|
+
in [:LASGN, var, arg]
|
74
|
+
var_addr = str_to_int(var, type: :variable)
|
75
|
+
commands << [:stack, :push, var_addr]
|
76
|
+
commands.concat(push_value(arg))
|
77
|
+
commands << [:heap, :save]
|
78
|
+
opt[:skip_children] = true
|
79
|
+
lvars << var_addr
|
80
|
+
in [:DEFN, name, [:SCOPE, lvar_table, [:ARGS, args_count ,*_], body]]
|
81
|
+
m = [
|
82
|
+
[:flow, :def, str_to_int(name, type: :method)],
|
83
|
+
]
|
84
|
+
lvar_table[0...args_count].reverse.each do |args_name|
|
85
|
+
m << [:stack, :push, str_to_int(args_name, type: :variable)]
|
86
|
+
m << [:stack, :swap]
|
87
|
+
m << [:heap, :save]
|
88
|
+
end
|
89
|
+
m.concat(ast_to_commands(body, main: false))
|
90
|
+
m << [:flow, :end]
|
91
|
+
|
92
|
+
methods << m
|
93
|
+
opt[:skip_children] = true
|
94
|
+
in [:SCOPE, *_] | [:BLOCK, *_]
|
95
|
+
# skip
|
96
|
+
in [:VCALL, name]
|
97
|
+
with_storing_lvars(lvars, commands) do
|
98
|
+
commands << [:flow, :call, str_to_int(name, type: :method)]
|
99
|
+
end
|
100
|
+
opt[:skip_children] = true
|
101
|
+
in [:FCALL, name, [:ARRAY, *args, nil]]
|
102
|
+
with_storing_lvars(lvars, commands) do
|
103
|
+
args.each do |arg|
|
104
|
+
commands.concat(push_value(arg))
|
105
|
+
end
|
106
|
+
commands << [:flow, :call, str_to_int(name, type: :method)]
|
107
|
+
end
|
108
|
+
opt[:skip_children] = true
|
109
|
+
in [:IF, cond, if_body, else_body]
|
110
|
+
commands.concat(compile_if(cond, if_body, else_body))
|
111
|
+
opt[:skip_children] = true
|
112
|
+
in [:UNLESS, cond, else_body, if_body]
|
113
|
+
commands.concat(compile_if(cond, if_body, else_body))
|
114
|
+
opt[:skip_children] = true
|
115
|
+
in [:WHILE, cond, body]
|
116
|
+
commands.concat(compile_while(cond, body))
|
117
|
+
opt[:skip_children] = true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
commands << [:flow, :exit] if main
|
122
|
+
commands.concat(*methods)
|
123
|
+
commands
|
124
|
+
end
|
125
|
+
|
126
|
+
private def commands_to_ws(commands)
|
127
|
+
buf = +""
|
128
|
+
commands.each do |command|
|
129
|
+
case command
|
130
|
+
in [:stack, :push, num]
|
131
|
+
buf << SPACE << SPACE << num_to_ws(num)
|
132
|
+
in [:stack, :swap]
|
133
|
+
buf << SPACE << NL << TAB
|
134
|
+
in [:heap, :save]
|
135
|
+
buf << TAB << TAB << SPACE
|
136
|
+
in [:heap, :load]
|
137
|
+
buf << TAB << TAB << TAB
|
138
|
+
in [:io, :write_char]
|
139
|
+
buf << TAB << NL << SPACE << SPACE
|
140
|
+
in [:io, :write_num]
|
141
|
+
buf << TAB << NL << SPACE << TAB
|
142
|
+
in [:io, :read_char]
|
143
|
+
buf << TAB << NL << TAB << SPACE
|
144
|
+
in [:io, :read_num]
|
145
|
+
buf << TAB << NL << TAB << TAB
|
146
|
+
in [:flow, :exit]
|
147
|
+
buf << NL << NL << NL
|
148
|
+
in [:flow, :call, num]
|
149
|
+
buf << NL << SPACE << TAB << num_to_ws(num)
|
150
|
+
in [:flow, :def, num]
|
151
|
+
buf << NL << SPACE << SPACE << num_to_ws(num)
|
152
|
+
in [:flow, :end]
|
153
|
+
buf << NL << TAB << NL
|
154
|
+
in [:flow, :jump_if_zero, label]
|
155
|
+
buf << NL << TAB << SPACE << num_to_ws(label)
|
156
|
+
in [:flow, :jump, label]
|
157
|
+
buf << NL << SPACE << NL << num_to_ws(label)
|
158
|
+
in [:flow, :jump_if_neg, label]
|
159
|
+
buf << NL << TAB << TAB << num_to_ws(label)
|
160
|
+
in [:calc, :add]
|
161
|
+
buf << TAB << SPACE << SPACE << SPACE
|
162
|
+
in [:calc, :sub]
|
163
|
+
buf << TAB << SPACE << SPACE << TAB
|
164
|
+
in [:calc, :multi]
|
165
|
+
buf << TAB << SPACE << SPACE << NL
|
166
|
+
in [:calc, :div]
|
167
|
+
buf << TAB << SPACE << TAB << SPACE
|
168
|
+
in [:calc, :mod]
|
169
|
+
buf << TAB << SPACE << TAB << TAB
|
170
|
+
end
|
171
|
+
end
|
172
|
+
buf
|
173
|
+
end
|
174
|
+
|
175
|
+
private def with_storing_lvars(lvars, commands, &block)
|
176
|
+
lvars.each do |var_addr|
|
177
|
+
# stack.push(addr); stack.push(val)
|
178
|
+
commands << [:stack, :push, var_addr]
|
179
|
+
commands << [:stack, :push, var_addr]
|
180
|
+
commands << [:heap, :load]
|
181
|
+
# Fill zero
|
182
|
+
commands << [:stack, :push, var_addr]
|
183
|
+
commands << [:stack, :push, 0]
|
184
|
+
commands << [:heap, :save]
|
185
|
+
end
|
186
|
+
|
187
|
+
block.call
|
188
|
+
|
189
|
+
lvars.size.times do
|
190
|
+
commands << [:heap, :save]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
private def push_value(ast)
|
195
|
+
commands = []
|
196
|
+
|
197
|
+
case ast
|
198
|
+
in [:LIT, num]
|
199
|
+
commands << [:stack, :push, num]
|
200
|
+
in [:STR, str]
|
201
|
+
check_char!(str)
|
202
|
+
commands << [:stack, :push, str.ord]
|
203
|
+
in [:LVAR, name]
|
204
|
+
commands << [:stack, :push, str_to_int(name, type: :variable)]
|
205
|
+
commands << [:heap, :load]
|
206
|
+
in [:VCALL, :get_as_number]
|
207
|
+
tmp_var = str_to_int("__tmp", type: :variable)
|
208
|
+
commands << [:stack, :push, tmp_var]
|
209
|
+
commands << [:io, :read_num]
|
210
|
+
commands << [:stack, :push, tmp_var]
|
211
|
+
commands << [:heap, :load]
|
212
|
+
in [:VCALL, :get_as_char]
|
213
|
+
tmp_var = str_to_int("__tmp", type: :variable)
|
214
|
+
commands << [:stack, :push, tmp_var]
|
215
|
+
commands << [:io, :read_char]
|
216
|
+
commands << [:stack, :push, tmp_var]
|
217
|
+
commands << [:heap, :load]
|
218
|
+
in [:OPCALL, l, sym, [:ARRAY, r, nil]]
|
219
|
+
com = {'+': :add, '-': :sub, '*': :multi, '/': :div, '%': :mod}[sym]
|
220
|
+
raise ParserError, "Unknown symbol: #{sym}" unless com
|
221
|
+
commands.concat(push_value(l))
|
222
|
+
commands.concat(push_value(r))
|
223
|
+
commands << [:calc, com]
|
224
|
+
end
|
225
|
+
|
226
|
+
commands
|
227
|
+
end
|
228
|
+
|
229
|
+
private def compile_if(cond, if_body, else_body)
|
230
|
+
commands = []
|
231
|
+
else_label = str_to_int("else_#{next_label_index}", type: :condition)
|
232
|
+
end_label = str_to_int("end_#{next_label_index}", type: :condition)
|
233
|
+
|
234
|
+
body = -> (x, sym) do
|
235
|
+
commands.concat(push_value(x))
|
236
|
+
commands << [:flow, sym, else_label]
|
237
|
+
commands.concat(ast_to_commands(else_body, main: false)) if else_body
|
238
|
+
commands << [:flow, :jump, end_label]
|
239
|
+
commands << [:flow, :def, else_label]
|
240
|
+
commands.concat(ast_to_commands(if_body, main: false)) if if_body
|
241
|
+
commands << [:flow, :def, end_label]
|
242
|
+
end
|
243
|
+
|
244
|
+
case cond
|
245
|
+
in [:OPCALL, [:LIT, 0], :==, [:ARRAY, x, nil]]
|
246
|
+
body.(x, :jump_if_zero)
|
247
|
+
in [:OPCALL, x, :==, [:ARRAY, [:LIT, 0], nil]]
|
248
|
+
body.(x, :jump_if_zero)
|
249
|
+
in [:OPCALL, x, :<, [:ARRAY, [:LIT, 0], nil]]
|
250
|
+
body.(x, :jump_if_neg)
|
251
|
+
in [:OPCALL, [:LIT, 0], :<, [:ARRAY, x, nil]]
|
252
|
+
body.(x, :jump_if_neg)
|
253
|
+
end
|
254
|
+
|
255
|
+
commands
|
256
|
+
end
|
257
|
+
|
258
|
+
private def compile_while(cond, body)
|
259
|
+
commands = []
|
260
|
+
cond_label = str_to_int("cond_#{next_label_index}", type: :condition)
|
261
|
+
body_label = str_to_int("body_#{next_label_index}", type: :condition)
|
262
|
+
end_label = str_to_int("end_#{next_label_index}", type: :condition)
|
263
|
+
|
264
|
+
make_body = -> (x, sym) do
|
265
|
+
commands << [:flow, :def, cond_label]
|
266
|
+
commands.concat(push_value(x))
|
267
|
+
commands << [:flow, sym, body_label]
|
268
|
+
commands << [:flow, :jump, end_label]
|
269
|
+
commands << [:flow, :def, body_label]
|
270
|
+
commands.concat(ast_to_commands(body, main: false))
|
271
|
+
commands << [:flow, :jump, cond_label]
|
272
|
+
commands << [:flow, :def, end_label]
|
273
|
+
end
|
274
|
+
|
275
|
+
case cond
|
276
|
+
in [:OPCALL, [:LIT, 0], :==, [:ARRAY, x, nil]]
|
277
|
+
make_body.(x, :jump_if_zero)
|
278
|
+
in [:OPCALL, x, :==, [:ARRAY, [:LIT, 0], nil]]
|
279
|
+
make_body.(x, :jump_if_zero)
|
280
|
+
in [:OPCALL, x, :<, [:ARRAY, [:LIT, 0], nil]]
|
281
|
+
make_body.(x, :jump_if_neg)
|
282
|
+
in [:OPCALL, [:LIT, 0], :<, [:ARRAY, x, nil]]
|
283
|
+
make_body.(x, :jump_if_neg)
|
284
|
+
end
|
285
|
+
|
286
|
+
commands
|
287
|
+
end
|
288
|
+
|
289
|
+
private def check_char!(char)
|
290
|
+
raise ParserError, "String size must be 1, but it's #{char} (#{char.size})" if char.size != 1
|
291
|
+
end
|
292
|
+
|
293
|
+
private def str_to_int(str, type:)
|
294
|
+
prefix =
|
295
|
+
case type
|
296
|
+
when :variable then 'v'
|
297
|
+
when :method then 'f'
|
298
|
+
when :condition then 'c'
|
299
|
+
else
|
300
|
+
raise "Unknown type: #{type}"
|
301
|
+
end
|
302
|
+
"#{prefix}_#{str}".bytes.inject { |a, b| (a << 8) + b }
|
303
|
+
end
|
304
|
+
|
305
|
+
private def num_to_ws(num)
|
306
|
+
sign =
|
307
|
+
if num < 0
|
308
|
+
TAB
|
309
|
+
else
|
310
|
+
SPACE
|
311
|
+
end
|
312
|
+
sign + num.abs.to_s(2).gsub("1", TAB).gsub('0', SPACE) + NL
|
313
|
+
end
|
314
|
+
|
315
|
+
private def next_label_index
|
316
|
+
@label_index += 1
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
data/lib/akaza/version.rb
CHANGED
data/lib/akaza/vm.rb
CHANGED
@@ -25,15 +25,25 @@ module Akaza
|
|
25
25
|
in [:stack, :pop]
|
26
26
|
@stack.pop
|
27
27
|
in [:calc, :add]
|
28
|
-
|
28
|
+
r = @stack.pop
|
29
|
+
l = @stack.pop
|
30
|
+
@stack.push l + r
|
29
31
|
in [:calc, :sub]
|
30
|
-
|
32
|
+
r = @stack.pop
|
33
|
+
l = @stack.pop
|
34
|
+
@stack.push l - r
|
31
35
|
in [:calc, :multi]
|
32
|
-
|
36
|
+
r = @stack.pop
|
37
|
+
l = @stack.pop
|
38
|
+
@stack.push l * r
|
33
39
|
in [:calc, :div]
|
34
|
-
|
40
|
+
r = @stack.pop
|
41
|
+
l = @stack.pop
|
42
|
+
@stack.push l / r
|
35
43
|
in [:calc, :mod]
|
36
|
-
|
44
|
+
r = @stack.pop
|
45
|
+
l = @stack.pop
|
46
|
+
@stack.push l % r
|
37
47
|
in [:heap, :save]
|
38
48
|
val = @stack.pop
|
39
49
|
addr = @stack.pop
|
@@ -42,13 +52,13 @@ module Akaza
|
|
42
52
|
addr = @stack.pop
|
43
53
|
@stack.push @heap[addr]
|
44
54
|
in [:flow, :def, label]
|
45
|
-
#
|
55
|
+
# skip
|
46
56
|
in [:flow, :call, label]
|
47
|
-
raise "unknwon label:#{label}" unless @labels.key?(label)
|
57
|
+
raise "unknwon label:#{label.inspect}" unless @labels.key?(label)
|
48
58
|
@call_stack.push @index
|
49
59
|
@index = @labels[label]
|
50
60
|
in [:flow, :jump, label]
|
51
|
-
raise "unknwon label:#{label}" unless @labels.key?(label)
|
61
|
+
raise "unknwon label:#{label.inspect}" unless @labels.key?(label)
|
52
62
|
@index = @labels[label]
|
53
63
|
in [:flow, :jump_if_zero, label]
|
54
64
|
@index = @labels[label] if @stack.pop == 0
|
@@ -77,7 +87,7 @@ module Akaza
|
|
77
87
|
@commands.each.with_index do |command, index|
|
78
88
|
case command
|
79
89
|
in [:flow, :def, label]
|
80
|
-
@labels[label] = index
|
90
|
+
@labels[label] = index
|
81
91
|
else
|
82
92
|
# skip
|
83
93
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: akaza
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masataka Pocke Kuwabara
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -61,7 +61,6 @@ extra_rdoc_files: []
|
|
61
61
|
files:
|
62
62
|
- ".gitignore"
|
63
63
|
- Gemfile
|
64
|
-
- Gemfile.lock
|
65
64
|
- README.md
|
66
65
|
- Rakefile
|
67
66
|
- akaza.gemspec
|
@@ -72,6 +71,7 @@ files:
|
|
72
71
|
- lib/akaza/annotation.rb
|
73
72
|
- lib/akaza/ast_ext.rb
|
74
73
|
- lib/akaza/parser.rb
|
74
|
+
- lib/akaza/ruby2ws.rb
|
75
75
|
- lib/akaza/version.rb
|
76
76
|
- lib/akaza/vm.rb
|
77
77
|
homepage: https://github.com/pocke/akaza
|
data/Gemfile.lock
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
akaza (0.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
minitest (5.11.3)
|
10
|
-
rake (12.3.2)
|
11
|
-
|
12
|
-
PLATFORMS
|
13
|
-
ruby
|
14
|
-
|
15
|
-
DEPENDENCIES
|
16
|
-
akaza!
|
17
|
-
bundler (~> 2.1.a)
|
18
|
-
minitest (>= 5)
|
19
|
-
rake (~> 12.0)
|
20
|
-
|
21
|
-
BUNDLED WITH
|
22
|
-
2.1.0.pre.1
|