rinline 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/.gitignore +9 -0
- data/Gemfile +4 -0
- data/README.md +44 -0
- data/Rakefile +9 -0
- data/benchmark/simple.rb +36 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rinline.rb +22 -0
- data/lib/rinline/ext/ast_ext.rb +181 -0
- data/lib/rinline/ext/iseq_ext.rb +11 -0
- data/lib/rinline/ext/method_ext.rb +40 -0
- data/lib/rinline/location.rb +14 -0
- data/lib/rinline/optimizer.rb +155 -0
- data/lib/rinline/runner.rb +57 -0
- data/lib/rinline/version.rb +3 -0
- data/rinline.gemspec +34 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dc0964e6130a5e6bd8f80a5ada38a861082d5576b012c5557e90c07646942d76
|
4
|
+
data.tar.gz: c3a30e6a0c4c5de9c4e003abc2ace61c17a92cb375296de967ffff58e1acb308
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 115a1a1f849277b1725e6c32555e9a85acc39a18dbcc5d7738a0825c3df0921f788dea8b1e34ccf3337d1add62aafe483c5178bd8c07ad1a4ad794b9b1809864
|
7
|
+
data.tar.gz: 5d00f2b9fccf4811176f91a4e3e96c7a966041c4bf0b4c2d719ee451944d0aa47c7525d035e3b116bd70509e99a3503f21c9cfc56e9b1c7f0a6b40b3cb12ba13
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Rinline
|
2
|
+
|
3
|
+
Inline expansion for Ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'rinline'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install rinline
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Call `Rinline.optimize` after your program is loaded, but before your program is not ran yet.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'your_program'
|
27
|
+
require 'rinline'
|
28
|
+
|
29
|
+
Rinline.optimize do |r|
|
30
|
+
r.optimize_namespace(YourProgram)
|
31
|
+
end
|
32
|
+
|
33
|
+
YourProgram.start
|
34
|
+
```
|
35
|
+
|
36
|
+
## Development
|
37
|
+
|
38
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
39
|
+
|
40
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pocke/rinline.
|
data/Rakefile
ADDED
data/benchmark/simple.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# $ ruby benchmark/simple.rb
|
2
|
+
# user system total real
|
3
|
+
# plain 6.203292 0.000000 6.203292 ( 6.206694)
|
4
|
+
# optimized 3.623372 0.000000 3.623372 ( 3.625261)
|
5
|
+
|
6
|
+
require 'benchmark'
|
7
|
+
|
8
|
+
class C
|
9
|
+
def plain
|
10
|
+
m + n
|
11
|
+
end
|
12
|
+
|
13
|
+
def optimized
|
14
|
+
m + n
|
15
|
+
end
|
16
|
+
|
17
|
+
def m
|
18
|
+
1
|
19
|
+
end
|
20
|
+
|
21
|
+
def n
|
22
|
+
2
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'rinline'
|
27
|
+
Rinline.optimize do |r|
|
28
|
+
r.optimize_instance_method(C, :optimized)
|
29
|
+
end
|
30
|
+
|
31
|
+
i = C.new
|
32
|
+
|
33
|
+
Benchmark.bm(20) do |x|
|
34
|
+
x.report('plain') { 100000000.times { i.plain } }
|
35
|
+
x.report('optimized') { 100000000.times { i.optimized } }
|
36
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "rinline"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/rinline.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
require_relative "./rinline/version"
|
4
|
+
require_relative './rinline/ext/iseq_ext'
|
5
|
+
require_relative './rinline/ext/ast_ext'
|
6
|
+
require_relative './rinline/ext/method_ext'
|
7
|
+
require_relative './rinline/optimizer'
|
8
|
+
require_relative './rinline/location'
|
9
|
+
require_relative './rinline/runner'
|
10
|
+
|
11
|
+
module Rinline
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def optimize(&block)
|
15
|
+
runner = Runner.new
|
16
|
+
Runner.current = runner
|
17
|
+
block.call runner
|
18
|
+
Runner.current = nil
|
19
|
+
|
20
|
+
$stderr.puts "[Rinline] Optimizing is finised" if runner.debug
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module Rinline
|
2
|
+
module Ext
|
3
|
+
module AstExt
|
4
|
+
refine RubyVM::AbstractSyntaxTree::Node do
|
5
|
+
def traverse(&block)
|
6
|
+
opt = {}
|
7
|
+
block.call self, opt
|
8
|
+
|
9
|
+
# workaround for modifiers
|
10
|
+
# TODO: Remove this workaround by refining offset
|
11
|
+
if ((type == :IF || type == :UNLESS) && children[2] == nil && children[1].before_than(children[0])) ||
|
12
|
+
((type == :WHILE || type == :UNTIL) && children[1].before_than(children[0]))
|
13
|
+
children[1].traverse(&block)
|
14
|
+
children[0].traverse(&block)
|
15
|
+
else
|
16
|
+
self.children.each.with_index do |child, index|
|
17
|
+
next if opt[:ignore_index] == index
|
18
|
+
child.traverse(&block) if child.is_a?(RubyVM::AbstractSyntaxTree::Node)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_source(path)
|
24
|
+
file(path)[first_index(path)..last_index(path)]
|
25
|
+
end
|
26
|
+
|
27
|
+
def location(path)
|
28
|
+
Location.new(first_index(path), last_index(path))
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_child?(*types)
|
32
|
+
traverse do |child|
|
33
|
+
return true if child.is_a?(RubyVM::AbstractSyntaxTree::Node) && types.include?(child.type)
|
34
|
+
end
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
# var = 1
|
39
|
+
# ^^^
|
40
|
+
def location_variable_name_of_lasgn(path)
|
41
|
+
type! :LASGN
|
42
|
+
first_index = first_index(path)
|
43
|
+
|
44
|
+
Location.new(first_index, first_index + self.children[0].size - 1)
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_body
|
48
|
+
type! :SCOPE
|
49
|
+
self.children[2]
|
50
|
+
end
|
51
|
+
|
52
|
+
def method_args
|
53
|
+
type! :SCOPE
|
54
|
+
self.children[1]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Extensions for ARGS
|
58
|
+
def args_pre_num
|
59
|
+
type! :ARGS
|
60
|
+
self.children[0]
|
61
|
+
end
|
62
|
+
|
63
|
+
def args_pre_init
|
64
|
+
type! :ARGS
|
65
|
+
self.children[1]
|
66
|
+
end
|
67
|
+
|
68
|
+
def args_opt
|
69
|
+
type! :ARGS
|
70
|
+
self.children[2]
|
71
|
+
end
|
72
|
+
|
73
|
+
def args_first_post
|
74
|
+
type! :ARGS
|
75
|
+
self.children[3]
|
76
|
+
end
|
77
|
+
|
78
|
+
def args_post_num
|
79
|
+
type! :ARGS
|
80
|
+
self.children[4]
|
81
|
+
end
|
82
|
+
|
83
|
+
def args_post_init
|
84
|
+
type! :ARGS
|
85
|
+
self.children[5]
|
86
|
+
end
|
87
|
+
|
88
|
+
def args_rest
|
89
|
+
type! :ARGS
|
90
|
+
self.children[6]
|
91
|
+
end
|
92
|
+
|
93
|
+
def args_kw
|
94
|
+
type! :ARGS
|
95
|
+
self.children[7]
|
96
|
+
end
|
97
|
+
|
98
|
+
def args_kwrest
|
99
|
+
type! :ARGS
|
100
|
+
self.children[8]
|
101
|
+
end
|
102
|
+
|
103
|
+
def args_block
|
104
|
+
type! :ARGS
|
105
|
+
self.children[9]
|
106
|
+
end
|
107
|
+
|
108
|
+
def expandable_method?(parameter_size)
|
109
|
+
a = self.method_args
|
110
|
+
a.args_pre_num == parameter_size &&
|
111
|
+
a.args_pre_init == nil &&
|
112
|
+
a.args_opt == nil &&
|
113
|
+
a.args_first_post == nil &&
|
114
|
+
a.args_post_num == 0 &&
|
115
|
+
a.args_post_init == nil &&
|
116
|
+
a.args_rest == nil &&
|
117
|
+
a.args_kw == nil &&
|
118
|
+
a.args_kwrest == nil &&
|
119
|
+
a.args_block == nil
|
120
|
+
end
|
121
|
+
|
122
|
+
def array_size
|
123
|
+
type! :ARRAY
|
124
|
+
self.children.size - 1
|
125
|
+
end
|
126
|
+
|
127
|
+
def array_content
|
128
|
+
type! :ARRAY
|
129
|
+
self.children[0..-2]
|
130
|
+
end
|
131
|
+
|
132
|
+
def fcall_args
|
133
|
+
type! :FCALL
|
134
|
+
self.children[1]
|
135
|
+
end
|
136
|
+
|
137
|
+
def lasgn_opasgn?
|
138
|
+
type! :LASGN
|
139
|
+
right = children[1]
|
140
|
+
first_lineno == right.first_lineno &&
|
141
|
+
first_column == right.first_column
|
142
|
+
end
|
143
|
+
|
144
|
+
private def first_index(path)
|
145
|
+
return first_column if first_lineno == 1
|
146
|
+
|
147
|
+
lines = file(path).split("\n")
|
148
|
+
lines[0..(first_lineno - 2)].sum(&:size) +
|
149
|
+
first_lineno - 1 + # For \n
|
150
|
+
first_column
|
151
|
+
end
|
152
|
+
|
153
|
+
private def last_index(path)
|
154
|
+
last_column = self.last_column - 1
|
155
|
+
return last_column if last_lineno == 1
|
156
|
+
|
157
|
+
lines = file(path).split("\n")
|
158
|
+
lines[0..(last_lineno - 2)].sum(&:size) +
|
159
|
+
last_lineno - 1 + # For \n
|
160
|
+
last_column
|
161
|
+
end
|
162
|
+
|
163
|
+
private def type!(type)
|
164
|
+
raise "Unexpected type: #{self.type}" unless self.type == type
|
165
|
+
end
|
166
|
+
|
167
|
+
def before_than(right)
|
168
|
+
if self.first_lineno == right.first_lineno
|
169
|
+
self.first_column < right.first_column
|
170
|
+
else
|
171
|
+
self.first_lineno < right.first_lineno
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
private def file(path)
|
176
|
+
Runner.current.file_cache[path] ||= File.binread(path)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rinline
|
2
|
+
module Ext
|
3
|
+
module MethodExt
|
4
|
+
refine UnboundMethod do
|
5
|
+
using IseqExt
|
6
|
+
using AstExt
|
7
|
+
|
8
|
+
def to_ast
|
9
|
+
RubyVM::AbstractSyntaxTree.of(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_iseq
|
13
|
+
RubyVM::InstructionSequence.of(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def expandable?
|
17
|
+
ruby_method? &&
|
18
|
+
to_iseq&.short? &&
|
19
|
+
!eval? &&
|
20
|
+
!to_ast.has_child?(:SUPER, :ZSUPER, :RETURN, :CONST) &&
|
21
|
+
# HACK: RubyVM::AST omits `return` from tree if it is meaningless.
|
22
|
+
# So checking AST is not enough.
|
23
|
+
!to_ast.to_source(absolute_path).match?(/\breturn\b/)
|
24
|
+
end
|
25
|
+
|
26
|
+
def ruby_method?
|
27
|
+
!!source_location
|
28
|
+
end
|
29
|
+
|
30
|
+
def eval?
|
31
|
+
absolute_path == '(eval)'
|
32
|
+
end
|
33
|
+
|
34
|
+
def absolute_path
|
35
|
+
source_location[0]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Rinline
|
2
|
+
class Optimizer
|
3
|
+
using Ext::MethodExt
|
4
|
+
using Ext::AstExt
|
5
|
+
using Ext::IseqExt
|
6
|
+
|
7
|
+
# @param klass [Class]
|
8
|
+
# @param method_name [Symbol] an instance method name
|
9
|
+
# @return [String,nil] optimized code if optimized
|
10
|
+
def self.optimize(klass, method_name)
|
11
|
+
self.new(klass, method_name).optimize
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(klass, method_name)
|
15
|
+
@klass = klass
|
16
|
+
@method_name = method_name
|
17
|
+
@method = klass.instance_method(method_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def optimize
|
21
|
+
return unless method.ruby_method?
|
22
|
+
return if method.eval?
|
23
|
+
ast = method.to_ast
|
24
|
+
return unless ast
|
25
|
+
return if ast.has_child?(:CONST)
|
26
|
+
path = method.absolute_path
|
27
|
+
replacements = []
|
28
|
+
|
29
|
+
ast.traverse do |node, opt|
|
30
|
+
case node.type
|
31
|
+
when :VCALL
|
32
|
+
target_method_name = node.children[0]
|
33
|
+
next if method_name == target_method_name
|
34
|
+
target_method =
|
35
|
+
begin
|
36
|
+
klass.instance_method(target_method_name)
|
37
|
+
rescue NameError
|
38
|
+
next
|
39
|
+
end
|
40
|
+
next unless target_method.expandable?
|
41
|
+
|
42
|
+
to_ast = target_method.to_ast
|
43
|
+
next unless to_ast.expandable_method?(0)
|
44
|
+
|
45
|
+
to_path = target_method.absolute_path
|
46
|
+
body = to_ast.method_body
|
47
|
+
to_code =
|
48
|
+
if body
|
49
|
+
"((#{replace_lvar(body, to_path)}))"
|
50
|
+
else
|
51
|
+
"()"
|
52
|
+
end
|
53
|
+
replacements << {
|
54
|
+
from: node.location(path),
|
55
|
+
to: to_code,
|
56
|
+
}
|
57
|
+
when :FCALL
|
58
|
+
target_method_name = node.children[0]
|
59
|
+
next if method_name == target_method_name
|
60
|
+
target_method =
|
61
|
+
begin
|
62
|
+
klass.instance_method(target_method_name)
|
63
|
+
rescue NameError
|
64
|
+
next
|
65
|
+
end
|
66
|
+
next unless target_method.expandable?
|
67
|
+
|
68
|
+
to_ast = target_method.to_ast
|
69
|
+
args = node.fcall_args
|
70
|
+
next unless args&.type == :ARRAY
|
71
|
+
next unless to_ast.expandable_method?(args.array_size)
|
72
|
+
|
73
|
+
to_path = target_method.absolute_path
|
74
|
+
lvar_suffix = gen_lvar_suffix
|
75
|
+
|
76
|
+
args = assign_args(to_ast, node, path, lvar_suffix)
|
77
|
+
body =
|
78
|
+
if to_ast.method_body
|
79
|
+
replace_lvar(to_ast.method_body, to_path, lvar_suffix: lvar_suffix)
|
80
|
+
else
|
81
|
+
"()"
|
82
|
+
end
|
83
|
+
to_code = "((#{args}#{body}))"
|
84
|
+
replacements << {
|
85
|
+
from: node.location(path),
|
86
|
+
to: to_code
|
87
|
+
}
|
88
|
+
opt[:ignore_index] = 1 # Ignore arguments
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
return if replacements.empty?
|
93
|
+
return replace(ast, path, replacements).force_encoding(Encoding::UTF_8) # TODO: Support other encodings
|
94
|
+
end
|
95
|
+
|
96
|
+
attr_reader :klass, :method_name, :method
|
97
|
+
private :klass, :method_name, :method
|
98
|
+
|
99
|
+
# @param original_method [Method]
|
100
|
+
# @param replacements [Array<{from: Rinline::Location, to: String}>]
|
101
|
+
private def replace(original_ast, original_path, replacements)
|
102
|
+
ret = original_ast.to_source(original_path)
|
103
|
+
offset = -original_ast.location(original_path).first_index
|
104
|
+
|
105
|
+
replacements.each do |replacement|
|
106
|
+
from = replacement[:from]
|
107
|
+
to_code = replacement[:to]
|
108
|
+
|
109
|
+
ret[(from.first_index + offset)..(from.last_index + offset)] = to_code
|
110
|
+
offset += to_code.size - from.size
|
111
|
+
end
|
112
|
+
|
113
|
+
ret
|
114
|
+
end
|
115
|
+
|
116
|
+
private def replace_lvar(ast, path, lvar_suffix: gen_lvar_suffix)
|
117
|
+
replacements = []
|
118
|
+
|
119
|
+
ast.traverse do |node, opt|
|
120
|
+
case node.type
|
121
|
+
when :LASGN
|
122
|
+
next if node.lasgn_opasgn?
|
123
|
+
|
124
|
+
replacements << {
|
125
|
+
from: node.location_variable_name_of_lasgn(path),
|
126
|
+
to: "#{node.children[0]}#{lvar_suffix}",
|
127
|
+
}
|
128
|
+
when :LVAR
|
129
|
+
replacements << {
|
130
|
+
from: node.location(path),
|
131
|
+
to: "#{node.children[0]}#{lvar_suffix}"
|
132
|
+
}
|
133
|
+
when :OP_ASGN_OR
|
134
|
+
opt[:ignore_index] = 0
|
135
|
+
when :OP_ASGN_AND
|
136
|
+
opt[:ignore_index] = 0
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
replace(ast, path, replacements)
|
141
|
+
end
|
142
|
+
|
143
|
+
private def assign_args(method_node, fcall_node, fcall_path, lvar_suffix)
|
144
|
+
params = method_node.children[0]
|
145
|
+
args = fcall_node.fcall_args.array_content
|
146
|
+
args.map.with_index do |arg, index|
|
147
|
+
"#{params[index]}#{lvar_suffix} = #{arg.to_source(fcall_path)}"
|
148
|
+
end.join(';') + ';'
|
149
|
+
end
|
150
|
+
|
151
|
+
private def gen_lvar_suffix
|
152
|
+
"__#{SecureRandom.hex(5)}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Rinline
|
2
|
+
class Runner
|
3
|
+
class << self
|
4
|
+
attr_accessor :current
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_accessor :debug, :iseq_threshold
|
8
|
+
attr_reader :file_cache
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@debug = false
|
12
|
+
@iseq_threshold = 50
|
13
|
+
@file_cache = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def optimize_instance_method(klass, method_name)
|
17
|
+
debug_print "optimizing: #{klass}##{method_name}"
|
18
|
+
optimized = Optimizer.optimize(klass, method_name)
|
19
|
+
unless optimized
|
20
|
+
debug_print "skipped: #{klass}##{method_name}"
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
klass.class_eval "undef :#{method_name}; #{optimized}"
|
25
|
+
debug_print "optimized: #{klass}##{method_name}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def optimize_instance_methods(klass)
|
29
|
+
klass.instance_methods(false).each do |method|
|
30
|
+
optimize_instance_method(klass, method)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def optimize_class(klass)
|
35
|
+
debug_print "class: #{klass}"
|
36
|
+
optimize_instance_methods(klass)
|
37
|
+
optimize_instance_methods(klass.singleton_class)
|
38
|
+
end
|
39
|
+
|
40
|
+
alias optimize_module optimize_class
|
41
|
+
|
42
|
+
def optimize_namespace(mod)
|
43
|
+
debug_print "namespace: #{mod}"
|
44
|
+
optimize_module(mod)
|
45
|
+
constants = mod.constants
|
46
|
+
constants -= Struct.constants if mod < Struct
|
47
|
+
constants.each do |child|
|
48
|
+
child = mod.const_get(child)
|
49
|
+
optimize_namespace(child) if child.is_a?(Module)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def debug_print(*msg)
|
54
|
+
$stderr.puts(*msg) if debug
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/rinline.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "rinline/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rinline"
|
7
|
+
spec.version = Rinline::VERSION
|
8
|
+
spec.authors = ["Masataka Pocke Kuwabara"]
|
9
|
+
spec.email = ["kuwabara@pocke.me"]
|
10
|
+
|
11
|
+
spec.summary = %q{Inline expansion for Ruby}
|
12
|
+
spec.description = %q{Inline expansion for Ruby}
|
13
|
+
spec.homepage = "https://github.com/pocke/rinline"
|
14
|
+
|
15
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
19
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", ">= 2"
|
31
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
32
|
+
spec.add_development_dependency 'minitest', '>= 5'
|
33
|
+
spec.add_development_dependency 'rr'
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rinline
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Masataka Pocke Kuwabara
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rr
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Inline expansion for Ruby
|
70
|
+
email:
|
71
|
+
- kuwabara@pocke.me
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- Gemfile
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- benchmark/simple.rb
|
81
|
+
- bin/console
|
82
|
+
- bin/setup
|
83
|
+
- lib/rinline.rb
|
84
|
+
- lib/rinline/ext/ast_ext.rb
|
85
|
+
- lib/rinline/ext/iseq_ext.rb
|
86
|
+
- lib/rinline/ext/method_ext.rb
|
87
|
+
- lib/rinline/location.rb
|
88
|
+
- lib/rinline/optimizer.rb
|
89
|
+
- lib/rinline/runner.rb
|
90
|
+
- lib/rinline/version.rb
|
91
|
+
- rinline.gemspec
|
92
|
+
homepage: https://github.com/pocke/rinline
|
93
|
+
licenses: []
|
94
|
+
metadata:
|
95
|
+
homepage_uri: https://github.com/pocke/rinline
|
96
|
+
source_code_uri: https://github.com/pocke/rinline
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubygems_version: 3.0.3
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: Inline expansion for Ruby
|
116
|
+
test_files: []
|