RubyInlineWithoutZenTest 3.12.2
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/History.txt +470 -0
- data/LICENSE.txt +22 -0
- data/Manifest.txt +12 -0
- data/README.md +29 -0
- data/README.txt +138 -0
- data/Rakefile +17 -0
- data/demo/fastmath.rb +27 -0
- data/demo/hello.rb +13 -0
- data/example.rb +86 -0
- data/example2.rb +33 -0
- data/lib/inline/mapping.rb +119 -0
- data/lib/inline/version.rb +3 -0
- data/lib/inline.rb +902 -0
- data/rubyinlinewithoutzentest.gemspec +39 -0
- data/test/test_inline.rb +1059 -0
- data/tutorial/example1.rb +63 -0
- data/tutorial/example2.rb +96 -0
- metadata +127 -0
data/demo/fastmath.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
begin require 'rubygems' rescue LoadError end
|
3
|
+
require 'inline'
|
4
|
+
|
5
|
+
class FastMath
|
6
|
+
def factorial(n)
|
7
|
+
f = 1
|
8
|
+
n.downto(2) { |x| f *= x }
|
9
|
+
return f
|
10
|
+
end
|
11
|
+
inline do |builder|
|
12
|
+
builder.c "
|
13
|
+
long factorial_c(int max) {
|
14
|
+
int i=max, result=1;
|
15
|
+
while (i >= 2) { result *= i--; }
|
16
|
+
return result;
|
17
|
+
}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
math = FastMath.new
|
22
|
+
|
23
|
+
if ARGV.empty? then
|
24
|
+
30000.times do math.factorial(20); end
|
25
|
+
else
|
26
|
+
30000.times do math.factorial_c(20); end
|
27
|
+
end
|
data/demo/hello.rb
ADDED
data/example.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
$:.unshift 'lib'
|
5
|
+
require 'inline'
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
FileUtils.rm_rf File.expand_path("~/.ruby_inline")
|
9
|
+
|
10
|
+
class MyTest
|
11
|
+
|
12
|
+
def factorial(n)
|
13
|
+
f = 1
|
14
|
+
n.downto(2) { |x| f *= x }
|
15
|
+
f
|
16
|
+
end
|
17
|
+
|
18
|
+
inline do |builder|
|
19
|
+
builder.c "
|
20
|
+
long factorial_c(int max) {
|
21
|
+
int i=max, result=1;
|
22
|
+
while (i >= 2) { result *= i--; }
|
23
|
+
return result;
|
24
|
+
}"
|
25
|
+
|
26
|
+
builder.c_raw "
|
27
|
+
static
|
28
|
+
VALUE
|
29
|
+
factorial_c_raw(int argc, VALUE *argv, VALUE self) {
|
30
|
+
int i=FIX2INT(argv[0]), result=1;
|
31
|
+
while (i >= 2) { result *= i--; }
|
32
|
+
return INT2NUM(result);
|
33
|
+
}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# breakeven for build run vs native doing 5 factorial:
|
38
|
+
# on a PIII/750 running FreeBSD: about 5000
|
39
|
+
# on a PPC/G4/800 running Mac OSX 10.2: always faster
|
40
|
+
|
41
|
+
require 'benchmark'
|
42
|
+
puts "RubyInline #{Inline::VERSION}" if $DEBUG
|
43
|
+
|
44
|
+
MyTest.send(:alias_method, :factorial_alias, :factorial_c_raw)
|
45
|
+
|
46
|
+
t = MyTest.new()
|
47
|
+
max = (ARGV.shift || 1_000_000).to_i
|
48
|
+
n = (ARGV.shift || 5).to_i
|
49
|
+
m = t.factorial(n)
|
50
|
+
|
51
|
+
def validate(n, m)
|
52
|
+
if n != m then raise "#{n} != #{m}"; end
|
53
|
+
end
|
54
|
+
|
55
|
+
puts "# of iterations = #{max}, n = #{n}"
|
56
|
+
Benchmark::bm(20) do |x|
|
57
|
+
x.report("null_time") do
|
58
|
+
for i in 0..max do
|
59
|
+
# do nothing
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
x.report("c") do
|
64
|
+
for i in 0..max do
|
65
|
+
validate(t.factorial_c(n), m)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
x.report("c-raw") do
|
70
|
+
for i in 0..max do
|
71
|
+
validate(t.factorial_c_raw(n), m)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
x.report("c-alias") do
|
76
|
+
for i in 0..max do
|
77
|
+
validate(t.factorial_alias(n), m)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
x.report("pure ruby") do
|
82
|
+
for i in 0..max do
|
83
|
+
validate(t.factorial(n), m)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/example2.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/local/bin/ruby17 -w
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
rescue LoadError
|
6
|
+
$: << 'lib'
|
7
|
+
end
|
8
|
+
require 'inline'
|
9
|
+
|
10
|
+
class MyTest
|
11
|
+
|
12
|
+
inline do |builder|
|
13
|
+
|
14
|
+
builder.add_compile_flags %q(-x c++)
|
15
|
+
builder.add_link_flags %q(-lstdc++)
|
16
|
+
|
17
|
+
builder.include "<iostream>"
|
18
|
+
|
19
|
+
builder.c "
|
20
|
+
static
|
21
|
+
void
|
22
|
+
hello(int i) {
|
23
|
+
while (i-- > 0) {
|
24
|
+
std::cout << \"hello\" << std::endl;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
t = MyTest.new()
|
32
|
+
|
33
|
+
t.hello(3)
|
@@ -0,0 +1,119 @@
|
|
1
|
+
##
|
2
|
+
# Inline::Mapping - mapping method names from impl to test.
|
3
|
+
#
|
4
|
+
# Method names are mapped bidirectionally in the following way:
|
5
|
+
#
|
6
|
+
# method test_method
|
7
|
+
# method? test_method_eh (too much exposure to Canadians :)
|
8
|
+
# method! test_method_bang
|
9
|
+
# method= test_method_equals
|
10
|
+
# [] test_index
|
11
|
+
# * test_times
|
12
|
+
# == test_equals2
|
13
|
+
# === test_equals3
|
14
|
+
#
|
15
|
+
# Further, any of the test methods should be able to have arbitrary
|
16
|
+
# extensions put on the name to distinguish edge cases:
|
17
|
+
#
|
18
|
+
# method test_method
|
19
|
+
# method test_method_simple
|
20
|
+
# method test_method_no_network
|
21
|
+
#
|
22
|
+
# To allow for unmapped test methods (ie, non-unit tests), name them:
|
23
|
+
#
|
24
|
+
# test_integration_.*
|
25
|
+
|
26
|
+
module Inline
|
27
|
+
module Mapping
|
28
|
+
|
29
|
+
@@orig_method_map = {
|
30
|
+
'!' => 'bang',
|
31
|
+
'%' => 'percent',
|
32
|
+
'&' => 'and',
|
33
|
+
'*' => 'times',
|
34
|
+
'**' => 'times2',
|
35
|
+
'+' => 'plus',
|
36
|
+
'-' => 'minus',
|
37
|
+
'/' => 'div',
|
38
|
+
'<' => 'lt',
|
39
|
+
'<=' => 'lte',
|
40
|
+
'<=>' => 'spaceship',
|
41
|
+
"<\<" => 'lt2',
|
42
|
+
'==' => 'equals2',
|
43
|
+
'===' => 'equals3',
|
44
|
+
'=~' => 'equalstilde',
|
45
|
+
'>' => 'gt',
|
46
|
+
'>=' => 'ge',
|
47
|
+
'>>' => 'gt2',
|
48
|
+
'+@' => 'unary_plus',
|
49
|
+
'-@' => 'unary_minus',
|
50
|
+
'[]' => 'index',
|
51
|
+
'[]=' => 'index_equals',
|
52
|
+
'^' => 'carat',
|
53
|
+
'|' => 'or',
|
54
|
+
'~' => 'tilde',
|
55
|
+
}
|
56
|
+
|
57
|
+
@@method_map = @@orig_method_map.merge(@@orig_method_map.invert)
|
58
|
+
|
59
|
+
@@mapped_re = @@orig_method_map.values.sort_by { |k| k.length }.map {|s|
|
60
|
+
Regexp.escape(s)
|
61
|
+
}.reverse.join("|")
|
62
|
+
|
63
|
+
def munge name
|
64
|
+
name = name.to_s.dup
|
65
|
+
|
66
|
+
is_cls_method = name.sub!(/^self\./, '')
|
67
|
+
|
68
|
+
name = @@method_map[name] if @@method_map.has_key? name
|
69
|
+
name = name.sub(/=$/, '_equals')
|
70
|
+
name = name.sub(/\?$/, '_eh')
|
71
|
+
name = name.sub(/\!$/, '_bang')
|
72
|
+
|
73
|
+
name = yield name if block_given?
|
74
|
+
|
75
|
+
name = "class_" + name if is_cls_method
|
76
|
+
|
77
|
+
name
|
78
|
+
end
|
79
|
+
|
80
|
+
# Generates a test method name from a normal method,
|
81
|
+
# taking into account names composed of metacharacters
|
82
|
+
# (used for arithmetic, etc
|
83
|
+
def normal_to_test name
|
84
|
+
"test_#{munge name}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def unmunge name
|
88
|
+
name = name.to_s.dup
|
89
|
+
|
90
|
+
is_cls_method = name.sub!(/^class_/, '')
|
91
|
+
|
92
|
+
name = name.sub(/_equals(_.*)?$/, '=') unless name =~ /index/
|
93
|
+
name = name.sub(/_bang(_.*)?$/, '!')
|
94
|
+
name = name.sub(/_eh(_.*)?$/, '?')
|
95
|
+
name = name.sub(/^(#{@@mapped_re})(_.*)?$/) {$1}
|
96
|
+
name = yield name if block_given?
|
97
|
+
name = @@method_map[name] if @@method_map.has_key? name
|
98
|
+
name = 'self.' + name if is_cls_method
|
99
|
+
|
100
|
+
name
|
101
|
+
end
|
102
|
+
|
103
|
+
# Converts a method name beginning with test to its
|
104
|
+
# corresponding normal method name, taking into account
|
105
|
+
# symbolic names which may have been anglicised by
|
106
|
+
# #normal_to_test().
|
107
|
+
def test_to_normal(name, klassname=nil)
|
108
|
+
unmunge(name.to_s.sub(/^test_/, '')) do |n|
|
109
|
+
if defined? @inherited_methods then
|
110
|
+
known_methods = (@inherited_methods[klassname] || {}).keys.sort.reverse
|
111
|
+
known_methods_re = known_methods.map {|s| Regexp.escape(s) }.join("|")
|
112
|
+
n = n.sub(/^(#{known_methods_re})(_.*)?$/) { $1 } unless
|
113
|
+
known_methods_re.empty?
|
114
|
+
n
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|