rusby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 220468d5f249c9e28f702ff82cc05857fec824a3
4
+ data.tar.gz: ac156b073759a711c1889f0d4cdb39fedc823ff7
5
+ SHA512:
6
+ metadata.gz: addbb61765e9957e47af6b79f28cbc17597144997e667728f71628d93a80c231e8e3ba0efc1b7806f851c194ab5560540c8de0dba746ad17ae8e4d1ee38e2ae2
7
+ data.tar.gz: 80795fd42665c369763f4d72ecba264a977ecd3c5cc808e08dc6aef13886770e597f93cbfebc1aaa6fee55a47ee359c7da59c5e7e166d7b412044867923b000e
@@ -0,0 +1,3 @@
1
+ .byebug_history
2
+ examples/tmp/rusby
3
+ pkg
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.2
5
+ before_install: gem install bundler -v 1.12.4
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at akrasnoschekov@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rusby.gemspec
4
+ gemspec
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rusby (0.1.0)
5
+ colorize
6
+ ffi
7
+ hashie
8
+ method_source
9
+ parser
10
+ ruby-prof
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ ast (2.2.0)
16
+ byebug (9.0.5)
17
+ colorize (0.7.7)
18
+ diff-lcs (1.2.5)
19
+ ffi (1.9.10)
20
+ hashie (3.4.4)
21
+ method_source (0.8.2)
22
+ parser (2.3.1.0)
23
+ ast (~> 2.2)
24
+ rake (10.5.0)
25
+ rspec (3.4.0)
26
+ rspec-core (~> 3.4.0)
27
+ rspec-expectations (~> 3.4.0)
28
+ rspec-mocks (~> 3.4.0)
29
+ rspec-core (3.4.4)
30
+ rspec-support (~> 3.4.0)
31
+ rspec-expectations (3.4.0)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.4.0)
34
+ rspec-mocks (3.4.1)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.4.0)
37
+ rspec-support (3.4.1)
38
+ ruby-prof (0.15.9)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ bundler (~> 1.12)
45
+ byebug
46
+ rake (~> 10.0)
47
+ rspec (~> 3.0)
48
+ rusby!
49
+
50
+ BUNDLED WITH
51
+ 1.12.4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Alexander Krasnoschekov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ ## About
2
+
3
+ **Rusby** is a *Ruby* to *Rust* transpiler for simple performance-oriented methods.
4
+
5
+ Computations in plain Ruby are painfully slow.
6
+ Almost all internal methods in of Ruby are implemented in C, thus achieving acceptable performance on e.g. [Array#sort](https://github.com/ruby/ruby/blob/trunk/array.c).
7
+
8
+ On the other hand extension of ruby code with C or other low-level language functions is not to say hard... but at least is tricky. **Rusby** allows to write simple methods in plain ruby and convert them to rust with zero modifications.
9
+
10
+ Just mark method with `rusby!` and you are ready to rust :/
11
+
12
+ ![Quicksort example](https://raw.githubusercontent.com/rambler-digital-solutions/rusby/master/doc/img1.png)
13
+
14
+ ---
15
+
16
+ N.B. It's a research project, so at least test for edge cases (e.g. overflows) before production usage.
17
+
18
+ Transpilation was tested only on cases in `./examples` directory.
19
+
20
+ ---
21
+
22
+ ## How it works?
23
+
24
+ 1. You prefix your method definition with `!rusby`.
25
+ 1. Native Ruby method is ran for the first time.
26
+ 1. Its arguments types and return type are recorded.
27
+ 1. These data along with source code of the method (as AST tree) are passed to the Rusby::Builder.
28
+ 1. Rusby::Builder calls Rusby::Rust, which recursively generates rust code based on AST tree (Rusby::Generators::\*).
29
+ 1. Few hacks are applied along the way, see Rusby::Preprocessor, Rusby::Postrocessor.
30
+ 1. Generated Rust code is dumped to file into `./lib` Dir
31
+ 1. Rust code is prettified and compiled into dynamic lib.
32
+ 1. At last we have ruby method and rust counterpart linked via [FFI](https://github.com/ffi/ffi).
33
+ 1. Benchmark them and find the fastest one.
34
+ 1. Link the winner into the source class.
35
+ 1. Profit.
36
+
37
+ ## Features
38
+ - In-place ruby/rust method swapping based on benchmarks
39
+ - Recursive calls transpiling
40
+ - Nested functions transpiling
41
+ - Limited string operations support
42
+ - Integer matrix manipulation support
43
+
44
+ ## Quickstart
45
+ ```
46
+ brew install rust # or similar
47
+ cd examples
48
+ bundle
49
+ ruby run_examples.rb
50
+ ```
51
+
52
+ ## Tests
53
+ ```
54
+ rake spec
55
+ ```
56
+
57
+ ## Contributing
58
+
59
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rusby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
60
+
61
+
62
+ ## License
63
+
64
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,12 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |task|
5
+ task.rspec_opts = [
6
+ '--color',
7
+ '--require',
8
+ 'spec_helper'
9
+ ]
10
+ end
11
+
12
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rusby"
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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rusby', path: '..'
@@ -0,0 +1,31 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ rusby (0.1.0)
5
+ colorize
6
+ ffi
7
+ hashie
8
+ method_source
9
+ parser
10
+ ruby-prof
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ ast (2.2.0)
16
+ colorize (0.7.7)
17
+ ffi (1.9.10)
18
+ hashie (3.4.4)
19
+ method_source (0.8.2)
20
+ parser (2.3.1.0)
21
+ ast (~> 2.2)
22
+ ruby-prof (0.15.9)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ rusby!
29
+
30
+ BUNDLED WITH
31
+ 1.12.4
@@ -0,0 +1,8 @@
1
+ class FanaticGreeter
2
+ extend Rusby::Core
3
+
4
+ rusby!
5
+ def greet(name)
6
+ "Hello, #{name}!"
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class FanaticPluser
2
+ extend Rusby::Core
3
+
4
+ rusby!
5
+ def plusplus(number)
6
+ number + 1
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ class LevenshteinDistance
2
+ extend Rusby::Core
3
+
4
+ rusby!
5
+ def distance(s, t)
6
+ m = s.length
7
+ n = t.length
8
+
9
+ return m if n == 0
10
+ return n if m == 0
11
+ d = Array.new(m + 1) { Array.new(n + 1) }
12
+
13
+ (0..m).each { |i| d[i][0] = i }
14
+ (0..n).each { |j| d[0][j] = j }
15
+
16
+ (1..n).each do |j|
17
+ (1..m).each do |i|
18
+ d[i][j] = if s[i - 1] == t[j - 1] # adjust index into string
19
+ d[i - 1][j - 1] # no operation required
20
+ else
21
+ deletion = d[i - 1][j] + 1
22
+ insertion = d[i][j - 1] + 1
23
+ substitution = d[i - 1][j - 1] + 1
24
+ op = deletion < insertion ? deletion : insertion
25
+ op < substitution ? op : substitution
26
+ end
27
+ end
28
+ end
29
+ return d[m][n]
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ class Quicksort
2
+ extend Rusby::Core
3
+
4
+ rusby!
5
+ def quicksort(a, lo, hi)
6
+ return a unless lo < hi
7
+ pivot = partition(a, lo, hi)
8
+ quicksort(a, lo, pivot)
9
+ quicksort(a, pivot + 1, hi)
10
+ a
11
+ end
12
+
13
+ private
14
+
15
+ def partition(a, lo, hi)
16
+ pivot = a[lo]
17
+ i = lo - 1
18
+ j = hi + 1
19
+ loop do
20
+ begin
21
+ i += 1
22
+ end while a[i] < pivot
23
+
24
+ begin
25
+ j -= 1
26
+ end while a[j] > pivot
27
+
28
+ return j if i >= j
29
+ a[i], a[j] = [a[j], a[i]]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ Bundler.require
5
+ require "./fanatic_pluser"
6
+ require "./fanatic_greeter"
7
+ require "./quicksort"
8
+ require "./levenshtein_distance"
9
+ require "./weighted_random"
10
+
11
+ pluser = FanaticPluser.new
12
+ 2.times do |i|
13
+ puts "== #{i + 1} - #{pluser.plusplus(77)}"
14
+ end
15
+
16
+ greeter = FanaticGreeter.new
17
+ 2.times do |_i|
18
+ puts greeter.greet('Fred')
19
+ end
20
+
21
+ sorter = Quicksort.new
22
+ a = (1..50).map { |_i| rand(100_000) }
23
+ 2.times do |i|
24
+ puts "=> #{i + 1} time method is being called".colorize(:light_black)
25
+ puts "== #{i + 1} - #{sorter.quicksort(a.clone, 0, a.size - 1)}"
26
+ end
27
+
28
+ measurer = LevenshteinDistance.new
29
+ params = %w(unimaginatively incomprehensibilities)
30
+ 2.times do |i|
31
+ puts "#{i + 1}: #{measurer.distance(*params)}"
32
+ end
33
+
34
+ randomizer = WeightedRandom.new
35
+ weights = (1..1000).map { rand(1000).to_f }
36
+ 2.times do |i|
37
+ puts "#{i + 1}: #{randomizer.pick(weights, rand())}"
38
+ end
@@ -0,0 +1,22 @@
1
+ class WeightedRandom
2
+ extend Rusby::Core
3
+
4
+ rusby!
5
+ def pick(weights, seed)
6
+ sum = 0.0
7
+ left_bounds = []
8
+ right_bounds = []
9
+ weights.each do |item|
10
+ left_bounds << sum
11
+ sum = sum + item
12
+ right_bounds << sum
13
+ end
14
+ number = seed * sum
15
+ weights.each_with_index do |_, i|
16
+ if (number >= left_bounds[i] && number < right_bounds[i])
17
+ return i
18
+ end
19
+ end
20
+ return -1
21
+ end
22
+ end