vaporware-compiler 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +8 -0
- data/README.md +3 -0
- data/Rakefile +9 -0
- data/Steepfile +12 -0
- data/exe/vaporware +21 -0
- data/lib/vaporware/version.rb +5 -0
- data/lib/vaporware.rb +317 -0
- data/rbs_collection.lock.yaml +18 -0
- data/rbs_collection.yaml +22 -0
- data/sample/else.rb +5 -0
- data/sample/fiddle.rb +7 -0
- data/sample/hello.rb +1 -0
- data/sample/if.rb +3 -0
- data/sample/method.rb +2 -0
- data/sample/plus.rb +1 -0
- data/sample/variable.rb +4 -0
- data/sample/while.rb +11 -0
- data/sig/vaporware.rbs +57 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13390207490f478cdad891ae8c368d3fb3062c1b2005bdf331a25f3b2dc29dc4
|
4
|
+
data.tar.gz: 823150e9b1439dad476284f9b3ec00a8d86c427cd95d08f5ec19a75159cdf4f3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c6050037946286c6ddf340dada87bfa3847504feb1814bfd3e56bd5b467c5f30fe6a433d8d5372e7bc94722c09229c42a0bf17b0255ba8efc29d22fd696016b0
|
7
|
+
data.tar.gz: c45ee87e4728a90dbb6cfeb5b12c61048dd9ff82b6639d858cadbd211340f27c319ef0ab83fb43366deb1352b8d5912d8c6a0080ae0e6363b17df67421088e1d
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
data/Steepfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
D = Steep::Diagnostic
|
2
|
+
#
|
3
|
+
target :lib do
|
4
|
+
signature "sig"
|
5
|
+
check "lib" # Directory name
|
6
|
+
configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
|
7
|
+
configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
|
8
|
+
configure_code_diagnostics do |hash| # You can setup everything yourself
|
9
|
+
hash[D::Ruby::NoMethod] = :information
|
10
|
+
hash[D::Ruby::UnknownConstant] = :information
|
11
|
+
end
|
12
|
+
end
|
data/exe/vaporware
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "vaporware"
|
4
|
+
require "optparse"
|
5
|
+
opt = OptionParser.new
|
6
|
+
options = {}
|
7
|
+
opt.on("-c", "--compiler [VAL]", "this option is selecting compiler precompiled file, default: gcc") { |v| options[:compiler] = v }
|
8
|
+
opt.on("-D", "--debug") { |v| options[:debug] = v }
|
9
|
+
opt.on("-o", "--objects [VAL]") { |v| options[:dest] = v }
|
10
|
+
opt.on("--compiler-options[=VAL]", "compiler options") { |v| options[:compiler_options] = v.split(",") }
|
11
|
+
opt.on("-s", "--shared") { |v| options[:shared] = v }
|
12
|
+
|
13
|
+
begin
|
14
|
+
opt.parse!(ARGV)
|
15
|
+
raise "please compile target file" if ARGV.empty?
|
16
|
+
rescue => e
|
17
|
+
STDERR.puts(e.message)
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
Vaporware::Compiler.compile(ARGV.shift, **options)
|
data/lib/vaporware.rb
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "vaporware/version"
|
4
|
+
require "parser/current"
|
5
|
+
|
6
|
+
module Vaporware
|
7
|
+
class Error < StandardError; end
|
8
|
+
# Your code goes here...
|
9
|
+
class Compiler
|
10
|
+
REGISTER = %w(r9 r8 rcx rdx rsi rdi).reverse
|
11
|
+
attr_reader :ast, :_precompile, :debug, :seq, :defined_variables, :doned, :main, :shared, :defined_methods
|
12
|
+
def self.compile(source, compiler: "gcc", dest: "tmp", debug: false, compiler_options: ["-O0"], shared: false)
|
13
|
+
_precompile = "#{dest}.s"
|
14
|
+
s = new(source, _precompile: _precompile, debug:, shared:)
|
15
|
+
s.compile(compiler:, compiler_options:)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(source, _precompile: "tmp.s", debug: false, shared: false)
|
19
|
+
@_precompile, @debug, @seq, @shared = _precompile, debug, 0, shared
|
20
|
+
@defined_methods = Set.new
|
21
|
+
@defined_variables = Set.new
|
22
|
+
@doned = Set.new
|
23
|
+
src = File.read(File.expand_path(source))
|
24
|
+
@ast = Parser::CurrentRuby.parse(src)
|
25
|
+
@main = false
|
26
|
+
end
|
27
|
+
|
28
|
+
def compile(compiler: "gcc", compiler_options: ["-O0"])
|
29
|
+
puts ast if debug
|
30
|
+
|
31
|
+
register_var_and_method(ast)
|
32
|
+
|
33
|
+
output = File.open(_precompile, "w")
|
34
|
+
# prologue
|
35
|
+
output.puts ".intel_syntax noprefix"
|
36
|
+
if defined_methods.empty?
|
37
|
+
@main = true
|
38
|
+
output.puts ".globl main"
|
39
|
+
output.puts "main:"
|
40
|
+
output.puts " push rbp"
|
41
|
+
output.puts " mov rbp, rsp"
|
42
|
+
output.puts " sub rsp, #{defined_variables.size * 8}"
|
43
|
+
gen(ast, output)
|
44
|
+
# epilogue
|
45
|
+
gen_epilogue(output)
|
46
|
+
else
|
47
|
+
gen_prologue_methods(output)
|
48
|
+
output.puts ".globl main" unless shared
|
49
|
+
gen(ast, output)
|
50
|
+
# epilogue
|
51
|
+
gen_epilogue(output)
|
52
|
+
end
|
53
|
+
output.close
|
54
|
+
compiler_options += compile_shared_option if shared
|
55
|
+
call_compiler(compiler:, compiler_options:)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def compile_shared_option = %w(-shared -fPIC)
|
61
|
+
|
62
|
+
def register_var_and_method(node)
|
63
|
+
return unless node.kind_of?(Parser::AST::Node)
|
64
|
+
type = node.type
|
65
|
+
if variable_or_method?(type)
|
66
|
+
name, _ = node.children
|
67
|
+
name = [:lvasgn, :arg].include?(type) ? "lvar_#{name}".to_sym : name
|
68
|
+
type == :def ? @defined_methods << name : @defined_variables << name
|
69
|
+
end
|
70
|
+
node.children.each { |n| register_var_and_method(n) }
|
71
|
+
end
|
72
|
+
|
73
|
+
def already_build_methods? = defined_methods.sort == @doned.to_a.sort
|
74
|
+
def variable_or_method?(type) = [:lvasgn, :arg, :def].include?(type)
|
75
|
+
|
76
|
+
def call_compiler(output: _precompile, compiler: "gcc", compiler_options: ["-O0"])
|
77
|
+
base_name = File.basename(output, ".*")
|
78
|
+
name = shared ? "lib#{base_name}.so" : base_name
|
79
|
+
compile_commands = [compiler, *compiler_options, "-o", name, output].compact
|
80
|
+
IO.popen(compile_commands).close
|
81
|
+
|
82
|
+
puts File.read(output) if debug
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def gen_epilogue(output)
|
87
|
+
output.puts " mov rsp, rbp"
|
88
|
+
output.puts " pop rbp"
|
89
|
+
output.puts " ret"
|
90
|
+
end
|
91
|
+
|
92
|
+
def gen_prologue_methods(output)
|
93
|
+
defined_methods.each do |name|
|
94
|
+
output.puts ".globl #{name}"
|
95
|
+
output.puts ".type #{name}, @function" if shared
|
96
|
+
end
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def gen_define_method_prologue(node, output)
|
101
|
+
output.puts " push rbp"
|
102
|
+
output.puts " mov rbp, rsp"
|
103
|
+
output.puts " sub rsp, #{lvar_offset(nil) * 8}"
|
104
|
+
_name, args, _block = node.children
|
105
|
+
args.children.each_with_index do |_, i|
|
106
|
+
output.puts " mov [rbp-#{(i + 1) * 8}], #{REGISTER[i]}"
|
107
|
+
end
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
def gen_method(method, node, output)
|
112
|
+
output.puts "#{method}:"
|
113
|
+
gen_define_method_prologue(node, output)
|
114
|
+
node.children.each do |child|
|
115
|
+
next unless child.kind_of?(Parser::AST::Node)
|
116
|
+
gen(child, output, true)
|
117
|
+
end
|
118
|
+
gen_ret(output)
|
119
|
+
@doned << method
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
def gen_args(node, output)
|
124
|
+
node.children.each do |child|
|
125
|
+
name = "arg_#{child.children.first}".to_sym
|
126
|
+
gen_lvar(name, output)
|
127
|
+
output.puts " pop rax"
|
128
|
+
output.puts " mov rax, [rax]"
|
129
|
+
output.puts " push rax"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def gen_call_method(node, output, method_tree)
|
134
|
+
output.puts " mov rax, rsp"
|
135
|
+
output.puts " mov rdi, 16"
|
136
|
+
output.puts " cqo"
|
137
|
+
output.puts " idiv rdi"
|
138
|
+
output.puts " mov rax, 0"
|
139
|
+
output.puts " cmp rdi, 0"
|
140
|
+
output.puts " jne .Lprecall#{seq}"
|
141
|
+
output.puts " push 0"
|
142
|
+
output.puts " mov rax, 1"
|
143
|
+
output.puts ".Lprecall#{seq}:"
|
144
|
+
output.puts " push rax"
|
145
|
+
_, name, *args = node.children
|
146
|
+
args.each_with_index do |arg, i|
|
147
|
+
gen(arg, output, method_tree)
|
148
|
+
output.puts " pop #{REGISTER[i]}"
|
149
|
+
end
|
150
|
+
|
151
|
+
output.puts " call #{name}"
|
152
|
+
output.puts " pop rdi"
|
153
|
+
output.puts " cmp rdi, 0"
|
154
|
+
output.puts " je .Lpostcall#{seq}"
|
155
|
+
output.puts " pop rdi"
|
156
|
+
output.puts ".Lpostcall#{seq}:"
|
157
|
+
output.puts " push rax"
|
158
|
+
@seq += 1
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
|
162
|
+
def gen_comp(op, output)
|
163
|
+
output.puts " cmp rax, rdi"
|
164
|
+
output.puts " #{op} al"
|
165
|
+
output.puts " movzb rax, al"
|
166
|
+
output.puts " push rax"
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
|
170
|
+
def gen_lvar(var, output)
|
171
|
+
output.puts " mov rax, rbp"
|
172
|
+
output.puts " sub rax, #{lvar_offset(var) * 8}"
|
173
|
+
output.puts " push rax"
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
|
177
|
+
def lvar_offset(var)
|
178
|
+
return @defined_variables.size if var.nil?
|
179
|
+
@defined_variables.find_index(var).then do |i|
|
180
|
+
raise "unknown local variable...: #{var}" if i.nil?
|
181
|
+
i + 1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def gen_ret(output)
|
186
|
+
output.puts " pop rax"
|
187
|
+
output.puts " mov rsp, rbp"
|
188
|
+
output.puts " pop rbp"
|
189
|
+
output.puts " ret"
|
190
|
+
end
|
191
|
+
|
192
|
+
def gen(node, output, method_tree = false)
|
193
|
+
return unless node.kind_of?(Parser::AST::Node)
|
194
|
+
type = node.type
|
195
|
+
center = case type
|
196
|
+
when :int
|
197
|
+
output.puts " push #{node.children.last}"
|
198
|
+
return
|
199
|
+
when :begin
|
200
|
+
node.children.each do |child|
|
201
|
+
if already_build_methods? && !@main
|
202
|
+
return if shared
|
203
|
+
output.puts "main:"
|
204
|
+
output.puts " push rbp"
|
205
|
+
output.puts " mov rbp, rsp"
|
206
|
+
output.puts " sub rsp, 0"
|
207
|
+
output.puts " push rax"
|
208
|
+
@main = true
|
209
|
+
end
|
210
|
+
gen(child, output)
|
211
|
+
end
|
212
|
+
return
|
213
|
+
when :def
|
214
|
+
name, _ = node.children
|
215
|
+
gen_method(name, node, output)
|
216
|
+
return
|
217
|
+
when :args
|
218
|
+
gen_args(node, output)
|
219
|
+
return
|
220
|
+
when :lvar
|
221
|
+
return if method_tree
|
222
|
+
name = "lvar_#{node.children.last}".to_sym
|
223
|
+
gen_lvar(name, output)
|
224
|
+
# lvar
|
225
|
+
output.puts " pop rax"
|
226
|
+
output.puts " mov rax, [rax]"
|
227
|
+
output.puts " push rax"
|
228
|
+
return
|
229
|
+
when :lvasgn
|
230
|
+
left, right = node.children
|
231
|
+
|
232
|
+
# rvar
|
233
|
+
name = "lvar_#{left}".to_sym
|
234
|
+
gen_lvar(name, output)
|
235
|
+
gen(right, output, method_tree)
|
236
|
+
|
237
|
+
output.puts " pop rdi"
|
238
|
+
output.puts " pop rax"
|
239
|
+
output.puts " mov [rax], rdi"
|
240
|
+
output.puts " push rdi"
|
241
|
+
output.puts " pop rax"
|
242
|
+
return
|
243
|
+
when :if
|
244
|
+
cond, tblock, fblock = node.children
|
245
|
+
gen(cond, output)
|
246
|
+
output.puts " pop rax"
|
247
|
+
output.puts " push rax"
|
248
|
+
output.puts " cmp rax, 0"
|
249
|
+
if fblock
|
250
|
+
output.puts " je .Lelse#{seq}"
|
251
|
+
gen(tblock, output, method_tree)
|
252
|
+
gen_ret(output)
|
253
|
+
output.puts " jmp .Lend#{seq}"
|
254
|
+
output.puts ".Lelse#{seq}:"
|
255
|
+
gen(fblock, output, method_tree)
|
256
|
+
gen_ret(output)
|
257
|
+
output.puts ".Lend#{seq}:"
|
258
|
+
else
|
259
|
+
output.puts " je .Lend#{seq}"
|
260
|
+
gen(tblock, output, method_tree)
|
261
|
+
gen_ret(output)
|
262
|
+
output.puts ".Lend#{seq}:"
|
263
|
+
end
|
264
|
+
@seq += 1
|
265
|
+
return
|
266
|
+
when :while
|
267
|
+
cond, tblock = node.children
|
268
|
+
output.puts ".Lbegin#{seq}:"
|
269
|
+
gen(cond, output, method_tree)
|
270
|
+
output.puts " pop rax"
|
271
|
+
output.puts " push rax"
|
272
|
+
output.puts " cmp rax, 0"
|
273
|
+
output.puts " je .Lend#{seq}"
|
274
|
+
gen(tblock, output, method_tree)
|
275
|
+
output.puts " jmp .Lbegin#{seq}"
|
276
|
+
output.puts ".Lend#{seq}:"
|
277
|
+
@seq += 1
|
278
|
+
return
|
279
|
+
when :send
|
280
|
+
left, center, right = node.children
|
281
|
+
gen(left, output, method_tree) unless left.nil?
|
282
|
+
if left.nil?
|
283
|
+
gen_call_method(node, output, method_tree)
|
284
|
+
else
|
285
|
+
gen(right, output, method_tree)
|
286
|
+
output.puts " pop rdi"
|
287
|
+
end
|
288
|
+
output.puts " pop rax"
|
289
|
+
center
|
290
|
+
end
|
291
|
+
|
292
|
+
case center
|
293
|
+
when :+
|
294
|
+
output.puts " add rax, rdi"
|
295
|
+
output.puts " push rax"
|
296
|
+
when :-
|
297
|
+
output.puts " sub rax, rdi"
|
298
|
+
output.puts " push rax"
|
299
|
+
when :*
|
300
|
+
output.puts " imul rax, rdi"
|
301
|
+
output.puts " push rax"
|
302
|
+
when :/
|
303
|
+
output.puts " cqo"
|
304
|
+
output.puts " idiv rdi"
|
305
|
+
output.puts " push rax"
|
306
|
+
when :==
|
307
|
+
gen_comp("sete", output)
|
308
|
+
when :!=
|
309
|
+
gen_comp("setne", output)
|
310
|
+
when :<
|
311
|
+
gen_comp("setl", output)
|
312
|
+
when :<=
|
313
|
+
gen_comp("setle", output)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
---
|
2
|
+
sources:
|
3
|
+
- type: git
|
4
|
+
name: ruby/gem_rbs_collection
|
5
|
+
revision: 12631190e75c631eca0908ecc8c03bcfd78c0c99
|
6
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
7
|
+
repo_dir: gems
|
8
|
+
path: ".gem_rbs_collection"
|
9
|
+
gems:
|
10
|
+
- name: ast
|
11
|
+
version: '2.4'
|
12
|
+
source:
|
13
|
+
type: git
|
14
|
+
name: ruby/gem_rbs_collection
|
15
|
+
revision: 12631190e75c631eca0908ecc8c03bcfd78c0c99
|
16
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
17
|
+
repo_dir: gems
|
18
|
+
gemfile_lock_path: Gemfile.lock
|
data/rbs_collection.yaml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Download sources
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
|
8
|
+
# A directory to install the downloaded RBSs
|
9
|
+
path: .gem_rbs_collection
|
10
|
+
|
11
|
+
gems:
|
12
|
+
# Skip loading rbs gem's RBS.
|
13
|
+
# It's unnecessary if you don't use rbs as a library.
|
14
|
+
- name: steep
|
15
|
+
ignore: true
|
16
|
+
- name: rbs
|
17
|
+
ignore: true
|
18
|
+
- name: vaporware
|
19
|
+
ignore: true
|
20
|
+
- name: parser
|
21
|
+
- name: set
|
22
|
+
ignore: true
|
data/sample/fiddle.rb
ADDED
data/sample/hello.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
puts "hello"
|
data/sample/if.rb
ADDED
data/sample/method.rb
ADDED
data/sample/plus.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
((1 + 2) * 3) / (5-4)
|
data/sample/variable.rb
ADDED
data/sample/while.rb
ADDED
data/sig/vaporware.rbs
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Vaporware
|
2
|
+
VERSION: String
|
3
|
+
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
|
4
|
+
class Error
|
5
|
+
end
|
6
|
+
class Compiler
|
7
|
+
REGISTER: Array[String]
|
8
|
+
# instance variables
|
9
|
+
@_precompile: String
|
10
|
+
@debug: bool
|
11
|
+
@doned: Set[Symbol]
|
12
|
+
@defined_methods: Set[Symbol]
|
13
|
+
@defined_variables: Set[Symbol]
|
14
|
+
@seq: Integer
|
15
|
+
@main: bool
|
16
|
+
@shared: bool
|
17
|
+
|
18
|
+
# temporarily using untyped types since parser.gem's rbs information is unchecked.
|
19
|
+
@ast: untyped
|
20
|
+
|
21
|
+
# attr reader for instance variables
|
22
|
+
def _precompile: -> String
|
23
|
+
def ast: -> untyped # Parser::AST::Node
|
24
|
+
def defined_methods: -> Set[Symbol]
|
25
|
+
def defined_variables: -> Set[Symbol]
|
26
|
+
def debug: -> bool
|
27
|
+
def doned: -> Set[Symbol]
|
28
|
+
def seq: -> Integer
|
29
|
+
def shared: -> bool
|
30
|
+
|
31
|
+
# class methods
|
32
|
+
def self.compile: (String, ?compiler: String, ?dest: String, ?debug: bool, ?compiler_options: Array[String], ?shared: bool) -> nil
|
33
|
+
def initialize: (String, ?_precompile: String, ?debug: bool, ?shared: bool) -> untyped
|
34
|
+
|
35
|
+
# instance methods
|
36
|
+
def compile: (?compiler: String, ?compiler_options: Array[String]) -> nil
|
37
|
+
|
38
|
+
# instance private methods
|
39
|
+
def already_build_methods?: -> bool
|
40
|
+
def call_compiler: (?output: String, ?compiler: String, ?compiler_options: Array[String]) -> nil
|
41
|
+
def compile_shared_option: () -> Array[String]
|
42
|
+
def gen: (untyped, File, ?bool) -> nil
|
43
|
+
def gen_args: (untyped, File) -> nil
|
44
|
+
def gen_call_method: (untyped, File, bool) -> nil
|
45
|
+
def gen_comp: (String, File) -> nil
|
46
|
+
def gen_lvar: (untyped, File) -> nil
|
47
|
+
def gen_method: (Symbol, untyped, File) -> nil
|
48
|
+
def gen_define_method_prologue: (untyped, File) -> nil
|
49
|
+
def gen_epilogue: (File) -> nil
|
50
|
+
def gen_prologue: (untyped, File) -> nil
|
51
|
+
def gen_prologue_methods: (File) -> nil
|
52
|
+
def gen_ret: (File) -> nil
|
53
|
+
def lvar_offset: (Symbol | nil) -> Integer
|
54
|
+
def register_var_and_method: (untyped) -> nil
|
55
|
+
def variable_or_method?: (Symbol) -> bool
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vaporware-compiler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MATSUMOTO, Katsuyoshi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-05-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: test-unit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: steep
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Vaporware is the vaporware.
|
56
|
+
email:
|
57
|
+
- github@katsyoshi.org
|
58
|
+
executables:
|
59
|
+
- vaporware
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- CHANGELOG.md
|
64
|
+
- Gemfile
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- Steepfile
|
68
|
+
- exe/vaporware
|
69
|
+
- lib/vaporware.rb
|
70
|
+
- lib/vaporware/version.rb
|
71
|
+
- rbs_collection.lock.yaml
|
72
|
+
- rbs_collection.yaml
|
73
|
+
- sample/else.rb
|
74
|
+
- sample/fiddle.rb
|
75
|
+
- sample/hello.rb
|
76
|
+
- sample/if.rb
|
77
|
+
- sample/method.rb
|
78
|
+
- sample/plus.rb
|
79
|
+
- sample/variable.rb
|
80
|
+
- sample/while.rb
|
81
|
+
- sig/vaporware.rbs
|
82
|
+
homepage:
|
83
|
+
licenses:
|
84
|
+
- MIT
|
85
|
+
metadata: {}
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 3.2.0
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubygems_version: 3.4.10
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Vaporware is the vaporware.
|
105
|
+
test_files: []
|