vaporware-compiler 0.1.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 +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: []
|